文档库 最新最全的文档下载
当前位置:文档库 › 脚本入门

脚本入门

脚本入门


建立工程
建立组
结束程序
注释
语法和库
在基础篇,将一边完成单个短程序一边解说 RGSS 的基础知识。

首先,来进行开始学习的准备吧。

建立工程首先建立一个工程,把它作为学习脚本入门用的新工程。

脚本是有关游戏实际运行的数据,照原样改动制作完成的工程,一个小小的错误也将引起游戏不能正常运行。因此,推荐使用新建的工程进行学习。

另外,RGPXP 脚本数据是保存在 Data 文件夹内的 Scripts.rxdata 文件中,如果对此文件(或游戏全部数据)已经备份的话,也可以使用既存的工程。

建立组
建立工程后,在主菜单「工具」菜单中选择「脚本编辑器」。

显示脚本编辑器对话框后,在最上面新建一个组。点击右键于弹出菜单中选择「插入」,就建立了一个新的空白组。

组的名称是什么无所谓,可以取个容易理解的,我们这里暂命名为“TEST”。名称的输入在窗口左下方的「名称」里进行。

结束程序
首先,请输入下面的代码。

exit

注意,在 Ruby 中是区分字母大小写的,所以不能输入 EXIT 或 Exit。当然全角文字也不行。请全部以半角的小写字母输入。输入完毕按「确定」键关闭脚本编辑器,运行(游戏测试)看看吧。

运行游戏测试,窗口应该显示一瞬间后立即关闭。总之,在这里写的 exit 是结束程序的命令。

在最上面的 TEST 组中写入 exit,因此程序就此结束。而在后面众多组中编写的脚本都没有执行。以后示例程序都会省略 exit,在实际测试时请在最后一行加入 exit。如果没有加入 exit 而运行测试,就会显示出游戏的标题画面。

注释在 Ruby 中,# 符号后面的一整行文字会认定为注释。

# 后的注释代码不会执行,不会影响到程序的运作,只作为编写者标记的备忘记录来使用。

exit # 结束程序

这和事件指令的「注释」功能相同,是记录程序处理内容的简单说明,使用注释会很容易知道这段脚本是做什么的。即使是自己编写的程序,但时间一长,该段内容是指定做什么处理也会忘记。在脚本的学习和实际操作时,推荐注意多使用注释功能。

还有,作为程序的说明,在后面的学习中脚本会写有很多的注释。但实际操作中没有必要完全仿效其注释的内容。# 以后的文字,可以按实际中最容易理解的说明注释。

语法和库程序语言在结构上大致分为语法和库两种。

所谓语法,就是使用语言记录某些处理时的规则。与中文和英文等自然语言一样,程序语言也有语法。例如条件分歧的语法、循环的语法等等。「# 符号后面的一整行文字认定为注释」这也是语法之一。语言的说法,

狭义上指的就是语法。

所谓库,就是字符串的处理和图片的显示等带有应用功能的语言集。与中文英文等自然语言中的单词和词组的意思相似。学习了英文的语法在使用英文时,增加词汇量(掌握库的使用方法)则是非常必要的。

这个「脚本入门」基础篇是以学习语法为重点。最开始学习时或许会产生「学习语法,到底有什么用」的厌烦感,应用逻辑思维来理解基本语法就能突破最初的屏障,仔细阅读参考程序记住实际的使用方法,其实并不是多么困难的事情。

那么现在就开始吧!



数字的计算
数字
显示数字
计算方法
是关于 Ruby 中数字和计算的基础知识。作为例子将使用计算器那样简单的计算来解说。

数字Ruby 中能使用的数字,包括整数和浮点数两种。

3 # 整数
52 # 整数
-99 # 整数
1.5 # 浮点数
3.0 # 浮点数

所谓浮点数,就是使用小数点以下计算的数。数值相同的话写作 3 是整数,而写作 3.0 即是浮点数。整数计算速度快,如果不需要小数点以下的话尽量使用整数。

显示数字即在画面上显示数字。想显示某些数字时,使用 p 命令。

小写字母 p,半角字符,再把想要显示的数值按顺序输入后换行。今后会出现各种各样的命令和符号,除注释外其它一律使用半角输入。不小心输入全角字符的话,要注意发现错误。

p 3

这个 p 命令可以在排除程序故障时使用,学习显示数字将会是十分有用的。

运行这个程序,会看到在弹出的对话框中显示 3。原本 p 不是显示对话框的命令,但是游戏开发时特殊化的 RGSS 在没有其它输出地点时就会自动显示对话框。

计算方法在 Ruby 上进行计算吧。

p 1 + 1 # 加法
p 10 - 3 # 减法
p 7 * 5 # 乘法
p 24 / 4 # 除法

这样,写上普通算式就会输出计算的结果。+ 和 - 等符号称为运算符。

另外还有乘法的 * 和除法的 /。不熟悉的人,一定要记住这些重点。

优先顺序
和普通的算式一样,* 和 / 计算要优先于 + 和 - 计算。想改变这个顺序就要使用括号 ( ),括号中的算式将会优先计算。

p 2 * 2 + 3 * 4 # => 16
p 2 * (2 + 3) * 4 # => 40
p 2 * (2 + 3 * 4) # => 28

按优先顺序,示例第一行其实是 4+12,第二行是 2*5*4,第三行是 2*14,所以会是不同的计算结果。

括号还可以多层重叠起来(即使是二层三层的情况也是使用同一个符号)。

还有,示例程序的注释中使用 => 符号,主要是表示这行的输出结果。这是为了方便直观的理解而做的说明。

小数点以下的计算
整数除整数的情况下,会省略余数,答案将还是整数。想得

