设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
楼主: 「旅」
打印 上一主题 下一主题

[通用发布] 小旅的脚本入门教程(8.14基础篇完结!)~

  [复制链接]

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

11
 楼主| 发表于 2011-7-30 10:35:21 | 只看该作者
本帖最后由 「旅」 于 2011-8-13 21:58 编辑


扩展38.类变量(难度系数:★★★☆☆ 较难)


观看条件:
已经学过类,知道什么是@xxx、attr_accessor的意思。

内容讲解:
以前一直没讲过类变量,因为这个东西应用的很少,一般制作游戏的人完全不会遇见,但大家可以稍微了解下,说不定有一天会有妙用。

首先,类变量不是实例变量。我们在基础篇讲过的@xxxx是实例变量,而@@xxxx才是类变量。所以,类变量是@@的格式
@@类变量和@实例变量的区别在于他们存在的地方不同,一个是跟随类,一个是跟随实例,请看范例:
  1. # 定义类
  2. class A
  3.   attr_accessor :a
  4.   @a = 100
  5.   @@a = 999
  6.   def a2
  7.     return @@a
  8.   end
  9.   def a2=(a2)
  10.     @@a = a2
  11.   end
  12. end

  13. # 生成实例
  14. jiong1 = A.new
  15. jiong2 = A.new

  16. # 测试
  17. jiong1.a = "我是1"
  18. jiong2.a = "我是2"

  19. p jiong1.a # “我是1”
  20. p jiong2.a # “我是2” ——>两个不一样

  21. jiong1.a2 = "我打酱油"
  22. jiong2.a2 = "我卖炸弹"

  23. p jiong1.a2 # "我卖炸弹"
  24. p jiong2.a2 # "我卖炸弹"——>两个一样
复制代码
因为@@类变量没有attr_accessor可用,我们只好用麻烦些,自己写方法来读取和写入。
范例的大概意思就是,两个实例带入不同的东西,最终修改@a的结果会不同,而修改@@a的结果却是相同的,都是"我卖炸弹"。这是因为@a是实例自己用的,而@@a是两个实例共用的,为什么是共用的?因为它叫做类变量咯,他们都是A类的实例。
所以,不管生成几个实例,只要是修改同一个类的@@类变量,它们最终修改的都是同一个变量。

点评

个人感觉过于抽象化。。。不易于理解。。。话说旅酱高考完这坑还填不。。。  发表于 2012-5-26 23:00
看不懂  发表于 2012-5-17 23:13
回复 支持 反对

使用道具 举报

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

12
 楼主| 发表于 2011-7-30 10:35:30 | 只看该作者
本帖最后由 「旅」 于 2011-8-2 11:09 编辑


扩展39.分歧注意事项(难度系数:★★★☆☆ 较难)


这堂课的内容比较容易,是关于条件分歧一个特别需要注意的细节,如果不知道的话可是会遇上大麻烦的哦。

大家都知道if a or b 或 if a and b的意思,但大家一直会猜错unless a or b 和 unless a and b的含义。为什么呢,让我们来先来看一下下面这个问题。
首先,unless 的触发条件是伪的情况下(也可以说是非、false的情况,都一样)。那么如果我照上面那样写unless a or b,那么是不是代表在a为伪"或"b为伪的情况下,就会触发unless。那么我们试一下:
  1. a = true
  2. b = false
  3. unless a or b
  4.   p "你好啊"
  5. end
  6. exit
复制代码
测试完毕,大家会发现,根本就没有显示”你好啊”。那不是a为伪,或b为伪就可以触发吗,这里的b就是伪的呀,这是为什么呢。呵呵所以说问题来了。

首先我告诉大家,这个脚本没有问题,但只是大家理解的不够透彻。
or这个东西的作用,就是根据左右的真伪值(true和false),如果其中有一个为true,那么就返回true,只有全部都不是true的时候,才返回false。
也就是说,我们上面的那段脚本,就等于写出unless true,那么永远都不可能会执行了。
同样的情况也发生在unless a and b的身上。

所以unless a and b的中文意思其实是a"或"b为false时触发条件,而unless a or b的中文意思其实是a"和"b为false时触发条件
所以说有点时候理解脚本不能单纯从表面来理解。恩这堂课大家大概知道了解什么意思就行了。
只用记住,遇到unless,用中文解读代码意思时,就要把or和and倒过来用,这样就不会遇到问题了。