到小数点以下的答案,就要使用到浮点数。除数或被除数至少要有一个是浮点数(明确标明了小数点以下),计算的答案就会是浮点数。

p 15 / 4 # => 3
p 15.0 / 4 # => 3.75
p 15 / 4.0 # => 3.75

余数的计算
求余数(除法的余数),是使用 % 符号。

p 14 % 4 # => 2
p 13 % 4 # => 1
p 12 % 4 # => 0

运行示例第一行的算式,是求 14 除以 4 的余数,就会输出计算结果 2。

乘方的计算
没必要强迫记住,乘方(同一个数指定次数的相乘)是使用 ** 符号。

p 2 ** 4 # => 16

这个示例求 2 的 4 次方,也就是计算 2*2*2*2。



变量
变量的命名
赋值和引用
自运算
全局变量
所谓变量,就是某些数值附上名称。是相对于常量的数据类型。

变量的命名变量命名的管理。我们可以为变量取比如 x 和 y 或者更长的像 level 或 gold 这样的名称。名称的长度没有限制。

变量有几个类型,首先我们来学习最基本的局部变量。局部变量的命名规则有以下几点。其中的第 1 条应该特别注意。

第一个字符必须以小写英文字母或 _(下划线)开头。
第二个字符开始可以使用英文字母、数字或 _(下划线)。
不能使用保留字作变量的名称。
保留字是作为 Ruby 中具有特殊意义的词而被系统所「保留」,所以变量名称不能使用。以下就是系统的保留字。

alias def false nil return unless
and do for not self until
begin else if or super when
break elsif in redo then while
case end module rescue true yield
class ensure next retry undef

除上面列出的保留字以外,其它的词都可以作变量的名称。

赋值和引用在实际中使用变量看看吧。

x = 3
y = 4
p x + y # => 7

第一行和第二行是进行变量的赋值。其中 = 号是赋值运算符。和数学上使用等号表示「左边等于右边」的意思不同,这里表示「左边的变量代入右边的数值」。在上述示例中,第一行 x 变量和第二行 y 变量分别代入数值 3 和 4。

第三行是引用变量 x 和 y。所谓引用就是取得那个变量的数值。变量的计算和数字的计算方法完全一样。这里的 x + y 可以解释为 3 + 4,计算结果就为 7。

另外,引用从未进行赋值的局部变量,就会使程序出现错误。

p zzz # ERROR!!

请记住,变量一定要进行赋值后才能使用。

zzz = 5
p zzz # => 5

这个示例中,第一行变量 zzz 为其赋值代入 5 后,第二行引用。

自运算变量引用自己的数值,并再次代入计算结果称为自运算。

x = 1
x += 7
x -= 3
x *= 2
p x # => 10

第二

行的 x += 7 相当于 x = x + 7,总之就是向变量 x 里加上 7。同样 -=、*=、/=、%= 等也是如此使用。这些运算符就是自运算运算符。

RPGXP 的变量进行自运算计算处理时思考方法都相似。这个示例中第一行是赋值直接代入 1,第二行加上 7,这时 x 的值其实是 8,第三行减去 3,第四行再乘以 2,最后的计算结果就是 10。

全局变量局部变量是暂时使用的变量,只能在函数和类等定义(在后面讲述)内部使用,之外变量就无效。与之相对,在程序任何地方都能引用的就是全局变量。全局变量可以在程序中任何地方使用,名称相同,就必然是同一个变量。

如下面的示例,以 $ 号开头的变量就作为全局变量使用。赋值方法和局部变量完全相同。

$global

虽然在任何地方都能引用,但使用全局变量不一定比局部变量好。全局变量十分强大,胡乱使用恐怕会使程序变得很难懂。请在使用时注意。

字符串
print
为变量赋值
控制码
内嵌表达式
一般来说,由文字连接起来的数据就称为字符串。

print双引号 "" 或单引号 '' 中间的部分,就作为字符串数据使用。

p "RPG Maker XP" # => "RPG Maker XP"
p 'RPG Maker XP' # => "RPG Maker XP"

p 命令会导致双引号和字符串一起输出,所以使用 print 命令代替。

print "RPG Maker XP" # => RPG Maker XP

这次双引号就没有了。p 是按照人们容易理解的形式来显示的命令,所以它会加上双引号来强调字符串。print 和 p 相似,但它只显示字符串本身。

为变量赋值和数字一样,字符串也能代入变量为该变量赋值。

a = "RPG Maker XP"
print a # => RPG Maker XP

字符串也能作加法,字符串加上字符串,就会得到一个连接起来的字符串为答案。

a = "我的 "
b = "RPG Maker XP"
print a + b # => 我的 RPG Maker XP

还可以作乘法,字符串乘以一个整数,就会得到该整数次重复的字符串为答案。

a = "RPG Maker XP"
print a * 2 # => RPG Maker XPRPG Maker XP

控制码字符串中的 \ 符号,是作为一段连续文字中换行等操作使用的特殊文字。比如 \n 是表示换行。

控制码有 \t(Tab)和 \s(空格)等多种代码,另外 \n 表示换行,重叠起来的 \\ 表示 \ 文字本身,这两个一定要记住。

a = "RPG Maker XP"
b = "\\10,290"
print a + "\n" + b # => RPG Maker XP
# \10,290

单引号 '' 中间的字符串,除 \\(\ 符号本身)和 \'(单引号)外不能使用任何的控制码。这在打算原样显示文字本身的情况下使用会十分方便。

print 'RPG Maker XP\n' # => RPG Maker XP\n

\ 符号本身即为

计算机内部的控制码。以后实际字符串操作中应注意正确使用。

内嵌表达式在字符串里面,可以用 #{变量名} 的形式把变量的内容嵌入在字符串当中。

game = "RPG"
print "#{game} Maker XP" # => RPG Maker XP

上述示例里,第一行是为 game 变量赋值代入字符串“RPG”。第二行里面,其中 #{game} 是表示直接嵌入变量 game 的值字符串“RPG”,和后面的“ Maker XP”组合在一起,从而输出一个新的字符串。 RPGXP 的事件指令「显示文章」里,在文章中使用 \V[n] 和 \N[n] 控制码可以把变量的值和角色的名称作为信息嵌入文字中,这个功能好像和那个十分相似。

这个功能,让我们举例来说明在预置脚本中应如何使用。

print("文件 #{filename} 没找到。")

print 的显示内容应附加上括号 (),如果其优先顺序不易混淆的话可以省略(本章 print 的使用示例介绍中全部省略了括号)。预置脚本中基本上都统一使用有括号,所以在这儿也加上一个。

这个是当然,

print("文件 " + filename + " 没找到。")

像这样写也可以,使用内嵌表达式的方法会使读取程序变得很容易。

另外内嵌表达式和控制码一样,在单引号 '' 中间的字符串里使用也会无效。

条件分歧
比较运算符
真伪值
逻辑运算符
if ~ elsif ~ else ~ end
unless ~ end
case ~ end
条件运算符
满足特定的条件与否,之后的动作会根据其不同而改变就叫作条件分歧。

比较运算符在具体地学习处理条件分歧的方法之前,要先记住条件构成中使用的运算符。

下面 6 个运算符称为比较运算符。使用这些运算符,和给予的条件(数字和字符串)相比较,然后返回结果。

== 相等
!= 不相等
< 小于
> 大于
<= 小于或相等
>= 大于或相等

这里一定要注意的是,判断相等的运算符不是 = 而是 ==。像已学习过的那样,所谓 = 符号表示的不是比较而是代入。请注意不要弄混淆了。

真伪值比较运算的运算结果就称为真伪值。有真(正确)、伪(错误)两种情况。

比较后是正确的话为 true 值,是错误的话就为 false 值。请试试看吧。

p ("早安" == "早安") # => true
p ("早安" == "晚安") # => false
p (3 + 1 == 3 + 5) # => false
p (3 + 1 == 2 + 2) # => true

逻辑运算符下面 6 个运算符称为逻辑运算符。

and
&& 「~,与,~」的意思
or
|| 「~,或,~」的意思
not
! 「非~」的意思

英文单词运算符和符号运算符,无论用哪个都是一样的。在预置脚本中运用的主要是英文单词。使用这些逻辑运算符就能指定更加复杂的条件。

p (100 > 77 and 1 + 1 == 2) # => true
p (100 > 77

&& 1 + 1 == 2) # => true

上述示例中,第一行和第二行表示的都是一个内容「100 大于 77 同时 1 + 1 等于 2」。不用说 100 是比 77 大的整数,1 + 1 答案也为 2,两个运算都成立。所以输出结果就为 true(真,正确)。

那么,看下一个算式吧。

p (1 + 1 == 3 or 2 + 2 == 3) # => false
p (1 + 1 == 3 || 2 + 2 == 3) # => false

上述示例中,第一行和第二行表示的也都是一个内容「1 + 1 等于 3 或 2 + 2 等于 3」。很显然,1 + 1 不等于 3,2 + 2 也不等于 3,这样两个运算都不成立。比较运算符 or(||)是只要有一个运算成立就为 ture(真,正确),而这里两个运算全都不成立,所以输出结果就为 false(伪,错误)。

另外,not(!)和上面的例子稍微有些不同, not(!)表示的内容为后面的条件不成立。可以理解为颠倒 true 或 false 的运算符。

p (not true) # => false
p (! true) # => false

上述示例中的内容是「非 true」的意思,所以输出结果为 false。

if ~ elsif ~ else ~ endif ~ end 语句是条件分歧的句法。这个和英文的 if(如果~就)意思相同,表示「如果 if 后面的条件成立的话,就运行下面的处理」的意思。下面示例中的 3~5行就是条件分歧。

a = 20 # 为变量 a 赋值代入 20。

if a >= 10 # 如果 a 为 10 以上的话,
print "big" # 显示 big。
end # 分歧结束。

在条件不满足时也要进行处理的情况下就使用 else,条件不满足但指定另一个条件的情况下就使用 elsif。

a = 7 # 为变量 a 赋值代入 7。

if a >= 10 # 如果 a 为 10 以上的话,
print "big" # 显示 big。
elsif a >= 5 # 除此之外,如果 a 为 5 以上的话,
print "medium" # 显示 medium。
else # 其他,
print "small" # 显示 small。
end # 分歧结束。

unless ~ end与 if 相反,在条件不满足时才进行某些处理的情况下使用 unless 语句。

a = 7 # 为变量 a 赋值代入 7。

unless a >= 10 # 如果 a 不为 10 以上的话,
print "small" # 显示 small。
end # 分歧结束。

case ~ end在条件为特定的变量值进行分歧的情况下使用 case 语句会更方便。

a = 0 # 为变量 a 赋值代入 0。

case a # 分歧开始。
when 0 # 当 a 为 0 时,
print "零" # 显示 零。
when 1 # 当 a 为 1 时,
print "壹" # 显示 壹。
when 2 # 当 a 为 2 时,
print "贰" # 显示 贰。
end # 分歧结束。

把第一行 a = 后面的 0 改为 1 和 2,然后再来看看分歧的