回复 支持 反对

使用道具 举报

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

13
 楼主| 发表于 2011-7-30 10:35:39 | 只看该作者
本帖最后由 「旅」 于 2011-8-24 15:48 编辑


09.方法和函数(难度系数:★★★☆☆ 较难)


今天我们来学习"方法"。所谓方法是一种指令,我们曾经学过的exit、p、print都是方法的一种。

方法的定义:
我们先来看看怎么样定义方法。方法只需要def~end的格式就可以定义了,如下:
  1. def 方法名
  2.   方法内容
  3. end
复制代码
方法名称的命名方法,基本上和局部变量有相同的限制。也能在开头使用大写字母,但不推荐方法命名时使用。另外,作为方法命名的例外,在名称的最后还可以添加 ? 或 ! 符号。

我们来随便定义一个方法:
  1. def a
  2.   p 1
  3. end
复制代码
这样我们就定义好方法了,接着我们来调用方法,(调用方法也就是执行方法的内容)
  1. def a
  2.   p 1
  3. end
  4. a
复制代码
调用方法的方式很简单,直接把方法名写上去就行了。测试,工程显示了1,说明我们成功地调用了方法。

参数:
带有参数的方法,定义如下:
  1. def jiong(a)
  2.   p a
  3. end
  4. jiong(10)  # 显示10
  5. jiong("你好吗") # 显示"你好吗"
复制代码
这个方法可以根据在括号()里写入的数值,p出来。在这里,定义时的a被称为临时参数,而调用时写入的10和"你好吗"则称为实参数。在调用方法时,实参数会代入到临时参数中。
参数可以同时有多个,只需要用 , 逗号隔开就可以了。(注意不要写这个 , 而是 , 才对)
  1. def jiong(a,b,c,d)
  2.   p a + b + c + d
  3. end
  4. jiong(1,2,3,4) # 显示10
复制代码

默认参数:
定义方法时就已指定且使用时可以省略的参数称为默认参数。默认参数是在临时参数后面加上符号 = 来指定的。事先设定好了默认参数,在使用方法时未指定括号 () 内实参数数值的情况下,临时参数就会自动代入默认参数数值。
  1. def a(n = 6)
  2.   p n
  3. end
  4. a # 显示6
  5. a(5) #显示5
复制代码
默认参数同样可以指定多个参数,不过要注意一点,默认参数必须在普通参数的最后~!
  1. def jiong(c,a=2)
  2.   p a + c
  3. end
  4. jiong(2) # 显示4
复制代码
  1. def jiong(a=2,c) # 提示错误!!
  2.   p a + c
  3. end
复制代码


方法重定义:
如果在脚本中定义了两次同个方法,那么调用时就会选择最接近的那个定义
  1. def jiong
  2.   p 2
  3. end
  4. jiong # 显示2

  5. def jiong
  6.   p 999
  7. end
  8. jiong # 显示999
复制代码
重定义专业点讲可以叫做重写,它是导致脚本冲突的重要原因之一,大家要记住了。

方法的中断:
如果想要中断方法的运行,可以使用return这个指令。(注意:方法中断是return,而循环中断是break)
让我们看下面的例子:
  1. def jiong(a)
  2.   if a == 1
  3.     return
  4.   end
  5.   p a
  6. end

  7. jiong(1) # 什么都不显示

  8. jiong(4) # 显示4
复制代码
这个例子就是说当a为1时,执行return指令,正因为执行了return,所以第一个调用没有任何的显示。

函数
在原来的脚本入门教程里,作者直接把方法叫做函数了,但如果考虑到数学里所讲的函数的话,那么这个说法就太奇怪了。以我个人的看法吧,一般只有那些专门用于计算的方法才称得上是函数。

返回数值
在学习函数前,我们先来学习返回数值的方法return。没错,这个正是我们前面讲的那个return,它不单可以中断方法运行,同时它也可以返回指定的数值。范例如下:
  1. def jiong
  2.   return 1
  3. end
  4. p jiong # 显示1
复制代码
好了,返回数值成功,调用jiong时1被返回过来了。
返回数值
是指把一个数值放在return的右侧,接着它会被传送到调用方法的地方

要注意一点,这里p jiong的jiong是方法,但似乎在某个地方也看到类似的格式,没错,
  1. jiong = 1
  2. p jiong # 显示1