结果吧。当 a 代入 1 时会显示“壹”,代入 2 时会显示“贰”。

条件运算符使用符号 ? 和 : 也是运算符形式的条件分歧语句。

a = 3

p (a >= 10 ? "big" : "small") # => "small"

这个示例的意思是,变量 a 的值在 10 以上的话就显示 "big", 9 以下的话就显示 "small"。条件运算符的语法是「条件 ? 真时的值 : 伪时的值」。上述的条件是 a >= 10,真时的值为 "big",伪时的值为 "small",会根据条件是否满足来决定使用 ? 或 : 的值。

当然使用 if 语句也能完成同样的事情。

a = 3

if a >= 10
p "big"
else
p "small"
end

使用 if 语句的语法会像上面写的那样,但是使用条件运算符语句会更加简洁。该语句在当前的脚本中也使用得很多,所以最好事先记住。



循环
while ~ end
变化范围
for ~ in ~ end
loop do ~ end
break
next
重复进行特定的处理就要使用循环。

while ~ end在满足特定条件期间进行循环的情况下使用 while 语句。

a = 0 # 为变量 a 赋值代入 0。
i = 1 # 为变量 i 赋值代入 1。

while i <= 5 # 当变量 i 为 5 以下时循环开始(重复以下处理),
a += i # 变量 a 加上 i 的值。
i += 1 # 变量 i 的值增加 1。
end # 循环结束。

p a # 显示计算结果。

这个示例是求从 1 到 5 这五个数字总和的程序。在这里,变量 i 是用来产生从 1 到 5 这五个数字用的。当然变量名也可以不用 i,一般情况下循环处理用的变量会使用 i、j、k 为名称。

那么,这个程序最重要的是 i += 1 这行。如果没有这行 i 的值永远为 1,而 i <= 5 的条件也会一直满足,就会成为无限循环。因此,这里每次都向 i 加上 1 使得 i 的值依次变为 2、3、4、5、6 从而使得循环结束。

变量 a 和 i 的数值变化,如下表所示。

循环 a 的值 i 的值
初始状态 0 1
1 次后 1 2
2 次后 3 3
3 次后 6 4
4 次后 10 5
5 次后 15 6

循环 5 次后,在 a 的数值里面实际上进行了 1+2+3+4+5 的计算,i 的值也超过了 5 而执行 end 使得循环结束。

然后以 p 命令显示最终 a 的值,就会显示出答案 15。

变化范围数值的范围,例如类似于「从 1 到 5」这样的概念就称为变化范围。

1..5

上述示例表示「从 1 到 5」的意思。使用 .. 运算符,就能作成一个变化范围。

而且,使用 ... 运算符也可以。

1...5

和 .. 不同的是「不含最后一个数」。所以,这种情况实际上表示的是「从 1 到 4」的意思。

for ~ in ~ end想在变化范围表示的范围内循环的情况下使用 for 语句。

a = 0 # 为变量 a 赋值代入 0。

for i in 1..5 # 变量 i 的值按从 1

到 5 的范围变化,
a += i # 变量 a 加上 i 的值。
end # 循环结束。

p a # 显示计算结果。

这个示例和使用 while 语句的示例完全相同,也是求从 1 到 5 这五个数字总和的程序,但比使用 while 的情况更加简洁。在 while 中变量 i 加上 1 表示的是从 1 到 5 的范围,然而在 for 中是用变量 i 按「从 1 到 5 的范围」的顺序代入来表示。表面看起来不同,但实际上进行的是意思完全相同的处理。

Ruby 中有许多语法,循环中也存在各种各样不同的方法。在不同语法使用中,请按照这个示例提示的「让编写更简便」的方式来思考。实际上,如果理解了条件分歧和循环的话,就能进行大部分逻辑运算了。

loop do ~ end未指定循环次数和条件的情况下,也就是想进行无限循环时使用 loop 语句。这个与 while 和 for 语句的性质稍微有所不同,一般情况下没有必要注意。

i = 0 # 为变量 i 赋值代入 0。

loop do # 循环开始。
i += 1 # 变量 i 的值增加 1。
p i # 显示变量 i 的值。
end # 循环结束。

这个示例是「一边把 i 的值加上 1,一边显示 i 的值」的程序,没有结束条件。一旦运行的话就会连续显示 1、2、3……。如果这种对话框不断显示的话,就算要结束程序也是不可能的,只能按着 F12 键不放强行关闭对话框,并点击右上方的结束按钮关闭程序。

break想中途中断循环就要使用 break 命令。

i = 0 # 为变量 i 赋值代入 0。

loop do # 循环开始。
i += 1 # 变量 i 的值增加 1。
if i == 5 # 如果变量 i 的值为 5 的话,
break # 中断循环。
end # 条件分歧结束。
p i # 显示变量 i 的值。
end # 循环结束。

上述示例在程序中加上了「i 等于 5 的就中断循环」的条件。运行该程序,显示 1、2、3、4 就结束了。

break 即使在 while 和 for 等其它方法作成的循环中也能使用。

next在不中断循环的情况下,跳过本次循环而进入下一次循环时使用 next 命令。

for i in 1..5 # 变量 i 的值按从 1 到 5 的范围变化,
if i == 3 # 如果变量 i 的值为 3 的话,
next # 进入下一次循环。
end # 条件分歧结束。
p i # 显示变量 i 的值。
end # 循环结束。

运行这个示例,会显示 1、2、4、5。



函数
函数的使用
函数的定义
参数
默认参数
函数的重定义
数字的计算和字符串的显示等,能够进行某种处理的被命名的功能称为函数。

函数的使用我们

一直在使用的 exit、p、print 命令其实也是函数的一种。