复制代码
它就和局部变量的格式完完全全一样。所以我们要注意下面这种情况,
  1. def jiong
  2.   return 1
  3. end

  4. jiong = 2

  5. p jiong # 显示2
复制代码
如果刚好同时方法名和局部变量名都是一模一样的话,那么脚本只会用局部变量。

函数的使用:
学习好了返回数值我们正式开始学习函数。我上面说过了,一般只有专门用于计算的方法才称为函数。例如我们想知道某数量商品的价格,可以先写一个这样的函数:
  1. def zongjia(danjia,shulian)
  2.   return danjia * shulian
  3. end
复制代码
(为了方便理解,上面函数名叫做zongjia总价,参数分别是danjia单价、shulian数量)
写好这个函数后我们来调用,
  1. p zongjia(10,20) # 显示200
复制代码
这样一个函数就完成了。也许看后有的同学开始纳闷了,"我直接10*20得出结果不就好了?"。这样想就不对了,因为有些真正的函数它的内容格外复杂,是用了数条物理公式最终才得出的结论,例如:
  1. def d(a,b,c)
  2.   return Math.sqrt(Math.sqrt(a**2 + b**2)**2 + c**2)
  3. end
复制代码
这个是用来算出长方形对顶角间距离的函数,如果是每次都那么麻烦去写一次的话,估计有一堆同学要挂了。但我们现在只需要,
  1. p d(1,2,3)
复制代码
很方便吧。所以写程序永远记住一点,一劳永逸(写了大型脚本就会体会到)。另外写成函数的格式还方便观看,特别是在脚本写多时可以避免很多麻烦。

点评

我就不吐槽数量的拼音是shuliang了  发表于 2012-3-17 17:50
啊,是的~~感谢提醒~~~  发表于 2011-7-31 10:04
默认参数那一节第一个例子调用的应该是a和a(5)吧?  发表于 2011-7-31 09:52
回复 支持 反对

使用道具 举报

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

14
 楼主| 发表于 2011-7-30 10:35:47 | 只看该作者
本帖最后由 「旅」 于 2011-8-13 22:37 编辑


10.类和实例(难度系数:★★★☆☆ 较难)


今天我们来学习类的定义。注意一下,在默认脚本里,除了最后一个Main不是外,其余全部的脚本都是类,这足以说明类这样东西在脚本中的重要地位。

类的定义:
我们先来学习怎么定义类吧。定义类很容易,和定义方法的def
~end相似,定义类是class~end,如下
  1. class Aaaa
  2. end
复制代码
这样我们就定义一个类了。注意,方法名和局部变量名开头是小写,但类名的开头必须是大写哦,而后面就无所谓了

类的方法:
我们前一节课已经学过方法了,而方法这样东西,除非特别用途,他一般都是定义在类中的,如下:
  1. class A
  2.   def jiong
  3.     p 1
  4.   end
  5. end
复制代码
只要把方法放到类中,这样的话方法就属于类了。

调用类中的方法:
  1. class A
  2.   def jiong
  3.     p 1
  4.   end
  5. end

  6. a = A.new # 生成类的实例,并带入局部变量a
  7. a.jiong # 调用方法,显示1
复制代码
在调用前我们需要先生成类的实例,这是因为类就像一个大楼的规划图,而规划图终究是规划图,他不可能可以代替实物的功能,你必须把它建起它才能让人们住进去,也就是只有实物才能真正完成想要做到的事情。在这里,A.new就是按照类的定义建立起的实物,称之为实例(当然因为A.new代入到局部变量a里了,所以你可以称被代入后的a为实例)。

总之使用类,就必须先生成它的实例,实例只需 类名.new 就可以生成了接着调用方法, 变量名.方法名 就可以了

实例变量:
属于实例专用的变量称为实例变量或实变量,以@开头的变量,自动作为实例变量使用。局部变量只有在def~end等结构里才会有效,然而实例变量的话,只要他的实例存在,没有被系统清除,那实例变量就会一直存在了。另外在同一个实例的方法中可以一起共享哦。
  1. class A
  2.   def jiong
  3.     @rpg = "你好吗?"
  4.   end
  5.   def jiong2
  6.     p @rpg
  7.   end
  8. end
  9. a = A.new

  10. a.jiong2 # 显示nil

  11. a.jiong
  12. a.jiong2 # 显示"你好吗?"

  13. p woshiceshide # 局部变量没有赋值,出错!!
复制代码
(注意这里的nil是空的意思,也就是什么都没有。变量在赋值前,都是nil的。不过局部变量和实例变量有不同,局部变量在赋值前调用会出错,而实例变量则不会。)
上面调用jiong方法后,@rpg被赋予"你好吗?"这个字符串,所以第二次调用jiong2时,就显示"你好吗?"而不是nil了。

初始化:
我们使用类时,经常会用到许多变量,然而如果没有对变量进行初始化的话,容易发生下面的错误:
  1. class A
  2.   def plus_hp(hp)
  3.     @hp += hp
  4.   end
  5. end
  6. a = A.new
  7. p a.plus_hp(100) # 出现错误!!!
复制代码
因为@hp这时还只是nil,nil是不能进行+=这样的加法运算的,所以当然就会发生错误咯。
  1. class A
  2.   def initialize(hp=1000)
  3.     @hp = hp
  4.   end
  5.   def plus_hp(hp)
  6.     @hp += hp
  7.   end
  8. end

  9. a = A.new
  10. p a.plus_hp(100)
复制代码
我们可以用initialize (必背!) 这个方法名,它的中文意思就是初始化,当你在 .new 时,就会自动执行这个方法。另外initialize和普通方法一样,可以为它加上参数。

父类
往往为了便于阅读、修改等理由,你都可以用父类这样东西。例如你原本定义了一个叫做Car(汽车)的类,而你又打算定义Rolls_Royce(劳斯莱斯)和Benz(奔驰)这两个类,那么可以把Car作为父类,劳斯莱斯和奔驰作为子类,例子如下:
  1. class Car
  2.   def initialize
  3.     @luntai = 4
  4.     @ranliao = "汽油"
  5.   end
  6.   def jiong
  7.     p @luntai
  8.   end
  9. end

  10. class Rolls_Royce < Car
  11.   def initialize
  12.     super
  13.     @jiage = 100000000
  14.     @shuoming = "很昂贵的车"
  15.   end
  16. end

  17. class Benz < Car
  18.   def initialize
  19.     super
  20.     @jiage = 1999999
  21.     @shuoming = "很拉风的车"
  22.   end
  23. end
复制代码
首先我们定义Car,因为汽车嘛,都是luntai(轮胎)有4个,ranliao(燃料)是汽油,这凡是汽车都具有的特性,所以我们没必要每种车子都废话一次。
往下看,劳斯莱斯和奔驰都用了 < Car 这个东西,它便是用来指明自己的父类的。指定好后,我们就可以直接使用父类的方法了,如下:
  1. benz = Benz.new
  2. benz.jiong # 显示4 (jiong虽然只有在父类Car中定义,但子类却也可以调用它)
复制代码


不过有的同学注意到,父类和子类都定义了initialize方法,按照我们之前学的,那样的话父类的方法就被子类给覆盖掉了。的确,不过我们可以使用super,它会自动调用与该子类方法名相同的父类方法名的内容
  1. class A
  2.   def initialize(jiong)
  3.     p jiong
  4.   end
  5. end

  6. class B < A
  7.   def initialize
  8.     super(100)
  9.     p 999
  10.   end
  11. end

  12. b = B.new # 显示100,显示999
复制代码
而且super还可以写上参数哦。
回复 支持 反对

使用道具 举报

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

15
 楼主| 发表于 2011-8-1 11:04:56 | 只看该作者
本帖最后由 「旅」 于 2011-8-17 22:18 编辑


11.类的属性(难度:★★☆☆☆ 容易)


外部使用实例变量:
我们前一节课有讲解过实例变量,也就是以@开头的那种变量。我们讲过,它有一个特点,和局部变量只可以在def~end等结构中存在不同,它可以在在类的全部方法中共同享用。但它有一个问题,就是外部不能直接写入或读取它,如下:
  1. class A
  2.   def initialize
  3.     @jiong = 1
  4.   end
  5. end

  6. a = A.new
  7. p a.jiong # 出错
复制代码
  1. class A
  2.   def initialize
  3.     @jiong = 1
  4.   end
  5. end

  6. a = A.new
  7. a.jiong = 22 # 出错