学习自定义函数的方法前,让我们像函数那样来使用函数吧。先介绍生成随机数的 rand 函数。

p rand(100)

这个示例是每次运行都会显示出(0~99)中的任意一个随机数字的程序。rand 函数是从 0 到指定整数这个不大的范围中随机选取一个数字并返回的函数。这个「指定的值」就称为参数。参数通常在函数名称后面的括号 () 内指定。上面示例里 100 就是 rand 函数的参数。参数如不直接指定数值的话,还可以像下面的示例那样使用任意的运算。

x = 10
y = 20
p rand(x + y) # 等同于 p rand(30)

与参数相反,函数将原始数值进行处理后返回的结果数值称为返回值。也就是说,rand 函数的返回值是在特定范围内的随机数值。函数的返回值可以像普通数字和变量那样被使用。

p rand(6) + 1

上面示例的意思是 rand 函数的返回值加上 1,并显示其计算结果。rand 函数在给予的参数为 6 的情况下返回值为 0 到 5 范围内的任意一个数,所以再加上 1,就像丢骰子一样随机显示一个 1 到 6 范围内的数值。

像 exit 和 rand 那样的函数已预先被系统定义,所以称为系统函数。

函数的定义函数的定义是从 def 开始到 end 结束。具体的语法如下所示。

def 函数的名称
函数的内容
end

函数名称的命名方法,基本上和局部变量有相同的限制。也能在开头使用大写字母,但不推荐函数命名时使用。另外,作为函数命名的例外,在名称的最后还可以添加 ? 或 ! 符号。

比如,先前的 rand(6) + 1 处理可以定义为 dice 名称的函数,我们下面就来进行。这样定义了该函数,从此以后只要写 dice 就会得到一个 1 到 6 的随机数字。

def dice
return rand(6) + 1
end

p dice # 等同于 p rand(6) + 1

这里的 return 就是结束函数处理的命令。函数可以考虑为 RPGXP 的公共事件,而 return 就是相当于「中断事件处理」的意思。return 右侧所写的运算,就是该函数的返回值。在中途中断函数的情况以外还可以省略 return,这大概会更方便吧。预置脚本中也是这样,大多数情况下都省略了 return 没写。

参数含有参数的函数,如下面示例那样定义。

def abs(x)
if x < 0 # 如果 x 小于 0 的话,
return -x # 结束函数,返回值 -x。
else # 除此之外,
return x # 结束函数,返回值 x。
end # 分歧结束。
end

p abs(-3) # => 3

这个是返回指定参数数值绝对值的函数。这里「指定参数数值」暂时定义为 x。这个 x 称为临时参数。在函数内部使用有条件分歧,x 小于 0 时(为负数)返回值 -x,除

此之外(为 0 以上的整数)返回值 x。最后一行是指定参数为 -3 的实际情况下使用函数,其结果用 p 函数输出。与 x 为临时参数相比,这儿的 -3 称为实参数。

顺便讲一下,所谓绝对值是数学上提出的概念,是表示到原点(上述情况可以认为是 0)距离的数值。-3 也好 +3 也好,原点为 0 的情况下,每个到 0 的距离值都为 3。

含有多个参数的函数也能定义。多个参数要用逗号“,”分开来指定。

def sum(x, y)
return x + y # 结束函数,返回值 x + y。
end

p sum(2, 3) # => 5

这个是返回指定参数两个数值之和的函数。当然实际中写成 2 + 3 更快更容易,一般不会定义这样简单的函数。这只是说明语法的示例。

实际中参数省略括号 () 也能使用。

默认参数定义函数时就已指定且使用时可以省略的参数称为默认参数。默认参数是在临时参数后面加上符号 = 来指定的。事先设定好了默认参数,在使用函数时未指定括号 () 内实参数数值的情况下,临时参数就会自动代入默认参数数值。

def dice(n = 6)
return rand(n) + 1
end

p dice # 等同于 p dice(6)

上述示例中未指定参数,使用函数时会返回一个 1~6 的随机数字,然而指定参数的话,就能更改随机数字的最大值。比如,使用 dice(8) 就会返回一个 1~8 的随机数字。

多参数函数同样能够指定各个默认参数,这样使用时就可以省略。

函数的重定义下面的示例中,hello 名称的函数被重复定义了 2 回。

def hello
return "您好"
end

def hello
return "晚安"
end

p hello # => "晚安"

在 Ruby 中,函数名称重复的话不会出现错误。这种情况下系统会认定后面定义的函数有效,而先前的定义就无效了。



对象
对象和类
方法
父类
Ruby 是面向对象的语言。这里,所谓对象可以解释为任何东西。

对象和类Ruby 所使用的一切数据就称为对象。

3 # 整数对象
1.5 # 浮点数对象
"Ruby" # 字符串对象
1..10 # 范围对象

而对象的种类就称为类。比如字符串对象是属于 String 类,范围对象是属于 Range 类。关于 Ruby 中所有类的详细介绍,见 RGSS 参考 中的 内部类 部分。

要强调特定类所属的对象,有时使用实例这种说法。所谓类可以说是其所属对象的描述。大的设计方案都有很多类,决定对象的动作。对象必定是属于哪个类的。因此,「属于这个类的对象」也可以说成是「这个类的实例」。

方法尝试着看看 String 类的部分吧。现在或许不太了解其中的意思,但不用太介意。实际中自已编写脚本时将会经常参照这个参考,有必要提早有所了解。

看到方法

栏下方列出的项目了吧。这些就是该类所属对象专用的函数即方法。

方法列表中有个名称为 size 的项目。使用这个看看吧。

a = "Ruby"