复制代码
我们如果想要从外边写入或读取实例变量,就必须为它建立一个方法:
  1. class A
  2.   def initialize
  3.     @jiong = 1
  4.   end
  5.   def jiong # 读取方法
  6.     return @jiong
  7.   end
  8.   def jiong=(jiong) # 写入方法
  9.     @jiong = jiong
  10.   end
  11. end

  12. a = A.new
  13. a.jiong = 22
  14. p a.jiong # 显示22
复制代码
这次我们成功地写入和读取到@jiong这个实变量了。(以前讲过return是返回数值,所以它可以把实变量返回出来)

不过如果单单为了实现写入或读取一个变量的功能,我们就需要写两个方法,那也未免太麻烦了。所以我们平时写的时候可以直接用attr_accessor这个东西,是不是简洁很多?
  1. class A
  2.   attr_accessor :jiong
  3.   def initialize
  4.     @jiong = 1
  5.   end
  6. end

  7. a = A.new
  8. a.jiong = 22
  9. p a.jiong # 显示22
复制代码
attr_accessor可以帮我们直接定义写入方法和读取方法,可以省去很多时间的哦。
不过有的时候只需要定义写入方法的话,则是用attr_writer;只是读取方法的话,是attr_reader

类的属性:
我们定义类这样东西,往往都是将具体的事物进行了脚本化。例如先前说的Car,就是把车的概念转移到脚本上来。而车的一些数据,例如4个轮胎,叫做"奔驰",这在脚本里都可以叫做类的属性。
方便理解的话,配合了写入或读取方法的实例变量,都可以称为类的属性。

点评

OK改好了~  发表于 2011-8-17 22:20
推荐使用【实例变量】这个翻译……  发表于 2011-8-17 21:31
回复 支持 反对

使用道具 举报

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

16
 楼主| 发表于 2011-8-1 11:09:50 | 只看该作者
本帖最后由 「旅」 于 2011-8-17 22:21 编辑


12.深入认识类(难度系数:★★☆☆☆ 容易)


内部类:
先让我们打开RM的F1帮助文件-RGSS参考-标准库-内部类-Object (好长orz)。打开后大家会看到一堆的英文,不要太在意,我们只需先知道下面这几样东西:
类名
中文
实例
01.NilClass
空的类
nil
02.FalseClass
伪的类
false
03.TrueClass
真的类
true
04.Range
范围
1..2 1…5
05.String
字符串
"大家你们好吗"
06.Integer (父类Numeric)
整数(整型)
100
07.Float  (父类Numeric)
浮点数
100.9999
首先我们看到右侧的实例,没错,100大家你们好吗这些都是左边那些类的实例,这点大家要记清楚了。
正因为它们都是实例,按照我们以前学习类时的知识,只要生成了实例,就可以调用类中有定义的方法了。(包括父类中的方法)它的方法我们都可以在帮助文件中找到,例如,
  1. a = -999 # 生成整数的实例,并代入a
  2. p a.abs # 显示999
复制代码
这里的abs是整数Integer的父类Numeric里的一个方法,它可以取得数的绝对值(也就是会把负数变正数,而正数不变)

我们再来试试String里的方法,这里我们用它的最后一个方法upcase(将所有字母都变为大写形式)
  1. a = "我来自66rpg"
  2. p a.upcase # 显示"我来自66RPG"
复制代码
不出我们所料,测试很成功~!
另外,细心的同学应该发现了一个问题,字符串类里面有分upcase和upcase!两种方法,他们都可以返回字母改为大写形式后的字符串,但是……
  1. a = "我来自66rpg"
  2. p a.upcase # 显示"我来自66RPG"
  3. p a # ——>还是"我来自66rpg"
复制代码
  1. a = "我来自66rpg"
  2. p a.upcase! # 显示"我来自66RPG"
  3. p a # ——>变成了"我来自66RPG"
复制代码
(注意范例的大小写)也就是带有!的方法,会真正地永远地改变实例的内容

大家可以自己再试试这几个类中的其他方法,有一些看不明白的方法可以无视(因为制作游戏的话几乎没有接触那些东西),而有一些重要的我以后也会讲到。好了这节课就到这了^-^

点评

改好了~~  发表于 2011-8-17 22:21
表格对于字符串实例的引号有问题。  发表于 2011-8-17 21:32
回复 支持 反对

使用道具 举报

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

17
 楼主| 发表于 2011-8-1 11:27:42 | 只看该作者
本帖最后由 「旅」 于 2011-8-2 11:19 编辑


13.显示图片(难度系数:★★☆☆☆ 容易)


今天让我们稍稍轻松一下,来学习显示图片的脚本吧。

Graphics 模块
首先我们如果要显示图片的话,需要调用Graphics模块中的update(中文:更新)方法。因为模块这个东西用得比较少,所以暂时我们不详细讲解。总之调用模块里的方法可以直接 模块名.方法名 就行了。这和类需要生成实例才可以调用方法相比,就简单多了:
  1. # 类方法的调用:较麻烦
  2. a = A.new
  3. a.xxxx
复制代码
  1. # 模块方法的调用:容易
  2. Graphics.update
复制代码

好了抛开模块的事情,继续学习显示图片。
  1. loop do
  2.   Graphics.update
  3. end
复制代码
请大家看看上面,这段脚本是指不停地调用update方法,因为游戏画面总是需要更新的,所以要不断调用它。这个方法可以做到「处理游戏画面,并前进1帧(0.05秒)」的效果,处理游戏画面就是要显示什么它来负责;前进1帧的意思就和等待1帧一样。例如:
  1. p 1
  2. for i in 1..20
  3.   Graphics.update
  4. end
  5. p 2
复制代码
在这里显示1后等待1秒才显示2,所以证明游戏的等待就是由它来完成。

  1. loop do
  2.   Graphics.update
  3. end
复制代码
继续回到这段脚本。因为现在我们根部没有生成图片,所以运行上面的示例后什么也没有显示。这只是个反复显示乌黑画面的处理而已。下面我们就来学习实际显示图片的方法吧。

精灵和位图
向刚才的脚本中加入 2 行,如下所示。如果画面左上角显示出小恶魔的图片就表示成功了。
  1. devil = Sprite.new
  2. devil.bitmap = Bitmap.new("Graphics/Battlers/075-Devil01")

  3. loop do
  4.   Graphics.update
  5. end
复制代码
这里出现了Sprite(精灵)和Bitmap(位图)两个新类。Sprite是在游戏画面上显示某些图片的基本概念即精灵的类,Bitmap是精灵传输元位图本身内容的类。具体它们是做什么的,我们以后再讲,现在只需知道显示图片需要用到它们就行。
(另外,指定 Bitmap.new 参数的路径名,分隔符号是使用 / 而不是 \ 这点要特别注意)

属性
很多类都有属性,Sprite类也不另外。我们可以通过写入方法修改它的坐标变量x和y。
  1. devil = Sprite.new
  2. devil.bitmap = Bitmap.new("Graphics/Battlers/075-Devil01")
  3. devil.x = 320
  4. devil.y = 240

  5. loop do
  6.   Graphics.update
  7. end
复制代码
这样写的话,小恶魔就会出现在中间附近了。

让我们进一步加工一下。
  1. devil = Sprite.new
  2. devil.bitmap = Bitmap.new("Graphics/Battlers/075-Devil01")
  3. devil.ox = devil.bitmap.width / 2
  4. devil.oy = devil.bitmap.height / 2
  5. devil.x = 320
  6. devil.y = 240

  7. loop do
  8.   Graphics.update
  9. end
复制代码

这里 ox、oy 属性的设定,更改了精灵的原点。这和 RPGXP 的事件指令”显示图片”中选择”左上”、”中心”是一样的概念。默认状态下,原点在图片的左上。赋值运算符的右侧调用的 width、height 是 Bitmap 类的方法,作用是分别取得图片的宽和高。这里使用了其值的 1/2,也就是把图片的中心点设定为原点。


总之,这样修改就可以让小恶魔完完全全出现在中间了。好了,显示图片先讲到这里。

点评

不是吗?0 0  发表于 2011-8-17 22:22
“总之调用模块里的方法可以直接 模块名.方法名 就行了。”驳论……  发表于 2011-8-17 21:34
这篇写的不错。。  发表于 2011-8-3 11:55
0 0如果F1讲得好,我就会直接照搬~~~  发表于 2011-8-2 19:21
- -|小恶魔那段莫非直接照搬F1了吗............  发表于 2011-8-2 12:56
回复 支持 反对

使用道具 举报

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

18
 楼主| 发表于 2011-8-2 11:21:54 | 只看该作者
本帖最后由 「旅」 于 2011-8-14 11:21 编辑


14.数组(难度系数:★★☆☆☆ 容易)


想一起处理多个数据就要使用数组。