p a.size # => 4

String 类的 size 方法,是返回字符串字节数的方法。这里所说的「字节」指的是容量的意思。比如半角英文字母 1 个字符就是 1 个字节。"Ruby" 这个字符串是由 4 个字母组成所以返回的字节数就是 4(顺便说一下,全角的 1 个字符等于 3 个字节。在中国使用的是 gb2312 文字编码其 1 个全角字符等于 2 个字节,而 RGSS 使用的是 UTF-8 文字编码)。

再来试试这个吧。把字符串转换为大写字母的 upcase 方法。

a = "Ruby"

p a.upcase # => "RUBY"

上面示例中,调用对象的方法时于变量名称后面会加上符号“.”,在其后面记述要调用的方法。而操作的对象称为作用实例。这里 a.upcase 中的 a 就是作用实例。

但是,对字符串以外的对象调用 String 类的方法比如 upcase 方法的话会怎样呢?

a = 3

p a.upcase # ERROR!!

这样会出现错误。因为 3 是一个整数对象属于 Fixnum 类,而 upcase 在 Fixnum 类的方法中没有定义。

还有,没有必要完全记住这些方法的名称。在对字符串进行某些操作时要使用 String 类的方法,直接打开 GRSS 参考进行查找会十分方便。使用方法的次数多了,自然就会记住它们。

父类3 和 65 等整数,是 Fixnum 类的实例。

看到 Fixnum 类的方法列表了吧,它的方法数量是如此的少会不会觉得不可思议。当然整数能使用的方法不只这几个。关键在父类这栏里。到 Integer 里面去看看吧。

在 Integer 类中有个名称为 chr 的方法。这是个将数字转换为该数字编码的文字并返回的方法。试试看吧。

a = 65

p a.chr # => "A"

上例正确的返回了一个结果。但是 65 是 Fixnum 类的一个实例,为何调用 Integer 类的方法 chr 也不出现错误呢?这是因为 Integer 类是 Fixnum 类的父类,而 Fixnum 类继承了父类的方法。

所谓继承,就是在一个原有类中扩充定义一个新类,其新定义的类可以使用原有类的方法和属性。这样原来的类就称为父类,而新定义的类则称为子类。

总之,Fixnum 类是 Integer 类中扩充定义的一个新类。也可以这样说,Integer 类是 Fixnum 类的父类。Fixnum 类继承了 Integer 类的性质,也同样继承了父类的方法。当然,继承的还包括 Integer 类的父类 Numeric 类,以及 Numeric 类的父类 Object 类中定义的方法,Fixnum 类的实例都可以使用。

看到这里也许有人会问,为何要特意把这些类给分开呢?回答会有一点困难,继承的意思,是保持被继承者的性质但却同时拥有自己独有的特性。比如,浮点数是 Float

类的实例,这个类是从 Numeric 类中继承而来的。整数和浮点数的性质是不相同的,然而无论哪个都是表示「数字」这个概念却是共同的,所以在 Numeric 类中定义共同的部分而不用在各个子类中重复定义。



显示图片
Graphics 模块
精灵和位图
属性
在学习完对象后让我们稍稍轻松一下,来使用 RGSS 的游戏程序显示图片吧。

Graphics 模块在 RGSS 游戏程序中最重要的应当是 Graphics 模块。它是用来处理游戏中所有图片的方法集合,在游戏的画面中显示图片,就要使用到该模块的功能。

所谓模块,可以考虑成收集了相同范围方法的如容器那样的东西。和类比较相似,然而却不能生成模块的实例,也没有那个必要。

那么首先,请按下面那样输入。

loop do
Graphics.update
end

这个是用 loop do ~ end 语句作成的无限循环。这个处理是无限反复运行 Graphics.update 操作的意思。中间的那行,是调用 Graphics 模块的 update 方法。因为这个是和调用对象方法相同的形式,所以会比较容易理解吧。

Graphics.update 完成的是更新游戏画面,然后前进 1 帧这样的任务。 这个时候,会向画面中重新同时显示出图片。这个形式是 RGSS 游戏运行的基础。 而运行 RPG 大规模游戏的复杂的脚本,也不过是在这个基本形式上添加各种各样的处理而已。

还有,运行上面的示例后什么也没有显示。这只是个反复显示乌黑画面的处理而已。下面我们就来学习实际显示图片的方法吧。

精灵和位图向刚才的脚本中加入 2 行,如下所示。如果画面左上角显示出小恶魔的图片就表示成功了。

devil = Sprite.new
devil.bitmap = Bitmap.new("Graphics/Battlers/075-Devil01")

loop do
Graphics.update
end

这里出现了 Sprite 和 Bitmap 两个新类。Sprite 是在游戏画面上显示某些图片的基本概念即精灵的类,Bitmap 是精灵传输元位图本身内容的类。

第一行,是新生成一个 Sprite 类的实例,并把那个实例代入变量 devil。生成整数和字符串的实例比如 3 或 "Ruby" 等可以直接写入,然而生成精灵这样的实例时就必需以 Sprite.new 这样的方式生成。

第二行,是读取 RGSS-RTP 中所含的图片文件 ("Graphics/Battlers/075-Devil01") 并作为 Bitmap 类的一个新实例。而且,对 devil 对象的 bitmap 属性(后述)进行设定。也就是设定这个位图为精灵传输元的意思。

指定 Bitmap.new 参数的路径名,分隔符号是使用 / 而不是 \ 这点要特别注意。我们在字符串「控制码」这项中学习了 \ 在字符串中具有特殊的意义,而在这里使用 / 才是正确的。