数组的生成
在 [] 符号中间排列多个单元就生成了一个数组。如下例所示。
  1. a = ["艾力克斯","布莱恩","卡罗来"]
复制代码
上述程序建立了一个包含 "艾力克斯"、"布莱恩"、"卡罗来" 这三个字符串单元的数组,并把这个数组代入变量 a 为其赋值。
要取出数组中数据,如下例所示。
  1. a = ["艾力克斯","布莱恩","卡罗来"]

  2. p a[0]          # => "艾力克斯"
  3. p a[1]          # => "布莱恩"
  4. p a[2]          # => "卡罗来"
复制代码
上述中,a[0] 和 a[1] 等各个单元,能和其它变量那样单独使用。这里 0、1、2 那样的数字被称为数组的附加码。附加码不是从 1 开始而是从 0 开始的,这点一定要注意。从 0 开始,单元从左至右依次为 0、1、2 ……。
数组中除了字符串外还可以包含其它数据。而且,使用 p 命令也可以不指定附加码,那样就会显示数组的全部单元。
  1. a = [2000,"艾力克斯",true,1..50]

  2. p a             # => [2000,"艾力克斯",true,1..50]
复制代码
数组单元的重赋值
数组的各单元的使用和普通的变量一样,也能进行变量的重赋值。
  1. a = [10, 20, 30]
  2. a[0] = 100

  3. p a             # => [100, 20, 30]
复制代码
该示例中,首先是建立了一个由 10、20、30 这三个数字单元组成的数组,然后向第一个单元里重赋值代入 100。这时 a[0] 原先的数值 10 就被代入的 100 所代替,显示的结果就更改了。这个处理和普通变量的重赋值是一样的。
指定超过最初数组附加码范围的单元并为之赋值,会自动扩大数组添加新的单元。
  1. a = [10, 20, 30]
  2. a[3] = 40

  3. p a             # => [10, 20, 30, 40]
复制代码
建立数组时只有 3 个单元,现在为在其范围外的 a[3] 赋值,就会自动添加第 4 个单元扩大数组。C 语言等其它语言是不充许这样赋值的,而 Ruby 这种灵活的语言就可以放心添加。
如果跳过范围的话会如何呢?
  1. a = [10, 20, 30]
  2. a[5] = 60

  3. p a             # => [10, 20, 30, nil, nil, 60]
复制代码
中间就会出现 nil 值。这个与 true 和 false 等一样是常量的一种,意思是「什么都没有」。和 true 表示「真」,false 表示「伪」一样,nil 表示「无」。

数组的操作
数组是 Array 类的实例。可以调用这个类定义的方法对数据进行操作。

(可以打开RM帮助文件-RGSS参考-标准库-Object-Array参考方法类型)~~~~





比如,想知道数组的单元数量的话就可以使用 size 方法(当然也可以用它上方的length,它们是一样的)。和 String 类的 size 方法返回字符串字节数相似,Array 类的 size 方法是返回数组的单元数。数组为空时就返回 0。
  1. a = ["艾力克斯","布莱恩","卡罗来"]

  2. p a.size        # => 3
复制代码
想知道数组中是否含有特定的值的话,就要使用到 include? 方法。




  1. a = ["艾力克斯","布莱恩","卡罗来"]

  2. p a.include?("布莱恩")            # => true
  3. p a.include?("小田纯一狼")        # => false
复制代码
第三行中使用 include? 方法,是确认数组中是否含有字符串 "布莱恩"。上例在第一行生成数组时设定有字符串 "布莱恩",所以输出结果为 true(真)。同样第四行是确认数组中是否含有字符串 "小田纯一狼"。然而这个字符串在数组中是不存在的,所以输出结果就为 false(伪)。

数组的循环
使用 for 循环,可以把数组里全部数据都拿出来一遍。
  1. a = ["艾力克斯","布莱恩","卡罗来"]

  2. for s in a
  3.   p s
  4. end
复制代码
这里使用变量 s,循环代入数组 a 中所包含的单元。循环的范围是数组 a 包含的所有单元,按 "艾力克斯"、"布莱恩"、"卡罗来" 的顺序在对话框中显示,最后循环结束。

回复 支持 反对

使用道具 举报

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

19
 楼主| 发表于 2011-8-2 11:22:02 | 只看该作者
本帖最后由 「旅」 于 2011-8-14 11:19 编辑