属性Sprite 类中像 bitmap 那样的特性称为属性。实际上这并不是 Ruby 语言的概念,而是 RGSS 的独特用语

。在游戏程序中使用赋值运算符在多个方面对其内容特性进行设定,这些就称为属性。例如,更改表示精灵座标的 x、y 属性数值就是这样。

devil = Sprite.new
devil.bitmap = Bitmap.new("Graphics/Battlers/075-Devil01")
devil.x = 320
devil.y = 240

loop do
Graphics.update
end

上面第三行,是把指定精灵 X 座标的属性 x 设定为值 320。同样的第四行,是把指定精灵 Y 座标的属性 y 设定为值 240。这样运行的话,精灵就会显示在画面中央位置附近。

让我们进一步加工一下。

devil = Sprite.new
devil.bitmap = Bitmap.new("Graphics/Battlers/075-Devil01")
devil.ox = devil.bitmap.width / 2
devil.oy = devil.bitmap.height / 2
devil.x = 320
devil.y = 240

loop do
Graphics.update
end

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

现在,可以去看一看 Sprite 类和 Bitmap 类的说明了,是不是觉得写得很复杂不知如何理解?使用这些有趣的属性和方法,自己动手试一试吧。这才是学习 RGSS 的捷径。



数组
数组的生成
数组单元的重赋值
数组的操作
数组的循环
想一起处理多个对象就要使用数组。

数组的生成在 [] 符号中间排列多个单元就生成了一个数组。如下例所示。

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

上述程序建立了一个包含 "艾力克斯"、"布莱恩"、"卡罗来" 这三个字符串单元的数组,并把这个数组代入变量 a 为其赋值。

要取出数组中对象,如下例所示。

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

p a[0] # => "艾力克斯"
p a[1] # => "布莱恩"
p a[2] # => "卡罗来"

上述中,a[0] 和 a[1] 等各个单元,能和其它变量那样单独使用。这里 0、1、2 那样的数字被称为数组的附加码。附加码不是从 1 开始而是从 0 开始的,这点一定要注意。从 0 开始,单元从左至右依次为 0、1、2 ……。

数组中除了字符串外还可以包含其它任意的对象。而且,使用 p 命令也可以不指定附加码,那样就会显示数组的全部单元。

a = [2000,"艾力克斯",true,1..50]

p a # => [2000,"艾力克斯",true,1..50]

数组单元的重赋值数组的各单元的使用和普通的变量一样,也能进行变量的重赋值。

a = [10, 20, 30]
a[0] = 100

p a # => [100, 20, 30]

该示例中,首先是建立了一个由 10、20、30 这三个数字单元组成的数组,然后向

第一个单元里重赋值代入 100。这时 a[0] 原先的数值 10 就被代入的 100 所代替,显示的结果就更改了。这个处理和普通变量的重赋值是一样的。

指定超过最初数组附加码范围的单元并为之赋值,会自动扩大数组添加新的单元。

a = [10, 20, 30]
a[3] = 40

p a # => [10, 20, 30, 40]

建立数组时只有 3 个单元,现在为在其范围外的 a[3] 赋值,就会自动添加第 4 个单元扩大数组。C 语言等其它语言是不充许这样赋值的,而 Ruby 这种灵活的语言就可以放心添加。

如果跳过范围的话会如何呢?

a = [10, 20, 30]
a[5] = 60

p a # => [10, 20, 30, nil, nil, 60]

中间就会出现 nil 值。这个与 true 和 false 等一样是常量的一种,意思是「什么都没有」。和 true 表示「真」,false 表示「伪」一样,nil 表示「无」。

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

比如,想知道数组的单元数量的话就可以使用 size 方法。和 String 类的 size 方法返回字符串字节数相似,Array 类的 size 方法是返回数组的单元数。数组为空时就返回 0。

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

p a.size # => 3

想知道数组中是否含有特定的值的话,就要使用到 include? 方法。

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

p a.include?("布莱恩") # => true
p a.include?("小田纯一狼") # => false

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

数组的循环使用 for 循环,即使没有设定对象的附加码也能指定数组单元。

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

for s in a
p s
end

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



Hash 表
Hash 表的生成
Hash 表数值的添加
Hash 表的操作
Hash 表的循环
Hash 表是一种和数组比较类似的数据构造形式。

Hash 表的生成Hash 表也称为关联数组。和数组不同的是,作为取出数值 的主键(相当于数组的附加码),可以使用任意的对象。 在 {} 符号中间排列多个单元就生成了一个哈希表。

a = {"艾力克斯"=>2000, "杰克"=>2003}

这个例子中,"艾力克斯" 和 "杰克" 就是取出数值的主 键,2000 和 2003 就是实际的数值。这样, 使用 => 符号把主键和数值连接起来就形成了 Hash 表。


要取出 Hash 表中对象的时候,应按如下操作。

a = {"艾力克斯"=>2000, "杰克"=>2003}

p a["艾力克斯"] # => 2000
p a["杰克"] # => 2003
p a["宇佐助"] # => nil

从上例最后一行可以得知,当指定主键不存在时就会返回 nil。

这里是以字符串为主键,当然不使用字符串也可以。作为主键还可以使用整数等其它数据类型,在有很多编号单元的情况下使用哈希表会比使用数组更加方便。

另外,哈希表的反操作,也就是「检查与数值对应的主键」的情况下,在 [] 中写入数值是不能得到其主键的。这里不再多作陈述,该种操作方法我们会在后面特别介绍。

Hash 表数值的添加实际操作中,Hash 表可以在程序中直接指定数据建立, 亦可以使用先建立一个空的 Hash 表然后向其中添加单元数据等多种方法生成。 生成一个空的 Hash 表只需写入 {} 就行了。

a = {}

向 Hash 表中添加数值,和数组单元的重赋值完全相同。

a = {}
a["艾力克斯"] = 2000

p a # => {"艾力克斯"=>2000}

Hash 表的操作Hash 表是 Hash 类的对象。 同数组一样,可以调用这个类定义的方法对数据进行操作。

比如要从 Hash 表中删除数值的话,就要使用 delete 方法。

a = {"艾力克斯"=>2000, "杰克"=>2003}
a.delete("杰克")

p a # => {"艾力克斯"=>2000}

想知道 Hash 表中是否含有某个特定主键的情况下,就要使用 include? 方法。

a = {"艾力克斯"=>2000, "杰克"=>2003}

p a.include?("艾力克斯") # => true
p a.include?("宇佐助") # => false

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

Hash 表的循环在 Hash 类中,有取得全部主键排列的 keys 方法。

a = {3=>6, 4=>10, 5=>15}
p a.keys # => [5, 3, 4]

这样,=> 左侧的主键会全部排列出来。 但 Hash 表中是没有顺序的,所以排列会无顺序可言。

前节中,我们学习了使用 for 循环指定数组的方法。 现在让我们来用 for 循环指定 keys 方法的返回值,作成 Hash 表主键的循环吧。

a = {3=>6, 4=>10, 5=>15}

for k in a.keys
p k
end

运行上例就会按不同顺序显示 3、4、5。

而且,使用 values 方法的话,还能取得 Hash 表全部数值的排列。

a = {3=>6, 4=>10, 5=>15}

for v in a.values
p v
end

运行上例就会按不同顺序显示 6、10、15。





定义类
类的定义
方法的定义
实变量
对象初始化
方法的重载
基础篇的最后,让

我们来学习定义新类的方法。

类的定义直到今天,我们都是一直在使用 String 类、Array 类或者 Sprite 类等这些系统内部类的方法来进行学习。实际上如果想使用类,也可以自己定义。所谓「建立类」几乎和「程序设计」是一个意思。其实预置脚本中,除外最后一个 Main 组其余的全部都是类定义。

比如新定义一个 Person 类,可以如下操作。

class Person
end

定义类的话这样就行了。但现在只是个「什么都没有的类」,让我们再来进行以下操作。

alex = Person.new

这样就作成一个 Person 类的实例。

想要指定父类也很简单。比如,定义继承于父类 Monkey 类的 Person 类可以如下操作。

class Person < Monkey
end

方法的定义方法的定义,和定义普通函数的情况相同。如果在类定义当中加上 def ~ end 的话,就会自动成为该类的方法。

class Person
def hello
print "您好"
end
end

这样,就定义了调用后会显示“您好”字符串的 hello 方法。再进行如下操作。


alex = Person.new
alex.hello # => 您好

这样就能调用 hello 方法了。

实变量属于个体对象的变量称为实变量。名称以 @ 开头的变量,自动作为实变量使用。局部变量只有在 def ~ end 等结构内部使用时才有效,然而使用实变量的话,只要其对象存在,变量的值就会被保存。实变量一般作为对象的属性来使用。

class Person
def name
return @name
end
def name=(name)
@name = name
end
def hello
print "我是" + @name + ""
end
end

alex = Person.new
https://www.wendangku.net/doc/c6373875.html, = "艾力克斯"
alex.hello # => 我是艾力克斯

上面的示例是先准备 @name 实变量,使用 name、name= 方法把对象附加上 @name 实变量作为属性。像这样的方法称为附加属性。附加属性也能更简单的像下面那样编写。

attr_accessor :name

这样编写是,自动定义与 : 符号右侧名称相同的实变量对应属性的取得和注解方法。上例中是生成 @name 实变量并附加成为属性。总之,

def name
return @name
end
def name=(name)
@name = name
end

是与上面相同的意思。

在预置脚本中 attr_accessor 应用得很多。但在只定义属性的取得方法的情况下,一般使用 attr_reader 代替 attr_accessor。

对象初始化生成对象时,把实变量初始化为某个特定的值。先定义一个名称为 initialize 的方法,在使用 new 生成新实例时会自动调用该方法。

class Person
def initialize
@name = "无名先生"
end
end

从第二行开始的 initialize 方法的定义,表示实变量 @name 的初始值被赋值为字符串 "无名先生"。这样,生成新的 Person 对象的时候,会自动以 "无名先生" 初始化实变量



initialize 方法中设定有临时参数的情况下,new 会取该参数为初始值。

class Person
def initialize(name)
@name = name
end
end

alex = Person.new("艾力克斯")

上述示例中,initialize 方法里设定有临时参数 name,那么实变量 @name 的初始值就会使用该参数。参数 name 实际在 Person 类 new 时给予。最后一行,生成 Person 类对象时指定参数为 "艾力克斯",那么 @name 的初始值也就设定为 "艾力克斯"。

方法的重载父类中已定义的方法在子类中再次被定义称为重载。在子类方法中调用父类相同方法的情况下,要使用关键词 super。

class Hahaha
def laugh(x)
return "哈" * x
end
end

class Wahaha < Hahaha
def laugh(x)
return "哇" + super
end
end

man = Wahaha.new
p https://www.wendangku.net/doc/c6373875.html,ugh(4) # => "哇哈哈哈哈"

上述示例是,对新建实例调用 Wahaha 类的 laugh 方法,其中 super 能调用其父类 Hahaha 类的 laugh 方法。那么,最后一行调用 laugh 方法可以理解为 "哇" + "哈" * 4,于是输出结果就为 "哇哈哈哈哈"。











相关文档