15.哈希表(难度系数:★★☆☆☆ 容易)


Hash 表是一种和数组比较类似的数据构造形式。

Hash 表的生成
Hash 表也称为关联数组。和数组不同的是,作为取出数值 的主键(相当于数组的附加码),可以使用任意的数据。 在 {} 符号中间排列多个单元就生成了一个哈希表。
  1. a = {"艾力克斯"=>2000, "杰克"=>2003}
复制代码
这个例子中,"艾力克斯" 和 "杰克" 就是取出数值的主 键,2000 和 2003 就是实际的数值。这样, 使用 => 符号把主键和数值连接起来就形成了 Hash 表。
要取出 Hash 表中数据的时候,应按如下操作。
  1. a = {"艾力克斯"=>2000, "杰克"=>2003}

  2. p a["艾力克斯"]        # => 2000
  3. p a["杰克"]            # => 2003
  4. p a["宇佐助"]          # => nil
复制代码
从上例最后一行可以得知,当指定主键不存在时就会返回 nil。
这里是以字符串为主键,当然不使用字符串也可以。作为主键还可以使用整数等其它数据类型,在有很多编号单元的情况下使用哈希表会比使用数组更加方便。
另外,哈希表的反操作,也就是「检查与数值对应的主键」的情况下,在 [] 中写入数值是不能得到其主键的。这里不再多作陈述,该种操作方法我们会在后面特别介绍。

Hash 表数值的添加

实际操作中,Hash 表可以在程序中直接指定数据建立, 亦可以使用先建立一个空的 Hash 表然后向其中添加单元数据等多种方法生成。 生成一个空的 Hash 表只需写入 {} 就行了。
  1. a = {}
复制代码
当然我们也可以用普通生成实例的方法生成,
  1. a = Hash.new
复制代码
这两种生成方法都是一样的。
然后我们来向 Hash 表中添加数值,和数组单元的重赋值完全相同。
  1. a = {}
  2. a["艾力克斯"] = 2000

  3. p a                 # => {"艾力克斯"=>2000}
复制代码

Hash 表的操作

同数组一样,可以调用这个类定义的方法对数据进行操作。比如要从 Hash 表中删除数值的话,就要使用 delete 方法。
  1. a = {"艾力克斯"=>2000, "杰克"=>2003}
  2. a.delete("杰克")

  3. p a                 # => {"艾力克斯"=>2000}
复制代码
想知道 Hash 表中是否含有某个特定主键的情况下,就要使用 include? 方法。
  1. a = {"艾力克斯"=>2000, "杰克"=>2003}

  2. p a.include?("艾力克斯")    # => true
  3. p a.include?("宇佐助")      # => false
复制代码
第三行中使用 include? 方法,是确认哈希表中是否含有主键 "艾力克斯"。上例在第一行生成哈希表时主键设定有 "艾力克斯",所以输出结果为 true(真)。同样第四行是确认哈希表中是否含有主键 "宇佐助"。然而这个主键在哈希表中是不存在的,所以输出结果就为 false(伪)。



Hash 表的循环

在 Hash 类中,有取得全部主键排列的 keys 方法。
  1. a = {3=>6, 4=>10, 5=>15}
  2. p a.keys            # => [5, 3, 4]
复制代码
这样,=> 左侧的主键会全部排列出来。 但 Hash 表中是没有顺序的,所以排列会无顺序可言。

前节中,我们学习了使用 for 循环指定数组的方法。 现在让我们来用 for 循环指定 keys 方法的返回值,作成 Hash 表主键的循环吧。
  1. a = {3=>6, 4=>10, 5=>15}

  2. for k in a.keys
  3.   p k
  4. end
复制代码
运行上例就会按不同顺序显示 3、4、5。

而且,使用 values 方法的话,还能取得 Hash 表全部数值的排列。
  1. a = {3=>6, 4=>10, 5=>15}

  2. for v in a.values
  3.   p v
  4. end
复制代码
运行上例就会按不同顺序显示 6、10、15。



回复 支持 反对

使用道具 举报

Lv3.寻梦者

小柯的徒弟

梦石
0
星屑
1535
在线时间
1157 小时
注册时间
2008-5-24
帖子
3085

贵宾

20
 楼主| 发表于 2011-8-2 11:22:12 | 只看该作者
占楼占楼~ ^o^
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-12-23 11:49

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表