幻想森林

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 4532|回复: 12

[RM2K&2K3] [分享]Ruby的基本教程

[复制链接]

10

主题

52

帖子

574

积分

⑤进阶

积分
574
发表于 2007-4-6 23:29:11 | 显示全部楼层 |阅读模式
不知道火没火星~~建议你们打印输出[p:3][p:1]
回不到过去,去不了未来.我无路可逃.......
回复

使用道具 举报

10

主题

52

帖子

574

积分

⑤进阶

积分
574
 楼主| 发表于 2007-4-6 23:30:52 | 显示全部楼层
RPG Maker XP
RPG Maker XP(RPGXP)是一款可让玩家自行制作在计算机游戏中相当受欢迎的角色扮演游戏,也就是 Role-Playing Game(RPG)的软件。制作完成的游戏,即使在没有安装 RPG Maker XP 的电脑上也能运行。
主要特点
高精度的画面
支持 640×480 像素分辨率 32 色真彩色图像。完全对应 Alpha Channel(每个像素的透明度),光滑的透过处理,柔和的半透明表现。画面的合成方法也增加了通常的半透明合成、加算合成和减算合成。而且字型自动映射,粗体不再引人注目。
使用软件的音乐播放
作为 BGM,主要使用 DirectMusic Synthesizer 的 MIDI 播放。因为以软件播放,所以不能用其它格式代替,音乐素材的制造人没必需考虑对各种 MIDI 音乐的对应。在制作过程中能被正常播放的 MIDI 文件,同样可以在其它环境中正常播放。
灵活且强大的脚本系统
用 RPGXP 制作完成的游戏,脚本是以 Ruby 语言编写的。预先编写的脚本可以制作十分独特和有趣的游戏,它是为了更高级的游戏制作需求准备的,使用它可以进行画面设计、编写战斗系统,以及一切的游戏要素。运用脚本制作 RPG 以外类型的游戏也是可能的。
游戏的操作方法
基本操作
RPGXP 的游戏,以 8 个按钮和游戏手柄的操作为基础。
各个按钮(A,B,C,X,Y,Z,L,R)对应的键盘和具体功能如下所示。游戏手柄的 A,B,C 等 按钮也是如此对应,所以使用起来会更加容易。
名称    游戏手柄    键盘    主要功能
A    按钮 1    Shift, Z    -
B    按钮 2    Esc, Num 0, X    取消,菜单
C    按钮 3    Space, Enter, C    决定
X    按钮 4    A    -
Y    按钮 5    S    -
Z    按钮 6    D    -
L    按钮 7    Q, Pageup    前页
R    按钮 8    W, Pagedown    后页
述的「主要功能」是标准的游戏操作,各个游戏作品 可能因为有其独特的操作而存在不同的情况。
另外如果是游戏手柄的话,其方向键和键盘的方向键(↑↓←→)功能一样,用来控制人物和光标的移动。
游戏属性

在游戏运行中按 F1 键,会显示游戏属性对话框,如右图。这个窗口可以自行分配游戏手柄和键盘的按钮设定。 按「重置」键,就可以回复为系统默认设定。
在「常规」页里可以进行以下设置。
平滑模式
通常,游戏画面是以每秒 20 帧的速率显示,达到推荐配置以上的电脑(推荐 Pentium4 1.5 GHz 以上)可选择此项,游戏画面将以每秒 40 帧的速率显示而使画面更加平滑。
抑制画面抖动
垂直扫描完后更新画面,选择此项可以最低限度的减少画面的细微闪烁。然而,画面 会出现稍微延迟的情况。选择与否,可以根据哪个更舒适,PC 配置和个人的爱好决定。
播放 BGM 和 ME
此项可以选择是否欣赏游戏中的音乐。想一边听其他音乐一边测试游戏,就可以取消对勾,选择无声设置。
播放 BGS 和 SE
此项可以选择是否播放游戏中的声音效果。
其他操作
键    功能
Alt+Enter    窗口模式和全屏模式的切换。
Alt+F4    强制结束游戏。
F12    强制回到标题画面。
F2    测试游戏时,标题栏上显示 FPS(每秒的画面帧数)。
F9    测试游戏时,移动中按下该键可以呼出调试窗口(开关,变量一览表)。
Ctrl    测试游戏时,按下该键不放同时移动,会使地图图块的通行设置无效,而能在不充许通行的元件上自由移动。
帮助提示
帮助提示

在 RPGXP 中,大致全部对话框选项都准备有相应的简单说明,可以在不中断工作流程的情况下得到必要的信息。将这个功能称为帮助提示。调出帮助提示,有以下 3 种方法。
1.    在选项操作中按 F1 键。
2.    在选项上点击鼠标右键,于弹出菜单中选择「帮助」(如右图)。由于选项的种类不同,某些情况下可能不能使用。
3.    点击标题栏右上角的「?」图标后,把光标移到目标的上方点击鼠标左键。
要了解更详细的信息,请看本软件附属的使用说明手册。
工程
在 RPGXP 中,是以工程为单位来制作游戏的。建立一个工程,就会在硬盘中新建一个文件夹,而游戏中的各种数据资料就以文件保存在其中。
新建工程

制作一款新游戏,在主菜单「文件」菜单中选择「新建工程」。于显示的对话框中依照指示输入文件夹名和标题,并可选择一个路径,输入完毕按「确定」,就建立了一个新工程。
新建文件夹内的 Game.rxproj 文件就是工程文件。以后,只要双击这个文件就能直接打开该工程。可以把编辑中的工程在桌面上建立一个快捷方式,这样会更快捷方便。
更改标题

更改已建立工程的标题(游戏名),打开该工程,在主菜单「游戏」菜单中选择「更改标题」。于显示的对话框中输入新的标题,按「确定」就完成了标题的更改。
工程的操作

删除工程和更改文件夹名,在 RPGXP 中没有此项功能。想要删除工程和更改文件夹名,可于 Windows 中转到该文件夹,直接操作即可。
还有,复制游戏工程文件夹,就可完成整个游戏的拷贝。为了减少操作疏忽和无法预料的错误引起数据丢失的风险,推荐定期备份制作中的游戏。
游戏的发布
游戏制作完成后要于 Web 上发布,在主菜单「文件」菜单中选择「压缩游戏数据」。压缩结束,就在指定文件夹中生成了一个自解压文件,发布那个文件就 OK 了。
游戏发布后,如果玩家电脑内没有安装 RPGXP,要想运行 RPGXP 制作的游戏,就必须下载和安装 RGSS-RTP(也有不需要 RTP 的游戏制作方法,但不推荐)。 RGSS-RTP 可以从下面地址下载。
デジタルファミ通网页
http://www.enterbrain.co.jp/digifami/
如果不想别人编辑修改你的游戏内容,可在压缩时选取「生成加密档案文件」选项。这样生成的加密后的文件别人就不能修改了,但加密的文件会比通常的文件要大,所以要根据你自己的情况来决定。
不使用「压缩游戏数据」功能,也可以用其它软件进行游戏文件夹的压缩和发布,比如 winrar 或制成安装程序等,但一定要注意保持整个游戏数据的完整。
地图
原野、迷宫、城市街道和建筑物内部等主角移动的舞台称为地图。
游戏是由很多地图构成的,名个地图间可以随着事件的处理来回移动。例如主角在接触建筑物的入口后,画面就会消失,而转移到建筑物内部的另一个地图里。因此通过这样的衔接方式便能将整个地图联系在一起。
地图元件和图块

地图看起来就像一整张图画,然而实际上和拼图玩具的小块一样是由许多小部件组合而成的。构成地图的最小部件称为地图元件。地图元件可以设定各种不同的属性,比如人物能否通行等。
表现特定的场所就需要一组整理在一起的许多地图元件,并设定各种不同的属性,这就称为图块。各个地图可以选择使用不同的图块,然后用该图块中的地图元件组合配置成一张地图。在图块中,还可以设定战斗时显示的背景(战斗背景)图形,遭遇敌人时会自动使用该背景。
地图的制作

新地图的制作和多个地图的管理,是在主窗口左下方的地图树状目录里进行。
首先,在地图树状目录里选择一个地图名称,按下鼠标右键,出现选单后选择「新建地图」,便会开启制作地图窗口,设定好地图名称、图块、地图大小、遇敌率等必要信息后按下「确定」,就完成了新地图的制作。各项的具体意义请参照帮助提示。
地图设定完毕,最初选择的地图下方就会建立一个新的子地图,而上方的地图就叫母地图。这和 Windows 文件夹的目录结构相同。这个结构并不直接影响游戏的运行,比如城市的建筑物内部地图作成该城市整体地图的子地图,这样对多个地图的管理就会更加容易。地图可以通过鼠标直接拖曳 & 移动选项中的上下移动来改变目录结构。


地图是由 3 层各种各样不同的地图元件配置而成的。可以向各层任意配置各种地图元件,一般来说第 1 层是地面,第 2 层是栅栏和建筑物,第 3 层是窗户和烟囱,按照这个标准,地图就能顺利制作完成。
地图编辑时层的选择,是在主菜单「模式」中设定的。而且,在「视图」菜单中还可以更改「暗淡显示其它层」,和显示「当前及下一层」还是「全部层」等设定。
地图元件的配置
编辑地图时打算在地图上配置的地图元件,必须从主窗口左边的地图元件面板中选择。在地图元件面板中选择一个地图元件,也可以同时选择多个地图元件。选择了地图元件,就可以用绘图工具在右侧的绘图区域自由配置了。
配置地图元件的绘图工具,可以在主菜单「绘图」中选择。各个绘图工具的功能如下。
铅笔
是最常用的绘图工具。在绘图区域上进行点选和拖曳可将目前选取的地图元件配置到地图上。
四边形
籍由拖曳对角线形成一个四边形,将目前选取的地图元件填满该四边形区域。
椭圆
籍由拖曳对角线形成一个四边形缩起的圆形,将目前选取的地图元件填满该区域。
填充
在点选处的上下左右连续相同的地图元件全部置换为目前选取的地图元件。
选择
为地图的剪切和复制等选取一个编辑范围。这种情况下点击鼠标右键会显示一个弹出菜单,就可以进行该范围的剪切和复制等操作。另外,选取范围的复制等操作包括全部三层的所有对像。
绘图工具为「选择」以外的其它工具时,在绘图区域某处点击鼠标右键,地图元件面板中白线框选的地图元件就会自动切换为该处所配置的地图元件。这个功能称为吸管。使用吸管功能会省略从地图元件面板中选择地图元件的步骤,将大大提升作业效率。
自动地图元件

地图元件面板中最上面的一排地图元件叫做自动地图元件,是种特殊的地图元件。自动地图元件是一类有很多式样的地图元件,实际排列中会依照边界自动调节。
一边按「Shift」键一边配置自动地图元件和使用吸管时,这个功能会暂时失效。
而且,在地图元件面板上双击自动地图元件,就会出现「自动展开元件」对话框,可以直接选择边界调整的式样。
事件
向村民打听情报,有条件才能打开的宝箱等游戏中发生的一切事情称为事件。
游戏如何进行全部都由事件来管理,比如「主角从城市出口移动到草原地图」的处理就是使用的事件,作为一个游戏,建立事件是必需的。
事件的种类
事件共分为「地图事件」、「战斗事件」、「公共事件」三种。一般所说的独立事件,基本上指的是地图事件。
地图事件
就是在地图画面上运行的事件。包括场所的移动,人物的对话等。在主菜单「模式」菜单中选择「事件」,于地图编辑区域上双击(点右键选择「新建事件」亦可)就可新建一个地图事件。建立大量的地图事件会加大 CPU 的负荷,通常一个地图内事件数少于 100 会比较好。
战斗事件
就是在战斗画面中运行的事件。比如「敌人在 HP 值达到规定值以下时变身」的处理就是使用的战斗事件。在数据库「队伍」页中设定。
公共事件
可以从地图事件和战斗事件中调用,为特殊情况的处理,是通用的事件。在数据库「公共事件」页中设定。
事件页

在地图事件中,一个事件能设立多个不同内容的处理。这种设定的单位称为事件页。
各事件页内容的出现条件分为开关、变量、独立开关三种类型(开关总共是二个)。满足指定条件的事件页有多个的话,会执行号码最大的事件页的内容。
开关
整个游戏中,开关总会保持 ON/OFF 的数据。例如管理「接受了消灭怪物的委托」或「打倒了BOSS」的信息。
变量
整个游戏中,变量都会保持任意整数(最大 8 位)的数据。例如管理「主角的声望」或「收集世界中分散的物品,移交给委托者的件数」的信息。
独立开关
是引发个体事件的特殊开关。不会给其它事件造成影响,仅为该事件使用。例如管理「打开了宝箱」的信息。
战斗事件也有事件页,但是具体方法和地图事件不同。具体请参照战斗事件的设定。
公共事件没有事件页。如果自动执行事件的话,可以指定一个条件开关。
事件开始条件
已定义事件页的「执行内容」,实际开始执行的条件称为事件开始条件。
决定键
在主角与事件接触的状态下,按下决定键(C 按钮)时事件开始执行。当主角与事件之间即使有柜台属性的地图元件也可以。向村民问话或调查宝箱等基本事件会使用这种方式。
与主角接触
增加了「决定键」的条件,当主角以方向按钮向事件接触时也能开始执行事件。如果主角与事件能重叠的话,那么重叠时开始执行事件。场所移动事件会使用这种方式。
与事件接触
增加了「与主角接触」的条件,当事件移动到与主角接触时也能开始执行事件。比如怪物在地图上来回移动,接触到主角时触发战斗的事件会使用这种方式。
自动执行
事件立即自动执行。事件页的出现条件满足的情况下事件会反复执行,需要适当转换开关和独立开关,必须控制事件的出现条件。比如移动到特定地图发生强制事件时会使用这种方式。
并行处理
在事件出现期间,周期性的执行事件内容。并行处理的事件与通常的性质有所不同,在其他事件执行的同时并行执行该事件,使用时必须要格外注意。比如监视计时器的事件,一定时间制造雷电闪光画面的事件会使用这种方式。即使完全没有使用这种事件开始条件也不会影响游戏的制作,所以没有必要勉强记住使用方法。
公共事件的情况和地图事件不同,其没有实体的存在,开始条件只有由其它事件调用执行的「无」、「自动执行」和「并行处理」三种。但是无论是哪种开始条件,由并行处理事件调用执行和并行处理功能一样,要格外注意。并行处理中执行通常事件时,不要直接调用执行公共事件,最好经由开关控制的自动执行事件调用执行。
并行处理事件会加大 CPU 的负荷。特别是执行开关和变量的操作时,条件的变化会加强对事件出现还是消失的判定,地图存在事件页的量和处理时间成正比。这样,不推荐经常执行大量的并行处理事件。
战斗事件的设定

发生战斗中的事件称为战斗事件。
战斗事件和地图事件一样有事件页。经常按号码顺序检查事件页,有满足条件的事件页就立即执行。
战斗事件的出现条件为回合数、敌人的 HP、角色的 HP 和开关这四种,可指定多个。各个设定的具体内容请参照帮助提示。
执行内容
在游戏中产生某个变化的命令称为事件指令。
实际中事件的执行内容是由登录于事件执行列表中的事件指令来定义的,执行时从上到下依次执行。事件指令有「显示文章」、「场所移动」、「战斗处理」等各种不同的指令,变化丰富多种多样共计有 90 种之多。
执行内容的编辑方法种类事件都是共同的。插入事件指令,以下列顺序进行。
双击列表中有「◆」符号的项目。
会开启「事件指令」对话框。在这里选择欲使用的事件指令,按下标有该事件指令名称的按钮。如果不明白指令的意思可以调用帮助提示,就能看到各种指令的简单说明。
除一部分指令外,将会开启事件指令设定对话框。完成必要的设定后按下「确定」。
在该双击项目的位置就会插入一个事件指令。
在事件指令列表中,选择一个事件指令点击右键会出现弹出菜单,应用此菜单能进行复制粘贴等操作。按下「Shift」键不放的话,就可以同时选择多个事件指令一起进行操作。
文章的显示

在游戏画面上显示信息就要用到事件指令「显示文章」。这是个常用的指令,在全部事件指令中使用得最多。
在文章中可以使用以下的控制码。
\\V[n]
显示第 n 号变量中的值(n 为数字)。
\\N[n]
显示第 n 号角色的名称(n 为数字)。
\\C[n]
之后的文字用第 n 号的颜色显示。
0    1    2    3    4    5    6    7
\\G
开启所持金钱窗口。
\\\\
显示文字“\\”。
输入文章时按「F2」键,就可预览实际游戏中显示的信息窗口。
数据库
游戏中使用的各种数据集合在一起称为数据库。
数据库的内容
编辑数据库的内容,在主菜单「工具」菜单中选择「数据库」。在对话框的分页中进行切换,就可以编辑下列各种不同种类的数据。
角色    在游戏中被玩家操作的人物角色的数据。
职业    装备的武器、防具和能够学习的特技等,决定角色特征的数据。
特技    主要是消耗 SP 发动特别的效果,是技能和魔法等的数据。
物品    回复剂和事件物品等,除装备以外的物品的数据。
武器    具有攻击力等属性的武器的数据。作为物品的一种来使用。
防具    具有物理防御和魔法防御等属性的防具的数据。作为物品的一种来使用。
敌人    触发战斗和事件战斗的与主角敌对的敌人角色的数据。
队伍    敌人的组合。是游戏中实际出现的形态。
状态    对角色的能力和行动造成各种各样的影响,是健康情况和状态的数据。
动画    武器和特技的视觉效果等使用的动画的数据。
图块    设定绘制地图时所用图块的地图元件的数据。
公共事件    在整个游戏中通用的各种可调用事件的数据。
系统    初期同伴、属性、SE 和用语等各种各样的数据。
这些数据在游戏中基本不重复使用。比如角色中有「初期等级」设定项,然而实际角色在游戏中会成长,等级也会不断上升,从而会使用另外的数据。
编辑数据项目

除外「系统」,各分页的画面都是左右分开,左侧为数据项目的 ID(管理号)和名称目录,右侧显示为该数据项目的内容。编辑数据项目,单击左侧目录选择,再编辑右侧显示的各设定项目。各设定项目的具体意思请参照帮助提示。
数据库窗口中按「F4」、「F5」键,就能在各个数据项目中上下选择。在有很多数据要设定特定项目的情况下,使用该操作能大大提高工作效率。
在数据项目目录中点击右键会出现弹出菜单,可以进行复制和粘贴等操作。在这里选择「批量复制」,会出现指定批量复制项目数的对话框,设定一个要复制的项目数。这将会在从其它工程中转移数据的情况下使用。
更改最大值

要更改数据项目的数量,点击目录下面的「更改最大值」按钮。会显示更改最大值对话框,设定一个从 1 到 999 的数值。
增加最大值会增加游戏运行时必需的内存容量,数据的读写速度也会变慢。最好不要无意义的增加最大值。
如果减少了最大值,那么超过这个数量的项目会被全部删除。
脚本
掌管游戏运行的简单程序语言称为脚本。
与一般把「显示文章」这样的指令称为脚本的情况不同,RPGXP 把在事件指令之上,更接近程序概念的指令称为脚本。所有事件指令其实不是程序,只有脚本系统解读后才能运行。
脚本的编辑,是针对游戏系统的高级用户提供的功能,难度很高。如果只是制作普通游戏,就没有必要了解。最初的脚本系统完全可以制作不错的游戏,最好只在对默认脚本感到不满意的时候再进行编辑。
Ruby 是什么
脚本语言是一种独特的简单语言,RPGXP 采用的是 Ruby 脚本语言。Ruby 的官方网页是 http://www.ruby-lang.org/
Ruby 是松本行弘先生开发的免费软件,描述大规模的游戏也能保持良好性能。是善长文本处理的语言,照原样会加大游戏开发的难度。因此,对游戏开发用途的 Ruby 语言进行了特殊化,这就是 RGSS(Ruby Game Scripting System),中文意思就是 Ruby 游戏脚本系统。详细内容请参照 RGSS 参考。
另外,把 Ruby 标记为 ruby 是充许的,但是不能标记为 RUBY、ルビー或るびー(这两个日语的发音同 Ruby)。
脚本编辑器

在主菜单「工具」菜单中选择「脚本编辑器」。会出现脚本编辑器对话框。
运行像 RPG 这类大规模的游戏需要非常多的脚本程序,所以把全部脚本程序分为多个适当的单位来管理是很重要的。RPGXP 把这个单位称为组。脚本编辑器左侧显示的就是组列表。
脚本编辑器,和数据库有相似的设计便于操作。同数据库一样按「F4」、「F5」键,就能在各个组中上下选择。这里还增加了一个「F6」键,可以取光标当前位置的单词复制为该脚本组的名称。
组的操作

在组名称上点右键会出现弹出菜单。选择「插入」,就会在所选组前面添加一个新的空白组。同样,选择「剪切」和「复制」操作,就能更改组的顺序。
和数据库不同,组不是以 ID 来管理的。而是按照各组在列表中的顺序,从上到下依次运行。游戏开始脚本是列表最下面的“Main”,各种定义完成后实际游戏的运行是从该组开始的。
编辑操作

在右侧文本编辑窗口中点右键,会出现一个弹出菜单如右图。就能进行「剪切」、「复制」、「查找」、「替换」等基本的编辑操作。
文本编辑中还可使用 Ctrl+F 和 Ctrl+G 等快捷键。
如果使用「查找」在编辑的组中没有找到目标,而想对全部脚本组进行文本搜索时,可以在组的弹出菜单中选择「查找」。快捷键是 Ctrl+Shift+F。
脚本的使用方法
脚本除了能在脚本编辑器中直接编辑以外还有以下三种使用方法。
1.    在事件指令「脚本」中使用。
2.    在事件指令「条件分歧」的条件中使用。
3.    作为「移动路线」内的指令使用。
比如「调用加入了独立脚本的事件指令」的情况就能使用到脚本。这样或许能设计出各种各样有趣的使用方法。
素材规格
RPGXP 可以使用其本身初始的图片和声音素材文件。
在主菜单「工具」菜单中选择「媒体库」,会出现媒体库对话框,可以进行各种素材的导入与导出。向游戏文件夹里直接复制文件也可以,媒体库中还有图片预览功能,对素材不熟悉的话可以使用。
图片素材
可以使用 PNG 文件和 JPG 文件。如果是 PNG 文件则必须为 32 位元色彩(Alpha Channel)。
角色(Graphics/Characters)
收录地图上显示的角色图片的文件夹。
一个角色使用一个文件。尺寸任意,以 4 个方向(下、左、右、上)×4 个步行样式合计 16 个样式的规定顺序排列。位图宽高的各 1/4 就作为该角色的尺寸。
战斗者(Graphics/Battlers)
收录战斗画面中显示的角色图片的文件夹。
尺寸任意,但注意最好不要超过 640×320 的战斗画面。而且使用高 40 以下的图片会损害显示出来的清晰度。
动画(Graphics/Animations)
收录主要在战斗画面中显示效果的动画图片的文件夹。
一个个固定大小 192×192 的图片 5 张横向排列为一组,如有必要还可以纵向延长,即成为一整个动画文件。文件的尺寸大小无限制,但因为显示动画速度的关系,最好不要用太大的图片。
图块(Graphics/Tilesets)
收录构成地图的地图元件的文件夹。
一个个固定大小 32×32 的元件图片 8 张横向排列为一组,如有必要还可以纵向延长,即成为一整个图块文件。文件的尺寸大小无限制,但因为显示地图速度的关系,最好不要用太大的图片。
自动地图元件(Graphics/Autotiles)
收录边界自动生成的特殊地图元件的文件夹。
具体请参照自动地图元件说明。
远景(Graphics/Panoramas)
收录地图远处显示的图片(远景)的文件夹。
尺寸大小无限制。但要符合网页壁纸的特点,制作成上下左右能连接的样式。
雾(Graphics/Fogs)
收录地图前显示雾遮盖效果的图片的文件夹。
尺寸大小无限制。但要符合网页壁纸的特点,制作成上下左右能连接的样式。
战斗背景(Graphics/Battlebacks)
是收录战斗画面背景图片的文件夹。
尺寸为 640×320。
图标(Graphics/Icons)
收录技能和物品名称前显示的图标图片的文件夹。
尺寸为 24×24。
标题(Graphics/Titles)
收录标题画面图片的文件夹。
尺寸为 640×480。
游戏结束(Graphics/Gameovers)
收录游戏结束画面图片的文件夹。
尺寸为 640×480。
窗口皮肤(Graphics/Windowskins)
收录合成窗口画面的图片的文件夹。
具体请参照窗口皮肤说明。
图片(Graphics/Pictures)
收录游戏中事件所使用图片的文件夹。
尺寸任意。
切换效果(Graphics/Transitions)
收录游戏运行时指定画面切换效果的图片的文件夹。
必须是尺寸 640×480,灰色阶 256 色的 PNG 文件。按号码从小到大的顺序进行画面的切换。
自动地图元件说明

自动地图元件一般有如右图那样的 12 个基本样式。
A
代表样式。地图元件面板中显示的样式,在其它自动地图元件依存关系判定时使用。
B
边界样式。相同代表样式的自动地图元件紧邻放置在一起时,于边界侧作为边界线。
C
四角边界样式。
D
大范围边界带无边界中央区样式。

想以表现水面效果等动画作地图元件的话,基本结构组必须为横向排列配置。样式数量无限制。
地图动画元件必须是使用基本结构 32×32 的地图元件原样横向排列配置。
窗口皮肤说明

窗口皮肤是如右图那样的 192×128 的图片。通常是使用 32 位元色彩的 PNG 文件。
A
窗口的背景。128×128 的样式,会按照实际窗口的大小而扩大缩小。为了严谨,窗口周围缩小了 2 像素大小。这是为了能自然地看见圆角形窗口。而且一部分窗口中,背景部分只能以半透明显示。由于窗口为半透明,所以图片本身就没有作成半透明的必要。
B
窗口的边框及箭头。四角的 16×16 边框照这样显示,剩下的边框(边框的一部分)在窗口中按 16 像素的设计形状连接。箭头则作为窗口内容滚动的图标使用。
C
指令光标。在窗口内表现选择项目时使用。周围的 2 像素按长宽扩大缩小,剩下的按光标的大小平面显示。
D
暂停标记。在消息窗口中表示等待按钮输入的状态下使用。为 16×16 含 4 种图形的动画。
E
箭头光标。在战斗画面时选择角色和敌人时使用。显示为 32×32 的 2 种样式的交替。这虽然不是窗口的一部分,但放在这个文件夹中会很方便。
声音素材
可以使用 MID,OGG,WMA,MP3,WAV 这五种类型的音频文件(MID 格式仅限于 BGM 和 ME)。
BGM(Audio/BGM)
背景音乐(BackGround Music)。主要使用 MID 文件。
BGS(Audio/BGS)
背景声音(BackGround Sound)。主要使用 OGG 文件。
ME(Audio/ME)
效果音乐(Music Effect)。主要使用 MID 文件。
SE(Audio/SE)
效果声音(Sound Effect)。主要使用 OGG 文件。
各文件格式的特点,如以下所示。
MID    是以 DirectMusic Synthesizer 演奏 MIDI 文件。BGM 播放中, MIDI 数据中有控制切换的 111 号,作为乐曲播放到最后重播位置的标记。
OGG    是含有音质和压缩率均优良的音频压缩格式 Ogg Vorbis 数据的文件。但是,RPGXP 中不对应流再生,OGG 文件要全部读取后才开始播放,不适合播放时间较长的乐曲。
WMA    是 Windows Media Player 使用的音频压缩格式。以 DirectShow 播放。和 OGG 不同,对应流再生(一边读取数据一边再生流),所以能播放长时间的乐曲。
MP3    是一种普及率高的音频压缩格式。以 DirectShow 播放。特点和 WMA 相同。
WAV    是 Windows 标准的音频格式。通常无压缩的 WAV,Microsoft ADPCM 也能支持。
战斗计算式
RPGXP 默认的战斗系统,采用以下的计算式。
攻击方角色表示为 A,被攻击方角色以 B 表示。
第一命中率判定
普通攻击
第一命中率 = A 当前状态下的命中率 %
技能攻击
攻击力 F 为 1 以上(物理攻击)
第一命中率 = 技能的命中率 × A 当前状态下的命中率 % ÷ 100
攻击力 F 为 0(物理攻击以外)
第一命中率 = 技能的命中率
使用物品
第一命中率 = 物品的命中率
•    A 在正常状态下的命中率为 100。
必杀机率判定
普通攻击
必杀率 = 4 × A 的灵巧 ÷ B 的速度
技能攻击
必杀率 = 0
使用物品
必杀率 = 0
•    必杀率即奋力一击(通常会使敌方常受到较大的损伤)发生的机率,如果必杀率为 4 则表示每 4 个回合就出现一次奋力一击。
伤害计算
普通攻击
威力 = A 的攻击力 - (B 的物理防御 ÷ 2)
放大率 = 20 + A 的力量
分散度 = 15
•    威力的最小值:0
技能攻击
技能的威力值为正数
威力    =    技能的威力
    +    (A 的攻击力 × 技能的攻击力 F ÷ 100)
    -    (B 的物理防御 × 技能的物理防御 F ÷ 200)
    -    (B 的魔法防御 × 技能的魔法防御 F ÷ 200)
•    威力的最小值:0
技能的威力值为负数
威力 = 技能的威力
放大率    =    20
    +    (A 的力量 × 技能的力量 F ÷ 100)
    +    (A 的灵巧 × 技能的灵巧 F ÷ 100)
    +    (A 的速度 × 技能的速度 F ÷ 100)
    +    (A 的魔力 × 技能的魔力 F ÷ 100)
分散度 = 技能的分散度
使用物品
HP 回复量为负数
威力    =    - HP 回复量
    -    (B 的物理防御 × 物品的物理防御 F ÷ 20)
    -    (B 的魔法防御 × 物品的魔法防御 F ÷ 20)
•    威力的最小值:0
HP 回复量为正数
威力 = - HP 回复量
放大率 = 20
分散度 = 物品的分散度
伤害 = 威力 × 放大率 ÷ 20 × 属性修正 × 必杀修正 × 防御修正 ( ± 分散度 %)
•    属性修正:有攻击属性时,在 B 的属性有效度中选择最弱的进行修正,修正值如下。
A:200%,B:150%,C:100%,D:50%,E:0%,F:-100%
另外,攻击属性符合 B 防具的防御属性的,伤害减半,修正值为 1/2。
有多个相同防御属性的,减半效果要叠加。
•    必杀修正:伤害值为正数,奋力一击发动时修正值为 2。
•    防御修正:伤害值为正数,B 防御时修正值为 1/2。
第二命中率判定
伤害值为正数
B 为正常状态
回避力 = 8 × B 的速度 ÷ A 的灵巧 + B 的回避修正
普通攻击
第二命中率 = 100 - 回避力
技能攻击
第二命中率 = 100 -(回避力 × 技能的回避 F ÷ 100)
使用物品
第二命中率 = 100
B 附加有「不能回避攻击」状态
第二命中率 = 100
伤害值为负数(回复)
第二命中率 = 100
逃跑成功率
逃跑成功率 =50 × 角色的速度平均值 ÷ 敌人的速度平均值
脚本入门
在主菜单「工具」菜单中选择「脚本编辑器」,出现的那些英文字排列就是脚本。这个是 RPGXP 的关键部分,是掌管游戏实际运行的程序语言。虽然是简单的程序语言,但初学者要学习的话却是得花费大量的时间。首先得了解脚本是如何运作的,推荐先从基础学起。
这个「脚本入门」,是为已经学习 RGPXP 基本使用方法的人编写的。可以不具备计算机程序语言基础知识,但最低要对 RPGXP 的功能有一定程度的了解。
基础篇 开始
在基础篇,将一边完成单个短程序一边解说 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 条应该特别注意。
1.    第一个字符必须以小写英文字母或 _(下划线)开头。
2.    第二个字符开始可以使用英文字母、数字或 _(下划线)。
3.    不能使用保留字作变量的名称。
保留字是作为 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
双引号 "" 或单引号 '' 中间的部分,就作为字符串数据使用。
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 + " 没找到。")
像这样写也可以,使用内嵌表达式的方法会使读取程序变得很容易。
另外内嵌表达式和控制码一样,在单引号 '' 中间的字符串里使用也会无效。
基础篇 条件分歧
满足特定的条件与否,之后的动作会根据其不同而改变就叫作条件分歧。
比较运算符
在具体地学习处理条件分歧的方法之前,要先记住条件构成中使用的运算符。
下面 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 ~ end
if ~ 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
在满足特定条件期间进行循环的情况下使用 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)
回不到过去,去不了未来.我无路可逃.......
回复 支持 反对

使用道具 举报

10

主题

52

帖子

574

积分

⑤进阶

积分
574
 楼主| 发表于 2007-4-6 23:33:30 | 显示全部楼层
这个示例是每次运行都会显示出(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 类中定义共同的部分而不用在各个子类中重复定义。
基础篇 显示图片
在学习完对象后让我们稍稍轻松一下,来使用 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 表也称为关联数组。和数组不同的是,作为取出数值 的主键(相当于数组的附加码),可以使用任意的对象。 在 {} 符号中间排列多个单元就生成了一个哈希表。
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。
回不到过去,去不了未来.我无路可逃.......
回复 支持 反对

使用道具 举报

88

主题

5419

帖子

214748万

积分

版主

S素世上最伟大最华丽

Rank: 7Rank: 7Rank: 7

积分
2147483647
QQ
发表于 2007-4-6 23:38:31 | 显示全部楼层
你把F1帮助文档贴出来干嘛....
每个人都有的...就是按F1...
回复 支持 反对

使用道具 举报

10

主题

52

帖子

574

积分

⑤进阶

积分
574
 楼主| 发表于 2007-4-6 23:39:02 | 显示全部楼层
基础篇 定义类
基础篇的最后,让我们来学习定义新类的方法。
类的定义
直到今天,我们都是一直在使用 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
alex.name = "艾力克斯"
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 man.laugh(4)      # => "哇哈哈哈哈"
上述示例是,对新建实例调用 Wahaha 类的 laugh 方法,其中 super 能调用其父类 Hahaha 类的 laugh 方法。那么,最后一行调用 laugh 方法可以理解为 "哇" + "哈" * 4,于是输出结果就为 "哇哈哈哈哈"。
解读篇 数据库
在解读篇,我们会就预置脚本是做什么的作详细的说明。
本章将介绍 RPGXP 的数据库在脚本内是如何使用的。
$data_xxxx
请从脚本编辑器左侧目录,查找名称为 Scene_Title 的组。在这个组的右侧窗口中,会发现如下的部分。这个是在显示游戏标题画面之前运行的脚本。
    # 载入数据库
    $data_actors        = load_data("Data/Actors.rxdata")
    $data_classes       = load_data("Data/Classes.rxdata")
    $data_skills        = load_data("Data/Skills.rxdata")
    $data_items         = load_data("Data/Items.rxdata")
    $data_weapons       = load_data("Data/Weapons.rxdata")
    $data_armors        = load_data("Data/Armors.rxdata")
    $data_enemies       = load_data("Data/Enemies.rxdata")
    $data_troops        = load_data("Data/Troops.rxdata")
    $data_states        = load_data("Data/States.rxdata")
    $data_animations    = load_data("Data/Animations.rxdata")
    $data_tilesets      = load_data("Data/Tilesets.rxdata")
    $data_common_events = load_data("Data/CommonEvents.rxdata")
    $data_system        = load_data("Data/System.rxdata")
作一下说明,这段的意思是从 RPGXP 保存的文件中读取数据库信息,并在脚本中代入到各种数据变量为其赋值。这些以 $ 符号开头的变量是全局变量,因此这些数据在后面其它的脚本中也能引用。
其中的 load_data 是 RGSS 内部函数 之一,是一个从指定文件中读取数据的函数。比如第一行,就是表示从 Date 文件夹中的 Actors.rxdata 文件中读取数据,并代入全局变量 $data_actors 中为其赋值。
数据库的内容
各个对象的具体情况如下所示。
变量名称    内容    所属类
$data_actors    角色    RPG::Actor 数组

$data_classes    职业    RPG::Class 数组

$data_skills    特技    RPG::Skill 数组

$data_items    物品    RPG::Item 数组

$data_weapons    武器    RPG::Weapon 数组

$data_armors    防具    RPG::Armor 数组

$data_enemies    敌人    RPG::Enemy 数组

$data_troops    队伍    RPG::Troop 数组

$data_states    状态    RPG::State 数组

$data_animations    动画    RPG::Animation 数组

$data_tilesets    图块    RPG::Tileset 数组

$data_common_events    公共事件    RPG::CommonEvent 数组

$data_system    系统    RPG::System

从角色到公共事件的这 12 种数据,是和数据库中标记的号码相对应的数组。但是 RPGXP 的数据 ID 是从 1 号开始的,为了使数据 ID 和数组的附加码一致,所以数组的第一个(0 号)单元为 nil。
数据库的使用
比如下一个脚本是表示角色中 1 号人物的名称。
$data_actors[1].name
下一个脚本是表示敌人中 2 号敌人的 MaxHP。
$data_enemies[2].maxhp
下一个脚本是表示物品中 3 号物品指定图标的文件名。
$data_items[3].icon_name
下一个脚本是表示系统中 4 号开关的名称。
$data_system.switches[4]
这些要点,请在参考中参照数据的属性(变量)名称来查看。想以 p 函数显示这些数据的话,可以使用事件指令的「脚本」命令来执行,这样会很方便。
解读篇 游戏对象
数据库,原则上其中的数据在游戏中是不变的,不会进行数据的重新写入。与之相对,比如地图画面上人物的移动等,这种情况下发生数据改变的是游戏对象。
$game_xxxx
在 Scene_Title 组中,command_new_game 方法下有如下的部分。这个是在标题画面中选择「新游戏」时运行的脚本。
    # 生成各种游戏对像
    $game_temp          = Game_Temp.new
    $game_system        = Game_System.new
    $game_switches      = Game_Switches.new
    $game_variables     = Game_Variables.new
    $game_self_switches = Game_SelfSwitches.new
    $game_screen        = Game_Screen.new
    $game_actors        = Game_Actors.new
    $game_party         = Game_Party.new
    $game_troop         = Game_Troop.new
    $game_map           = Game_Map.new
    $game_player        = Game_Player.new
和数据库的 $data_xxxx 相同,这些也是全局变量。后面是生成 Game_Xxxx 名称类的实例,并代入到变量为其赋值。这些 Game_Xxxx 名称应该认识吧。在脚本编辑器组列表里,最上面的一些组就是这样的名称。也就是说,这些组定义的类在这里被实例化了。
游戏对象的内容
各个对象的具体情况如下所示。和数据库的情况不同,这些对象所属的类不是 RGSS 预先设定的类,而是在脚本中定义的。
变量名称    内容    所属类
$game_temp    临时数据    Game_Temp
$game_system    系统数据    Game_System
$game_switches    开关    Game_Switches
$game_variables    变量    Game_Variables
$game_self_switches    独立开关    Game_SelfSwitches
$game_screen    画面效果    Game_Screen
$game_actors    角色排列    Game_Actors
$game_party    同伴    Game_Party
$game_troop    队伍    Game_Troop
$game_map    地图    Game_Map
$game_player    主角    Game_Player
这些类原则上只用于提供数据构造,并不具备显示图标或处理键盘输入的功能。但是 Game_Player 类为了方便,含有方向键的移动和决定键开始事件等处理。
其他关联类
上述是从全局变量中直接使用的游戏对象,其实这些对象内部,还进一步包含一些其他类的对象。如下所示。
类    内容    说明
Game_Picture    图片    Game_Screen 的内部使用
Game_Actor    角色    Game_Actors 的内部使用
Game_Enemy    敌人    Game_Troop 的内部使用
Game_CommonEvent    公共事件    Game_Map 的内部使用
Game_Event    地图事件    Game_Map 的内部使用
另外,还有下面这两个重要的类。这两个类在脚本中的数量非常多,被分割成多个组定义。
类    内容    说明
Game_Battler    战斗者    Game_Actor、Game_Enemy 的父类
Game_Character    人物    Game_Player、Game_Event 的父类
所谓父类,有继承的意思。因为在角色和敌人、主角和事件中各自有共同的性质,所以把这些共同的部分作为一个类。
最后 Game_Xxxx 系列类只剩下一个了。
类    内容    说明
Game_BattleAction    行动    Game_Battler 的内部使用
这个是管理战斗中行动的类,在战斗者内部使用。
这个「脚本入门」是以大致掌握预置脚本全体概貌为目的,所以本章所提及类的具体内容没有各自说明。但是在实际挑战脚本对脚本进行改造时,这些内容定义的是什么将会十分重要。在预置脚本中都有一些注释说明,一开始可能不太明白,但推荐有兴趣的人仔细看看。
解读篇 活动块的管理
游戏对象本身,没有任何在画面中显示自身的方法。所以建立反映游戏对象内容,在画面中显示图片的类就很必要。
活动块
在脚本编辑器左侧的组列表中,Game_Xxxx 的部分已经介绍过了。现在让我们来看看 Sprite_Xxxx 名称的组吧。这些组的名称与其定义的类的名称相对应,如下所示。
类    内容    父类
Sprite_Character    角色显示用    RPG::Sprite

Sprite_Battler    战斗显示用    RPG::Sprite

Sprite_Picture    显示图片用    Sprite

Sprite_Timer    显示计时器用    Sprite

这些类,是继承于基础篇中学习过的 Sprite 类,或其高功能版 RPG::Sprite 类,具有在实际中显示各图片活动块的功能。
名活动块类的实例实时监视对应的游戏对象,其状态发生变化的话,会自动的在画面中反映。比如 Sprite_Character 是角色显示用的活动块,会监视 Game_Character 的被继承类的实例。人物在地图上稍微移动一下,这个动作会立即在活动块中反映。实际上这个「反映」的处理是调用 update 名称的方法时进行的。调用该方法在下面的活动块组中也有介绍。
活动块组
在活动块组中有下面两个类。
类    内容
Spriteset_Map    地图画面显示用
Spriteset_Battle    战斗画面显示用
这些类,统一管理构成各个画面的几乎全部图片(窗口和光标除外)。当然包括前面介绍的活动块类,地图本身和天气效果等,以及一切能收集到的图片对象,调用 update 名称的方法,就会在游戏环境中更新全部的图片。
调用活动块组的 update 方法,将在本篇后面一章场景类中说明。
这些类中,场所入口和活动块 Z 座标的概念承担了重要的任务。这些关系到显示各图片的优先顺序。请同时参照 Viewport 类的说明。
Spriteset_Map
地图画面活动块组的构成如下所示(数字是 Z 座标)。
@viewport3 (5000)    -    画面的闪烁
@timer_sprite (500)    -    计时器
@viewport2 (200)    @picture_sprites (1..50)    图片
@viewport1 (0)    @fog (3000)    雾
    @weather (1000)    天气
    @character_sprites (0..800)    人物
    @tilemap (0..800)    地图
    @panorama (-1000)    远景
Spriteset_Battle
战斗画面活动块组的构成如下所示(数字是 Z 座标)。
@viewport4 (5000)    -    画面的闪烁
@timer_sprite (500)    -    计时器
@viewport3 (200)    @picture_sprites (51..100)    图片
@viewport2 (101)    @actor_sprites (1..4)    战斗者(角色)
@viewport1 (0)    @weather (1000)    天气
    @enemy_sprites (1..320)    战斗者(敌人)
    @battleback_sprite (0)    战斗背景
解读篇 窗口的管理
从信息窗口和状态窗口开始,RPG 中必须要使用大量的窗口。现在我们来介绍这些窗口是如何管理的。
基本窗口
脚本中以 Window_Xxxx 命名的组有很多吧。根据惯例它们的名称与其定义的类名是相对应的。其中有两个尤其重要,就是最上面的那两个类。
类    内容    父类
Window_Base    基本窗口    Window

Window_Selectable    项目选择窗口    Window_Base
首先,必须要知道在 RGSS 中 Window 类是已预先设定好的。这个类在基础篇中没有提及,负责窗口的边框,背景的描绘以及内容的滚动等这些比较低级的处理,是一个非常底层的类。
Window_Base 类是这个 Window 类的子类,负责在 RPG 的窗口中添加必要的基本功能。这个类最重要的功能,是自动读取为当前窗口设定的皮肤图片文件。而且,各种文字颜色也是由这个类定义的。
Window_Selectable 类是 Window_Base 的子类,添加了检测键盘按钮的输入及移动光标的处理。比如说物品的选择,游戏中物品选择窗口会频繁的使用。这个类定义了这些窗口的一些共同功能。实际的光标移动处理,是调用 update 名称的方法时进行的。
调用窗口的 update 方法,将在本篇后面一章场景类中说明。
窗口的应用
现在我们来一起介绍窗口系列剩下的其它类。这些类,全都是从 Window_Base 类或 Window_Selectable 类继承而来的。
类    内容    父类
Window_Command    指令窗口(泛用)    Window_Selectable
Window_Help    帮助窗口    Window_Base
Window_Gold    显示金钱窗口    Window_Base
Window_PlayTime    菜单画面用 游戏时间窗口    Window_Base
Window_Steps    菜单画面用 步数窗口    Window_Base
Window_MenuStatus    菜单画面用 状态窗口    Window_Selectable
Window_Item    物品选择窗口    Window_Selectable
Window_Skill    特技选择窗口    Window_Selectable
Window_SkillStatus    特技画面用 状态窗口    Window_Base
Window_Target    物品、特技画面用 对象选择窗口    Window_Selectable
Window_EquipLeft    装备画面用 左侧窗口    Window_Base
Window_EquipRight    装备画面用 右侧窗口    Window_Selectable
Window_EquipItem    装备画面用 物品窗口    Window_Selectable
Window_Status    状态画面用 状态窗口    Window_Base
Window_SaveFile    存档、读档画面用 文件窗口    Window_Base
Window_ShopCommand    商店画面用 商品选择窗口    Window_Selectable
Window_ShopBuy    商店画面用 购买窗口    Window_Selectable
Window_ShopSell    商店画面用 出售窗口    Window_Selectable
Window_ShopNumber    商店画面用 数量输入窗口    Window_Base
Window_ShopStatus    商店画面用 状态窗口    Window_Base
Window_NameEdit    名称输入画面用 名称窗口    Window_Base
Window_NameInput    名称输入画面用 文字选择窗口    Window_Base
Window_InputNumber    数值输入窗口    Window_Base
Window_Message    信息窗口    Window_Selectable
Window_PartyCommand    战斗画面用 同伴指令窗口    Window_Selectable
Window_BattleStatus    战斗画面用 状态窗口    Window_Base
Window_BattleResult    战斗画面用 结果显示窗口    Window_Base
Window_DebugLeft    调试画面用 左侧窗口    Window_Selectable
Window_DebugRight    调试画面用 右侧窗口    Window_Selectable
箭头光标
所谓箭头光标,是在战斗画面中选择角色和敌人作为行动对象时使用的光标。它的性质更接近于窗口,为了方便所以就放在这里介绍。
类    内容    父类
Arrow_Base    箭头光标    Sprite

Arrow_Enemy    敌人选择用 箭头光标    Arrow_Base
Arrow_Actor    角色选择用 箭头光标    Arrow_Base
Arrow_Base 类,包含光标图像的忽明忽暗等基本处理。Arrow_Enemy、Arrow_Actor 类分别参照 $game_troop 和 $game_party 等游戏对象,根据方向键的左右输入执行选择战斗者的处理。和窗口一样,忽明忽暗和移动光标的处理是调用 update 名称的方法时进行的。
解读篇 编译器
现在我们来介绍 RPGXP 的事件指令在脚本内是如何操作的。
Interpreter 类
事件指令中有「显示文章」和「场所移动」等变化丰富的命令,把这些指令组合起来就能操控游戏的进行。但是,事件指令列表,在脚本内并不是 RPG::EventCommand 类实例简单的排列。要解释这个事件指令的数据,执行该任务的就是编译器。
在脚本左侧的目录中有名称为 Interpreter 1~7 的组,这些组用来分割定义 Interpreter 这个巨大的类。该类在预置脚本定义的类中是个相当大规模的类。
这个类的实例属于以下的这 3 个类。
•    Game_System
•    Game_Event
•    Game_CommonEvent
这样可以认为是在游戏对象的内部使用,编译器广义上也可以说成是游戏对象的一种。
个体事件和公共事件有必要保持编译器实现并列处理。通常的(非并列)事件执行常规,也就是主要的编译器是包含 Game_System 类中。
事件代码
各事件指令中都分配有如下表那样代码。Interpreter 类根据这些代码来辨别事件指令,并调用各自进行处理的方法。
101: 显示文章
102: 显示选择项
103: 数值输入的处理
104: 更改文章选项
105: 按钮输入的处理
106: 等待
108: 注释
111: 条件分歧
112: 循环
113: 中断循环
115: 中断事件处理
116: 暂时消除事件
117: 公共事件
118: 标签
119: 标签跳转
121: 开关操作
122: 变量操作
123: 独立开关操作
124: 计时器操作
125: 增减金钱
126: 增减物品
127: 增减武器
128: 增减防具
129: 替换队员
131: 更改窗口外观
132: 更改战斗 BGM
133: 更改战斗结束 ME
134: 更改禁止存档
135: 更改禁止菜单
136: 更改禁止遇敌    201: 场所移动
202: 设置事件位置
203: 画面卷动
204: 更改地图设置
205: 更改雾的色调
206: 更改雾的不透明度
207: 显示动画
208: 更改透明状态
209: 设置移动路线
210: 等待移动结束
221: 准备渐变
222: 执行渐变
223: 更改画面色调
224: 画面闪烁
225: 画面震动
231: 显示图片
232: 移动图片
233: 旋转图片
234: 更改图片色调
235: 图片消失
236: 天气设置
241: 演奏 BGM
242: 淡出 BGM
245: 演奏 BGS
246: 淡出 BGS
247: 记忆 BGM / BGS
248: 还原 BGM / BGS
249: 演奏 ME
250: 演奏 SE
251: 停止 SE    301: 战斗处理
302: 商店处理
303: 名称输入处理
311: 增减 HP
312: 增减 SP
313: 更改状态
314: 完全回复
315: 增减 EXP
316: 增减等级
317: 增减能力值
318: 增减特技
319: 变更装备
320: 更改角色姓名
321: 更改角色职业
322: 更改角色图形
331: 增减敌人 HP
332: 增减敌人 SP
333: 更改敌人状态
334: 敌人出现
335: 敌人变身
336: 敌人完全回复
337: 显示动画
338: 伤害处理
339: 强制行动
340: 战斗中断
351: 呼叫菜单画面
352: 呼叫存档画面
353: 游戏结束
354: 返回标题画面
355: 脚本
事件代码就是上述这些,但也不是全部,比如「显示文章」指令下面的第二行分配的是 401 代码,这些存在特殊的情况。但是,事件指令的处理本身因为在预置的 Interpreter 类中完成,所以没必要在意这样的内部代码。只要事先记住这些就 OK 了。
解读篇 场景类
负责地图画面、菜单画面等各种画面处理的就是场景类。
场景类的种类
各场景类对应的画面如下所示。除 Scene_Battle 类分割定义外,其它的类名和组名都是一一对应的。另外 Scene_File 类作为 Scene_Save 和 Scene_Load 的父类而定义,没有包含在这个表中。
类    内容
Scene_Title    标题画面
Scene_Map    地图画面
Scene_Menu    菜单画面
Scene_Item    物品画面
Scene_Skill    特技画面
Scene_Equip    装备画面
Scene_Status    状态画面
Scene_Save    存档画面
Scene_Load    读档画面
Scene_End    游戏退出画面
Scene_Battle    战斗画面
Scene_Shop    商店画面
Scene_Name    名称输入画面
Scene_Gameover    游戏结束画面
Scene_Debug    调试画面
场景类的结构
场景类的实例是保存在 $scene 名称的全局变量中。这个变量只要值不是 nil 就能调用 main 名称的方法,是继续游戏运行的结构。典型的场景类的构架如下所示。
class Scene_Xxxx
  def main
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end
    end
    Graphics.freeze
  end
  def update
  end
end
Graphics.freeze 和 Graphics.transition,可以考虑成与各个事件指令的「准备渐变」和「执行渐变」相同的意思。这些方法的详细内容请参照 Graphics 模块的说明。主循环是以这些方法包围的,在画面切换时使用渐变效果。
if $scene != self 是「如果全局变量 $scene 指定的对象不是自己的话」的意思,即「切换到其它画面的情况」(self 是表示自身对象的伪变量)。另外,Input.update 是更新游戏手柄和键盘输入信息的方法。输入关联的处理请参照 Input 模块的说明。
还有,基础篇中曾介绍过的下面这个形式是 RGSS 游戏运行的基本结构。场景类的 main 方法那样复杂的处理,都是在这个形式上发展而来的。
loop do
  Graphics.update
end
Main 组
终于到最后的组了。到现在为止上面的组全都是关于类的定义,实际上,可以认为真正脚本的运行是从这里开始的。Main 组除去注释只剩下下面的这 12 行。
begin
  Font.default_name = (["黑体"])
  Graphics.freeze
  $scene = Scene_Title.new
  while $scene != nil
    $scene.main
  end
  Graphics.transition(20)
rescue Errno::ENOENT
  filename = $!.message.sub("No such file or directory - ", "")
  print("找不到文件 #{filename}。")
end
begin ~ rescue ~ end 是异常处理的句法。这里,是脚本的运行中如果发生「找不到文件」的异常情况时指定转移执行 rescue 以下的处理。即显示「找不到文件 XXX」的错误信息后结束程序。异常处理在预置脚本中也可以不使用,所以没有记住其使用方法也不要紧。
Graphics.freeze 和 Graphics.transition 在先前就已介绍过了。其中最先是进行「准备渐变」,准备从乌黑的状态逐渐显示到标题画面。最后的 Graphics.transition 是相反的过程又渐变到乌黑状态结束。参数指定为 20,为一般延迟的渐变。其中第二行是设置系统默认字体。
还剩下 4 行。先是生成负责标题画面处理的 Scene_Title 类的实例,设定全局变量 $scene。然后和前面讲过的那样 $scene 变量只要值不是 nil 就调用 main 名称的方法。
最后
非常感谢大家。「脚本入门」到这里就结束了。
迄今学习到的知识,参照 RGSS 参考,应该就能明白的解读预置脚本了。没有必要绝对理解 RGSS 的全部。有兴趣的话可以到脚本中看看,是不是很自然的产生了要改造脚本的想法。
可能性是无限的。使用 RGSS 做什么,一切随您。
回不到过去,去不了未来.我无路可逃.......
回复 支持 反对

使用道具 举报

10

主题

52

帖子

574

积分

⑤进阶

积分
574
 楼主| 发表于 2007-4-6 23:40:14 | 显示全部楼层
RGSS 参考
RGSS(Ruby Game Scripting System),中文意思是 Ruby 游戏脚本系统,是应用面向对象的脚本语言 Ruby 开发 Windows 2D 游戏的系统。使用 RGSS,就和 C 语言等程序语言那样简单,能创建完全原创的游戏系统。Ruby 是一种初学者也能很容易使用,并且功能强大的高级语言。
关于本文档
本文档是从 Ruby 的参考手册上摘录下使用 RGSS 的必要信息,加上关于 RGSS 独特方法的解说重编辑而成。对于 RGSS 的用户,在游戏程序设计方面不重要的部分进行了大幅删减,对各处描述也稍作了修改。因此在描述上可能会出现不正确的情况。作为 Ruby 的参考,请注意那些非常简单的东西。
原始的 Ruby 和本文档的原文可在 Ruby 的官方网页 http://www.ruby-lang.org/ 上获得。想要了解关于 Ruby 更详细的信息,请参照官方网页。
关于用户支持
关于使用脚本编辑进行游戏制作的方法,或由此引起的任何问题,Enterbrain 公司用户支持中心将不会受理。而且在 Ruby 脚本方面,本公司和松本先生没有支持的义务。编辑的时候请充分理解 RGSS 的功能后再行尝试。
无论是已对 Ruby 已达到某种度还是网页运营人员亦或其他使用者,上述网页、其他关于 Ruby 的信息、支持网页等,还请多多参考。
RGSS 的说明
负责地图画面、菜单画面等各种画面处理的就是场景类。
场景类的种类
各场景类对应的画面如下所示。除 Scene_Battle 类分割定义外,其它的类名和组名都是一一对应的。另外 Scene_File 类作为 Scene_Save 和 Scene_Load 的父类而定义,没有包含在这个表中。
类    内容
Scene_Title    标题画面
Scene_Map    地图画面
Scene_Menu    菜单画面
Scene_Item    物品画面
Scene_Skill    特技画面
Scene_Equip    装备画面
Scene_Status    状态画面
Scene_Save    存档画面
Scene_Load    读档画面
Scene_End    游戏退出画面
Scene_Battle    战斗画面
Scene_Shop    商店画面
Scene_Name    名称输入画面
Scene_Gameover    游戏结束画面
Scene_Debug    调试画面
场景类的结构
场景类的实例是保存在 $scene 名称的全局变量中。这个变量只要值不是 nil 就能调用 main 名称的方法,是继续游戏运行的结构。典型的场景类的构架如下所示。
class Scene_Xxxx
  def main
    Graphics.transition
    loop do
      Graphics.update
      Input.update
      update
      if $scene != self
        break
      end
    end
    Graphics.freeze
  end
  def update
  end
end
Graphics.freeze 和 Graphics.transition,可以考虑成与各个事件指令的「准备渐变」和「执行渐变」相同的意思。这些方法的详细内容请参照 Graphics 模块的说明。主循环是以这些方法包围的,在画面切换时使用渐变效果。
if $scene != self 是「如果全局变量 $scene 指定的对象不是自己的话」的意思,即「切换到其它画面的情况」(self 是表示自身对象的伪变量)。另外,Input.update 是更新游戏手柄和键盘输入信息的方法。输入关联的处理请参照 Input 模块的说明。
还有,基础篇中曾介绍过的下面这个形式是 RGSS 游戏运行的基本结构。场景类的 main 方法那样复杂的处理,都是在这个形式上发展而来的。
loop do
  Graphics.update
end
Main 组
终于到最后的组了。到现在为止上面的组全都是关于类的定义,实际上,可以认为真正脚本的运行是从这里开始的。Main 组除去注释只剩下下面的这 12 行。
begin
  Font.default_name = (["黑体"])
  Graphics.freeze
  $scene = Scene_Title.new
  while $scene != nil
    $scene.main
  end
  Graphics.transition(20)
rescue Errno::ENOENT
  filename = $!.message.sub("No such file or directory - ", "")
  print("找不到文件 #{filename}。")
end
begin ~ rescue ~ end 是异常处理的句法。这里,是脚
启动游戏

一般情况下,双击游戏启动文件 Game.exe(Windows 文件夹选项「隐藏已知文件类型的扩展名」激活时,只显示 Game)的图标运行游戏。该文件所在的文件夹称为「游戏文件夹」。
在 RPGXP 编辑状态下,可以从菜单的「游戏测试」或数据库「队伍」的「战斗测试」启动。这些情况下可以使用调试模式,自动加载 Ruby 的内部变量 $DEBUG。战斗测试的情况下 $DEBUG 变量也自动为 true。
游戏如何运行在结构设定文件 Game.ini 中指定。
Game.ini
Game.ini 文件是 RPGXP 自动生成、更新的,可以用记事本等程序打开直接编辑。
例如:
[Game]
Library=RGSS100J.dll
Scripts=Data\\Scripts.rxdata
Title=RubyQuest
RTP1=Standard
RTP2=
RTP3=
Library
RGSS 自身程序的 DLL 名。这个文件通常被安装在 Windows 的系统文件夹中。
如果游戏文件夹中也指定了 DLL 的话,就优先使用游戏文件夹中的 DLL。
Scripts
保存脚本数据的文件。指定其在游戏文件夹中的相对路径。
Ruby 扩展名为 .rb 的文本文件通常能作为脚本直接运行,然而 RGSS 中使用独特的形式将脚本压缩成了一个单一文件。这个文件如果不使用 RPGXP 的脚本编辑器是无法编辑的。其中数据由多个组构成,按照目录的顺序从上到下依次运行。
Title
游戏标题。这个名称会显示在游戏窗口标题栏中。
RTP1
RTP2
RTP3
该游戏中所使用 RGSS-RTP 的登记名。未安装指定 RTP 的话会显示错误提示。
一个 RTP 都不指定,而且游戏文件夹中包含 RGSS 的 DLL(用 Library 指定),这样就制作成了不需要安装 RTP 的游戏。这个发布方法是不推荐的,然而在使用的素材大部分是原创的情况下,使用该方法或许会有很多优点。
RGSS-RTP
RTP(RunTime Package)是一种减小被发布游戏数据容量的构件。RTP 中包含有许多游戏共同使用且被大量应用的图片、声音等素材。在玩游戏的时候,这些素材数据预先作为共同文件被安装,因此没有必要重复多次下载。
RGSS-RTP 的构成文件,在游戏程序的下列内部方法中使用,且只有当游戏文件夹中同时存在时才会有效。使用这些方法时给予的文件名,可以全部省略扩展名(“.png”和“mid”等,程序会自动判断)。
Bitmap.new、Audio.bgm_play、Audio.bgs_play、Audio.me_play、Audio.se_play、Graphics.transition
安装信息
RPGXP 标准的 RTP 只限于“Standard”一种,但也可以同时使用多个 RTP。如果有制作安装程序的知识,并依照下面的规则,就可以自己独立制作 RTP。但是这种情况下,尽量不要使用“Extension”等广泛应用的通用名称作为 RTP 的登记名。因为这样就有可能会与将来公司提供的新 RTP 名称冲突。
RTP 是默认安装在下面目录中。
[CommonFilesFolder]\\Enterbrain\\RGSS\\[RTPName]
这里的 [CommonFilesFolder] 是 Windows 的「公共文件文件夹」,[RTPName] 是 RTP 的登记名。实际中会是下面那样的路径名。
C:\\Program Files\\Common Files\\Enterbrain\\RGSS\\Standard
RTP 的安装程序制作,要在注册表键“HKEY_LOCAL_MACHINE\\SOFTWARE\\Enterbrain\\RGSS\\RTP”中新建一个字符串数值(数值名称设为该 RTP 的登记名),数值数据设定为该 RTP 的路径名。这个键中设定的字符串,RGSS 会作为 RTP 来识别。
加密档案文件
加密档案文件是使别人很难再对游戏的内容进行分析和改造的构件。通常为 Game.rgssad 名称的文件,这个文件中包含全部数据文件和图片文件(不包含声音文件)。在 RPGXP 进行「压缩游戏数据」时选择「生成加密档案文件」选项就可作成。
加密档案文件内部的文件,在游戏库的下列内部方法中使用,并且能像游戏文件夹中的文件一样地访问。
load_data、Bitmap.new、Graphics.transition
游戏文件夹中存在加密档案文件的情况下,Game.ini 中 Sctipts 定义的脚本数据(通常为 Data\\Scripts.rxdata)必须从档案文件内部读取。这样是为了防止通过外部的脚本来读取档案内部的文件。
功能的性质,加密档案文件的内部格式不会公开。谢绝对此进行分析。
其他
文字编码
RGSS 处理文字的编码是 UTF-8 。UTF-8 是 Unicode(能表现全世界文字的文字编码)编码方法的一种。
Ruby 内部变量 $KCODE(这个参考中没有说明),预先就设定为 ’UTF8’。RPGXP 输出的脚本数据和其他字符串数据都是用 UTF-8 编码的。
但是 Unicode 不兼容 Windows 98 / Me,因此如果是 Windows 98 / Me 的话不推荐在游戏中使用 Unicode 文字。
平滑模式
RGSS 的游戏是以每秒 20 帧速率运行为标准,选择游戏属性中的「平滑模式」选项的话,画面就会变成以每秒 40 帧速率运行。无论「平滑模式」的设定如何,脚本内部总是以每秒 40 帧速率运行。RPGXP 中设定有等待等数值,很多情况下使用 2 倍速率还请多注意。
帧率可以使用 Graphics.frame_rate 更改。
属性
在游戏库的说明中会使用到「属性」这个术语。这并不是 Ruby 语言的概念,而是 RGSS 的独特用语。
例如精灵的 X 座标(Sprite#x),可以像下例那样对其进行取得和设定。
x = sprite1.x         # 取得
sprite2.x = x + 32    # 设定
像这个 x 那样,可以使用赋值运算符进行取得(读取)和设定(写入)两方面运算的方法,方便起见就称之为属性。
本的运行中如果发生「找不到文件」的异常情况时指定转移执行 rescue 以下的处理。即显示「找不到文件 XXX」的错误信息后结束程序。异常处理在预置脚本中也可以不使用,所以没有记住其使用方法也不要紧。
Graphics.freeze 和 Graphics.transition 在先前就已介绍过了。其中最先是进行「准备渐变」,准备从乌黑的状态逐渐显示到标题画面。最后的 Graphics.transition 是相反的过程又渐变到乌黑状态结束。参数指定为 20,为一般延迟的渐变。其中第二行是设置系统默认字体。
还剩下 4 行。先是生成负责标题画面处理的 Scene_Title 类的实例,设定全局变量 $scene。然后和前面讲过的那样 $scene 变量只要值不是 nil 就调用 main 名称的方法。
最后
非常感谢大家。「脚本入门」到这里就结束了。
迄今学习到的知识,参照 RGSS 参考,应该就能明白的解读预置脚本了。没有必要绝对理解 RGSS 的全部。有兴趣的话可以到脚本中看看,是不是很自然的产生了要改造脚本的想法。
可能性是无限的。使用 RGSS 做什么,一切随您。
Ruby 的语法 字句构造和表达式
在 Ruby 中大写字母和小写字母是有区别的,注意不要弄错了。除外标识符和一部分字面值中间,任意的地方都能放置空字符和注释。空字符包括 space、tab、垂直 tab、backspace、回车、换页。换行比较特殊,换行如为一行的内容转到下一行继续就作为空字符,除此之外解释为语句的切分。
标识符
例子:
foobar
ruby_is_simple
Ruby 的标识符,以字母或“_”开始,后面是字母、“_”或数字。没有长度的限制。
注释
例子:
# this is a comment line
除在字符串中间以外,其他 # 符号后面的一整行文字会认定为注释。
保留字
保留字就是下面这些。
BEGIN    class    ensure   nil      self     when
END      def      false    not      super    while
alias    defined? for      or       then     yield
and      do       if       redo     true
begin    else     in       rescue   undef
break    elsif    module   retry    unless
case     end      next     return   until
保留字不能作为类名称、变量名称等使用。但是以接头符 $、@ 等开头就不再是保留字。而且在 def 和调用方法的对象后面使用的话,如明确系方法名称就可以作为方法使用。
表达式
例子:
true
(1+2)*3
foo()
if test then ok else ng end
包括变量和常量、字面值、运算式和控制结构等全部称为「表达式」。
排列这些表达式就成为 Ruby 的程序。表达式和表达式之间以分号(;)或换行分开。但是,紧跟反斜线符号(\\)的换行并非分隔符,而是表示到下一行继续。
还可以使用括号将表达式括起来进行群组化。
Ruby 的语法 变量和常量
Ruby 变量和常量的种类包括全局变量、实变量、局部变量和常量,都是靠其名称的第一个字符来区分的。通常变量的第二个字符开始是使用字母、数字或“_”,内部变量中有一部分是「’$’ + 1 个符号」的变量(请参考内部变量)。
变量和常量指定的是特定对象。变量和常量的赋值,是为了指定新的对象进行操作。所以代入对象不会生成新的拷贝。
全局变量
例子:
$foobar
以“$”开头的变量就是全局变量,程序的任何地方都能引用(因此应用时要特别注意)。全局变量没有必要事先声明。引用尚未初始化的全局变量其值为 nil。
实变量
例子:
@foobar
以“@”开头的变量就是实变量,属于特定的对象。实变量可以在其类或子类的方法中引用。引用尚未初始化的实变量其值为 nil。
局部变量
例子:
foobar
以小写字母或“_”开头的标识符就是局部变量或方法调用。
在局部变量作用域(类、模块、方法定义的部分)中小写字母开头的标识符要初始赋值,这个赋值属于局部变量的声明。引用未声明的标识符会当作无参数的方法调用。
常量
例子:
FOOBAR
以大写字母开头的标识符就是常量。常量的定义(和初始化)就是进行代入赋值,但是在方法里是不能定义的。访问未定义的常量会发生 NameError 异常。
常量可在类/模块中定义,除在该类/模块中可以引用外,该类的子类或嵌套该模块的类/模块中也能引用该常量。从外部引用常量要用到“::”运算符。
class Foo
  FOO = ’FOO’
end

class Bar < Foo
  p FOO             # => "FOO"
end

p Foo::FOO          # => "FOO"
而且,类和模块的名称也要和常量同时使用。
类和嵌套外侧存在同名常数时,会先引用嵌套外侧的常数。也就是说,引用常数时会先搜索嵌套关系的外侧,然后才会按照继承关系向上搜索。而顶层常数定义并不是位于嵌套外侧,所以在搜索了继承关系之后才能找到它。可见顶层常数的优先度很低。
另外,在类定义表达式生成类对象的同时,还会将类对象赋值给一个与该类同名的常数。从语法上讲,引用类名也就是引用该常数。若对与父类常数同名的常数进行赋值的话,则意味着在该类中定义一个新常数,而并不会对父类常数进行赋值。
伪变量
在普通变量以外,还有一种被称为伪变量的特殊变量。
self
当前方法的执行对象本身。
nil
NilClass 类唯一的实例。表示伪。
true
TrueClass 类唯一的实例。表示真。
false
FalseClass 类唯一的实例。表示伪。
不能更改伪变量的值。为伪变数代入赋值会出现语法错误。
Ruby 的语法 字面值
像数字 1 和字符串 "hello world" 那样 Ruby 程序中直接描述的内容就是字面值。
数字字面值
123
0d123
整数
-123
带符号整数
123.45
浮点数
浮点数是不能写成像 .1 那样直接以“.”开头的样式。必须要写成 0.1。
1.2e-3
浮点数
0xffff
十六进制整数
0b1011
二进制整数
0377
0o377
八进制整数
在数字字面值中可以插入“_”。ruby 编译器会忽略“_”,不会对其作特别的处理。这样在那些数值很大的数字中加入“_”,会很方便地快速看清楚其位数而了解其值的大小。但应特别注意的是,“_”加在字面值的开头(若在字面值开头则包括“+、-”号与字面值间的位置)和结尾,或连续写入多个“_”都是不充许的(会误认成局部变量或方法调用)。
1_000_000_000   # => 1000000000
0xffff_ffff     # => 0xffffffff
字符串字面值
例子:
"this is a string expression\\n"
’this is a string expression’
以双引号或单引号包围的字符串是 String 类的实例。
以双引号包围的字符串控制码和内嵌表达式都是有效的。而以单引号包围的字符串,除了 \\\\(反斜线符号本身)、\\’(单引号)和行尾的 \\(忽略换行)外,其它的在字符串中将不作处理。
中间夹有空字符的多个字符串字面值会被当作是一个字符串字面值来处理。
p "foo" "bar"   # => "foobar"
控制码
反斜线符号 \\ 是字符串中的特殊文字,当作控制码使用。
\\t
Tab(0x09)
\\n
换行(0x0a)
\\r
回车(0x0d)
\\f
换页(0x0c)
\\s
空格(0x20)
\\nnn
八进制代码(n 是 0-7)
\\xnn
十六进制代码(n 是 0-9,a-f)
内嵌表达式
在双引号(")包围的字符串和正则表达式中,可以使用“#{表达式}”的形式把表达式的内容(以字符串的形式)嵌入其中。表达式为以变量符号($、@)开头的变量时能够省略{},以“#变量名”的形式就可以了。# 后如果不是跟着 {、$、@,就会被仅当作字符“#”解释。如果确定不使用内嵌表达式的话在 # 前放置一个反斜线符号就可以了。
$ruby = "RUBY"
p "my name is #{$ruby}"     # => "my name is RUBY"
p ’my name is #{$ruby}’     # => "my name is #{$ruby}"
正则表达式字面值
例子:
/^Ruby the OOPL/
/Ruby/i
/my name is #{myname}/
/ 包围的部分就是正则表达式。正则表达式是 Regexp 类的实例。
关于正则表达式中元字符的用法问题,请参考正则表达式。
最后面 / 之后的字符是正则表达式的选项。选项的功能如下所示。
i
正则表达式匹配时不区分大小写字母。
m
多行模式。正则表达式“.”也能匹配换行。
o
开始计算正则表达式时只处理一次内嵌表达式。
x
正则表达式中的空字符(包括换行)将被忽视。同时,从“#”到行尾的部分将被当作注释处理(请注意,若注释中包含/则会引起语法解析错误)。
/foo        # 注释
bar/x
等同于“/foobar/”。
Ruby 正则表达式能正确使用多字节字符(汉字等)。
在正则表达式中和字符串一样,控制码和内嵌表达式也是有效的。
正则表达式字面值中不含内嵌表达式的话,则对其进行计算时始终返回同一个正则表达式对象。含有内嵌表达式的话,每计算一次(根据内嵌表达式的结果)就编译正则表达式生成一个正则表达式对象。
数组表达式
例子:
[1, 2, 3]
语法:
’[’ 表达式 ’,’ ... ’]’
分别计算每个表达式的值,然后返回由这些值构成的数组。数组是 Array 类的实例。
每次对数组表达式进行计算时都会生成新的数组对象。
哈希表表达式
例子:
{1=>2, 2=>4, 3=>6}
语法:
’{’ 表达式 ’=>’ 表达式 ’,’ ... ’}’
’{’ 表达式 ’,’ 表达式 ’,’ ... ’}’
分别计算每个表达式的值,返回由主键和数值组成的哈希表对象。哈希表是 Hash 类的实例。
哈希表(也叫作关联数组)就是把任意种类的对象和另一任意种类的对象进行关联。
每次对哈希表表达式进行计算时都会生成新的哈希表对象。
范围表达式
例子:
1 .. 20
语法:
式1 ’..’ 式2
式1 ’...’ 式2
在条件式以外的地方返回从式 1 到式 2 的范围对象。范围对象是 Range 类的实例。
.. 运算符生成的范围对象包含后面数值,... 运算符生成的范围对象不包含后面数值。
范围式两端是数值字面值的话,每次计算都会返回同一个对象。否则的话每次计算都会生成一个新的范围对象。
符号
例子:
:class
:lvar
:method
gvar
ivar
:+
语法:
’:’ 标识符
’:’ 变量名
’:’ 运算符
返回任意字符串和相对应的符号。符号是 Symbol 类的实例。
通常符号总是只有单个对象,即使被计算多少次也会返回同一个对象。
Ruby 的语法 运算符表达式
例子:
1+2*3/4
为了便于编程,有些方法调用和控制结构是以运算符的形式出现的。Ruby 语言中有下列运算符。
高     ::
       []
       **
       -(单项)  +(单项)  !  ~
       *  /  %
       +  -
       << >>
       &
       |  ^
       > >=  < <=
       <=> ==  === !=  =~  !~
       &&
       ||
       ..  ...
       ?条件运算符)
       =(+=, -= ... )
       not
低     and or
左侧的“高”和“低”表示运算符的优先度。例如“&&”的优先度要高于“||”,如下所示。
a && b || c   # => (a && b) || c
a || b && c   # =>  a || (b && c)
大部分运算符都是些特殊形式的方法调用,但有些运算符被嵌入在语言之中,无法进行重定义。
•    能够重定义的运算符(方法)
+@、-@ 表示单项运算符 +、-,在方法定义等场合中可以使用这种表示法。
|  ^  &  <=>  ==  ===  =~  >   >=  <   <=   <<  >>
+  -  *  /    %   **   ~   +@  -@  []  []=  `
•    不能重定义的运算符(控制结构)
回不到过去,去不了未来.我无路可逃.......
回复 支持 反对

使用道具 举报

10

主题

52

帖子

574

积分

⑤进阶

积分
574
 楼主| 发表于 2007-4-6 23:44:38 | 显示全部楼层
由多个运算符组合而成的自运算运算符、“!=”以及“!~”是不能重定义的。
=  ?:  ..  ...  !  not  &&  and  ||  or  ::
赋值
例子:
foo = bar
foo[0] = bar
foo.bar = baz
语法:
变量 '=' 表达式
常量 '=' 表达式
表达式 '['表达式..']' '=' 表达式
表达式 '.' 标识符 '=' 表达式
我们使用赋值表达式向变量等对象进行赋值。赋值也可以用作局部变量和常数的声明。赋值表达式的左边必须是下列之一。
•    变量
•    变量 '=' 表达式
若左边是变量的话,就将表达式的计算值代入其中。
•    数组调用
•    表达式1 '[' 表达式2 ... ']' '=' 表达式n
先计算表达式 1 得到一个对象,再把从表达式 2 到表达式 n 作为参数,来调用该对象的“[]=”方法。
class C
  def initialize
    @ary = [0,1,2,3,4,5,6,7]
  end
  def [](i)
    @ary[i * 2]
  end
  def []=( i, v )
    @ary[i * 2] = v
  end
end
c = C.new
p c[3]      # 变成 c.[]( 3 ), 结果为6
p c[3] = 1  # 变成 c.[]=(3,1),结果为1
•    属性调用
•    表达式1 '.' 标识符 '=' 表达式2
计算表达式 1 得到一个对象,再以表达式 2 为参数来调用该对象的“标识符=”方法。
class C
  def foo
    @foo
  end
  def foo=( v )
    @foo = v
  end
end
c = C.new
c.foo = 5   # 变成 c.foo=( 5 )
p c.foo     # => 5
还可以使用 attr_accessor 来定义属性。
class C
  attr_accessor :foo
end
c = C.new
c.foo = 5   # 变成 c.foo=( 5 )
p c.foo     # => 5
自运算
例子:
foo += 12       # foo = foo + 12
foo *= 3        # foo = foo * 3
语法:
表达式1 op= 表达式2     # 表达式 1 等同于普通赋值表达式左边的部分
op 就是下列中的某一个。运算符与 = 之间不留间隔。
+, -, *, /, %, **, &, |, ^, <<, >>, &&, ||
这种赋值形式和下面运算
表达式1 = 表达式1 op 表达式2
等同。
多重赋值
例子:
foo, bar, baz = 1, 2, 3
foo, = list()
foo, *rest = list2()
语法:
表达式 [',' [ 表达式 ',' ... ] ['*' [ 表达式 ]]] = 表达式 [, 表达式 ... ]['*' 表达式 ]
'*' [ 表达式 ] = 表达式 [, 表达式 ... ]['*' 表达式 ]
多重赋值是指,在多个表达式以及数组中同时进行的赋值。左边的各个表达式必须是可以被赋值的。若右边只有一个表达式时,则将该表达式的计算值转为数组后,再把数组中的各个单元依次赋值给左边。若右边数组单元的数量超过左边的话,将忽略多余的数组单元。若右边数组单元个数不足的话,将向左边多余的单元中代入 nil。
若左边最后一个表达式前带 * 的话,则将右边多余的单元以数组的形式代入这个带 * 的表达式中。若右边没有多余单元的话,就把空数组代入其中。
foo, bar  = [1, 2]      # foo = 1; bar = 2
foo, bar  = 1, 2        # foo = 1; bar = 2
foo, bar  = 1           # foo = 1; bar = nil
foo, bar  = 1, 2, 3     # foo = 1; bar = 2
foo       = 1, 2, 3     # foo = [1, 2, 3]
*foo      = 1, 2, 3     # foo = [1, 2, 3]
foo, *bar = 1, 2, 3     # foo = 1; bar = [2, 3]
and
例子:
test && set
test and set
语法:
表达式 '&&' 表达式
表达式 and 表达式
首先计算左边,若结果为真就接着计算右边。and 运算符的作用相同但优先度更低。将包含 and 的表达式作为某方法的参数时,必须使用双层括号。
or
例子:
demo || die
demo or die
语法:
表达式 '||' 表达式
表达式 or 表达式
首先计算左边,若结果为伪就接着计算右边。or 运算符的作用相同但优先度更低。将包含 or 的表达式作为某方法的参数时,必须使用双层括号。
not
例子:
! me
not me
i != you
语法:
'!' 表达式
not 表达式
若表达式值为真就返回伪,若表达式值为伪则返回真。
也可以使用下面的语法。
表达式 '!=' 表达式          # 等同于 !(表达式 == 表达式)
表达式 '=~' 表达式          # 等同于 !(表达式 =~ 表达式)
条件运算符
例子:
obj == 1 ? foo : bar
语法:
表达式1 ? 表达式2 : 表达式3
根据表达式 1 的结果,选择返回表达式 2 或表达式 3。它与
if 表达式1 then 表达式2 else 表达式3 end
完全相同。
Ruby 的语法 控制结构
与 C 语言等不同)Ruby 的控制结构是表达式,其中的一部分还会返回值(也有不返回值的,若把这些不返回值的表达式放在赋值表达式右边的话,就会发生 parse error)。
Ruby 中包括从 C 和 Perl 那里继承来的控制结构,还包括一种可以将控制结构抽象化的功能,即迭代器。迭代器的调用使类的设计者可以自己定义一些包括循环在内的控制结构。
条件分歧
if
例子:
if age >= 12 then
  print "adult fee\\n"
else
  print "child fee\\n"
end
gender = if foo.gender == "male" then "male" else "female" end
语法:
if 表达式 [then]
  表达式 ...
[elsif 表达式 [then]
  表达式 ... ]
...
[else
  表达式 ... ]
end
若条件表达式的计算结果为真时,将计算 then 以下的表达式。若 if 的条件表达式为伪时,将计算 elsif 的条件部分。可以存在若干个 elsif 部分,若所有的 if 以及 elsif 的条件表达式都为伪的话,如果有 else 部分,就计算它的表达式。
if 表达式的结果取决于条件成立部分(或 else 部分)中最后被计算的表达式的结果。若没有 else 部分,且所有条件均不成立的话,就返回 nil。
Ruby 中只有 false 和 nil 表示伪,其他的都是真,甚至 0 或空字符串也是如此。
请注意,在 Ruby 中,和 if 对应的是 elsif,而并非 else if(C 的语句)或者 elif(sh 的语句)。
if 修饰符
例子:
print "debug\\n" if $DEBUG
语法:
表达式 if 表达式
当右边的条件成立时,计算左边的表达式,并返回其结果。若条件不成立则返回 nil。
unless
例子:
unless baby?
  feed_meat
else
  feed_milk
end
语法:
unless 表达式 [then]
  表达式 ...
[else
  表达式 ... ]
end
unless 与 if 相反,当条件表达式结果为伪时,才计算 then 后面的表达式。unless 表达式中不能插入 elsif 语句。
unless 修饰符
例子:
print "stop\\n" unless valid(passwd)
语法:
表达式 unless 表达式
当右边的条件不成立时,计算左边的表达式,并返回其结果。否则返回 nil。
case
例子:
case $age
when 0 .. 2
  "baby"
when 3 .. 6
  "little child"
when 7 .. 12
  "child"
when 13 .. 18
  "youth"
else
  "adult"
end
语法:
case 表达式
[when 表达式 [, 表达式] ... [then]
  表达式 ..]..
[else
  表达式 ..]
end
case 先对一个表达式进行匹配判断,然后根据匹配结果进行分支选择。它使用 === 运算符比较 when 的指定值和最初那个表达式的计算值,若一致的话就计算 when 部分的内容。
case 将返回条件成立的 when 部分(或 else 部分)中最后被计算的表达式的结果。若所有条件都不成立的话,则返回 nil。
循环
while
例子:
ary = [0,2,4,8,16,32,64,128,256,512,1024]
i = 0
while i < ary.length
  print ary
  i += 1
end
语法:
while 表达式 [do]
   ...
end
只要表达式的计算值为真,就循环执行 while 语句中的内容。
while 返回 nil。另外,可以使用带参数的 break,将 while 表达式的返回值设为那个参数的值。
while 修饰符
例子:
sleep(60) while io_not_ready?
语法:
表达式 while 表达式
只要右边表达式的计算值为真,就循环执行左边部分。若左边表达式是 begin,则只在开始时计算一次然后就执行循环。
while 修饰符的表达式返回 nil。另外,可以使用带参数的 break,将 while 修饰符的表达式返回值设为那个参数的值。
until
例子:
until f.eof?
  print f.gets
end
语法:
until 表达式 [do]
   ...
end
在表达式的计算值变为真之前,一直循环执行 until 中的内容。
until 返回 nil。另外,可以使用带参数的 break,将 until 表达式的返回值设定为那个参数的值。
until 修饰符
例子:
print(f.gets) until f.eof?
语法:
表达式 until 表达式
在右边表达式的计算值变为真之前,一直循环执行左边部分。若左边表达式是 begin,则只在开始时计算一次然后就执行循环。
until 修饰符的表达式返回 nil。另外,可以使用带参数的 break,将 until 修饰符的表达式返回值设为那个参数的值。
for
例子:
for i in [1, 2, 3]
  print i*2, "\\n"
end
语法:
for lhs ...  in 表达式 [do]
  表达式 ..
end
先计算表达式得到一个对象,然后分别针对该对象中的每个单元,循环执行 for 的内容。这和下面的语法基本相同。
(表达式).each ’{’ ’|’ lhs..’|’ 表达式 .. ’}’
之所以说“基本”是因为,do...end 以及 {} 的结构中导入了新的局部变量的有效范围,而 for 语句对于局部变量的有效范围没有任何影响。
for 将返回 in 所指对象的 each 方法的返回值。
break
例子:
i = 0
while i < 3
  print i, "\\n"
  break
end
语法:
break [表达式]
break 将退出最内层的循环。所谓循环是指,下列之一。
•    while
•    until
•    for
•    迭代
与 C 语言不同,break 只能从循环中退出,而不能从 case 中退出。
若使用 break 退出 for 或迭代循环后,该循环将返回 nil。但如果使用了参数的话,循环将返回那个参数的值。
next
例子:
str.each_line do |line|
  next if line.empty?
  print line
end
语法:
next [表达式]
next 将跳转到最内侧循环的头部。在迭代器中,它将跳离 yield 调用。
用 next 跳离 yield 后,yield 表达式将返回 nil。但如果使用了参数的话,yield 表达式的返回值就是该参数的值。
异常处理
raise
例子:
raise
raise "you lose"
raise SyntaxError.new("invalid syntax")
raise SyntaxError, "invalid syntax"
语法:
raise
raise message
raise exception
raise error_type, message
引发异常。第一句将再次引发上一个异常。第二句中(参数为字符串的情况),就把那个字符串信息当作错误信息再引发 RuntimeError 异常。第三句中(参数为异常对象的情况),则引发该异常。第四句中,将引发第一个参数所指的异常,并以第二个参数的内容作为错误信息。
可以使用 begin 表达式的 rescue 部分来捕捉异常。
raise 并不是 Ruby 的保留字,而是内部函数。
begin
例子:
begin
  do_something
rescue
  recover
ensure
  must_to_do
end
语法:
begin
  表达式 ..
[rescue [error_type,..] [then]
  表达式 ..]..
[ensure
  表达式 ..]
end
若给出了 rescue 部分(可以有若干个)的话,就可以在发生异常时捕捉到它。若存在与异常类型一致的 rescue 部分的话,就执行 rescue 的内容。发生异常时,可以使用内部变量 $! 来查看异常的情况。
若 error_type 被省略,则将捕捉 StandardError 的子类中的所有异常。 Ruby 的大部分内部异常是 StandardError 的子类。具体请参考 内部异常类。
在 rescue 部分中,error_type 与普通的参数一样接受计算,若符合的话就执行相应部分的内容。若 error_type 的计算值既非类又非模块的话,则引发 TypeError 异常。
若存在 ensure 部分的话,则在 begin 表达式结束之前一定会计算它。
begin 表达式会返回其自身或 rescue 部分最后的计算结果。
rescue 修饰符
例子:
File.open("file") rescue print "can’t open\\n"
语法:
表达式1 rescue 表达式2
若表达式 1 中发生异常时就计算表达式 2。不能指定想捕捉的异常类(也就是说,只能捕捉 StandardError 异常类的子类了)。
在包含 rescue 修饰符的表达式中,若没发生异常则返回表达式 1 的值,若发生异常则返回表达式 2 的值。
方法结束
return
例子:
return
return 12
return 1,2,3
语法:
return [表达式[’,’ 表达式 ... ]]
结束方法的运行,且把表达式的值设定为方法的返回值。若给出了 2 个以上的表达式,则将这些表达式组成一个数组,然后把该数组设定为方法的返回值。若省略表达式,则返回值为 nil。
Ruby 的语法 方法调用
例子:
foo.bar()
foo.bar
bar()
print "hello world\\n"
print
语法:
[表达式 ’.’] 标识符 [’(’ 表达式 ... [’*’ [表达式]] ’)’]
方法调用表达式表示调用被调(“.”左侧表达式的值)的方法。若未指定被调,则调用 self 的方法。
方法名中除了通常的标识符以外,还可以添加“?”或“!”等后缀。通常在布尔型(返回真或伪)方法名后添加“?”,在比同名(无“!”)方法更具破坏性的方法名(例:tr 和 tr!)后添加“!”。
若最后一个参数前带“*”的话,将会先展开该参数的值,然后才传递。
foo(1,*[2,3,4])   # 等同于 foo(1,2,3,4)
super
例子:
super
super(1,2,3)
语法:
super
super(表达式 , ... )
super 将调用被当前方法覆盖的父类中的同名方法。若省略括号和参数时,将会把当前方法的参数原封不动地传递给父类中的同名方法。若调用时不想使用参数的话,请使用括号显式地标出,像 super() 这样。
class Foo
  def foo(arg=nil)
    p arg
  end
end

class Bar < Foo
  def foo(arg)
    super(5)       # 以5作为参数进行调用
    super(arg)     # 以5作为参数进行调用
    super          # 以5作为参数进行调用,super(arg) 的简写
    arg = 1
    super          # 以1作为参数进行调用,super(arg) 的简写
    super()        # 无参数的调用
  end
end
Bar.new.foo 5
迭代器
例子:
[1,2,3].each do |i| print i*2, "\\n" end
[1,2,3].each {|i| print i*2, "\\n" }
语法:
method(arg1, arg2, ...)  do [’|’ 表达式 ... ’|’] 表达式 ... end
method(arg1, arg2, ...) ’{’ [’|’ 表达式 ... ’|’] 表达式 ... ’}’
所谓迭代器是指,为了对控制结构(多见于循环)进行抽象化而设计的方法。将 do...end 或 {...} 中的代码片段(也就是块)添加在方法后面,然后再调用该方法时,就能从该方法内部对块进行计算。在迭代器内进行块调用时使用 yield 表达式。传给 yield 的值会被赋值给夹在“||”中的变量。
{...} 比 do...end 块的结合能力强。
foobar a, b do .. end   # foobar 是带块的方法
foobar a, b { .. }      # b    成了带块的方法
块中首次被赋值(声明)的局部变量的作用域仅限于该块。
foobar {
  i = 20                # 声明了局部变量 i
   ...
}
                        # 此处的 i 尚未定义
foobar a, b do
  i = 11                # 声明了一个新变量 i
   ...
end
迭代器的返回值与通常的方法是一样的,若块中的 break 引起中断时,将返回 nil。若 break 带参数的话,该参数的值就是带块方法的返回值。
yield
例子:
yield data
语法:
yield ’(’ [ 表达式 [’,’ 表达式 ... ]] ’)’
yield [ 表达式 [’,’ 表达式 ... ]]
把参数传给块之后,对块进行计算。因为 yield 定义迭代器,所以是在方法定义内使用。
def foo
  yield(1,2)
end

foo {|a,b| p [a,b]}
对块参数进行赋值时遵从多重赋值规律。若执行 yield 时,方法并没有带块(不是迭代器)的话,就会引发 LocalJumpError 异常。
yield 将会返回块内最后被计算的表达式的值。若因 next 引起块的运行中断的话,返回 nil。若 next 带参数的话,该参数的值就是 yield 的返回值。
Ruby 的语法 类和方法的定义
类定义
例子:
class Foo < Super
  def test
     :
  end
     :
end
语法:
class 标识符 [’<’ superclass ]
  表达式 ..
end
用来定义类的内容。类名是由大写字母开头的标识符。
类定义实际上就是把类赋值给由类名指定的常数(在 Ruby 中,类也是一个对象,它是 Class 类的实例)。
若某个类已经被定义过,此时又用相同的类名进行类定义的话,就意味着对原有的类的定义进行追加。
class Foo < Array
  def foo
  end
end

class Foo
  def bar
  end
end
在类定义表达式中,self 指的是该类本身,这与顶层没有什么不同。可以在类定义表达式中写入任何表达式,在定义类时这些表达式将被执行。
类定义中可以出现嵌套。下例中,嵌套外侧的 Foo 类和内侧的 Bar 类之间根本没有什么继承关系之类的功能上的联系(除了常数 Bar 是 Foo 中的常数 Foo:Bar 之外)。类的嵌套就是指,把与类有关的类/模块放在该类的外侧,使它们构成一个整体,借以表达某种包含关系。
class Foo
  class Bar
  end
end
类定义表达式将返回最后被计算的表达式的值。若最后的表达式不返回值,就返回 nil。
模块定义
例子:
module Foo
  def test
     :
  end
     :
end
语法:
module 标识符
  表达式 ..
end
用来定义模块的内容。模块名是由大写字母开头的标识符。
模块定义实际上就是把模块赋值给由模块名指定的常数(在 Ruby 中,模块也是一个对象,它是 Module 类的实例)。
若某个模块已经被定义过,此时又用相同的模块名来定义模块的话,就意味着对原有的模块定义进行追加。
模块定义表达式将返回最后被计算的表达式的值。若该表达式不返回值,则返回 nil。
方法定义
例子:
def fact(n)
  if n == 1 then
     1
  else
    n * fact(n-1)
  end
end
语法:
def 方法名 [’(’ [arg [’=’ default]] ... [’,’ ’*’ arg] ’)’]
  表达式 ..
[rescue [error_type,..] [then]
  表达式 ..]..
[ensure
  表达式 ..]
end
在定义语句所在的区域内定义一个方法。也就是说,若在类/模块的定义部分内定义一个方法的话,该方法就属于这个类/模块。若在顶层定义了一个方法的话,您就可以在任何地方调用它。这种方法其实就是其他语言中所说的“函数”。
方法名中,除了可以使用通常的标识符以外,还可以使用可重定义的运算符(例如 ==、+、- 等等。请参考运算符表达式)。
若给临时参数指定了默认表达式的话,在方法调用过程中如果实参数被省略时,该默认表达式的值就会变成默认值(方法调用时,在方法定义内计算默认表达式的值)。
若最后一个临时参数的前面带“*”的话,所有剩下的实参数将被转为数组后传递给该参数。
例子:
# 没有参数的方法。以下省略 end
def foo
end

# 有参数的方法
def foo(arg, arg2)

# 有默认参数的方法
def foo(arg = nil)

# 参数一应俱全
def foo(arg, arg2, arg3 = nil, *rest)

# 运算符表达式
def ==(other)
def +(other)
def *(other)
在方法定义中,只能以下列顺序指定临时参数。其中任何一项都是可选的。
•    没有默认表达式的参数(可多选)
•    有默认表达式的参数(可多选)
•    带 * 的参数(只能有一个)
我们再举几个特殊的例子。
# 单项+/-
def +@
def -@

# 给要素赋值
def foo=(value)             # obj.foo = value

# [] と []=
def [](key)                 # obj[key]
def []=(key, value)         # obj[key] = value
def []=(key, key2, value)   # obj[key, key2] = value
为了捕捉在方法运行时发生的异常,可以使用同 begin 一样的rescue、ensure 语句。
方法定义表达式返回 nil。
方法的计算
调用方法时,将按照下列顺序依此计算各个表达式。
•    参数的默认表达式(若有的话)
•    方法的内容
•    根据发生异常的实际状况,处理方法定义表达式的 rescue 部分或 else 部分(若有的话)
•    ensure 部分(若有的话)
在方法内,根据实际情况来计算这些部分,包括参数的默认表达式在内。
方法的返回值就是传给 return 的值。若没有调用 return 时,将返回在 ensure 部分之前最后计算的式子的值。
在定义某方法之前,是不能使用该方法的。例如
foo
def foo
  print "foo\\n"
end
调用未定义的方法会引发 NameError 异常。
特殊方法定义
例子:
def foo.test
  print "this is foo\\n"
end
语法:
def 表达式 ’.’ 标识符 [’(’ [ 参数 [’=’ default]] ... [’,’ ’*’ 参数 ]’)’]
  表达式 ..
[rescue [error_type,..] [then]
  表达式 ..]..
[else
  表达式 ..]
[ensure
  表达式 ..]
end
特殊方法就是专属于某个对象的方法。特殊方法的定义可以嵌套。
类的特殊方法将被该类的子类所继承。换言之,类的特殊方法所起到的作用,与其他面向对象系统中的类方法的作用是相同的。
特殊方法定义表达式返回 nil。
回不到过去,去不了未来.我无路可逃.......
回复 支持 反对

使用道具 举报

10

主题

52

帖子

574

积分

⑤进阶

积分
574
 楼主| 发表于 2007-4-6 23:46:23 | 显示全部楼层
类方法的定义
Ruby 中的类方法是指类的特殊方法。在 Ruby 中,类也是对象。因此它就可以像普通对象一样来定义特殊方法。
因此,若能在类对象中定义方法的话,该方法就会成为类方法。具体的定义方法如下(模块也一样)。
# 特殊方法方式。
class Hoge
  def Hoge.foo
  end
end

# 在类定义的外侧也行
def Hoge.bar
end

# 若使用下面的方法的话,即使类名改变了,也不必更改方法定义
class Hoge
  def self.baz
  end
end
与定义有关的操作
alias
例子:
alias foo bar
alias :foo :bar
语法:
alias 新方法名 旧方法名
给方法或全局变量添加别名。可以给方法名指定一个标识符或 Symbol(不能写 obj.method 这样的表达式)。 alias 的参数不会被计算。
给方法添加别名时,别名方法将继承此刻的原始方法。此后,即使原始方法被重新定义,别名方法仍然保持着重定义前的老方法的特性。若您改变了某方法的内容后,又想使用修改前的方法时,别名会非常有用。
# 定义 foo 方法
def foo
  "foo"
end

# 设定别名(避开方法定义)
alias :_orig_foo :foo

# 再定义 foo(利用以前的定义)
def foo
  _orig_foo * 2
end

p foo  # => "foofoo"
alias 表达式返回 nil。
标准库 内部函数
严格说来,Ruby 中没有函数,但 Kernel 模块中定义的方法(可以在任何地方用做函数,因此)可被其他语言当做函数来调用。若您对这些方法进行再定义时,就必需考虑到对其他方面的影响。
block_given?
若某方法带块则返回真,否则返回伪。请参考迭代器。
catch(tag) {|tag| .... }
运行块并返回它的值。若在块的运行过程中,遇到与 tag 同名的 throw 的话,将把 throw 的第二参数的值作为返回值。
嵌套的循环不会因为遇到 break 就一下子跳出。这时可使用 catch。
catch(:loop1) {
  for i in 1..2
    for j in 1..2
      throw :loop1, j
    end
  end
}
eval(expr)
把字符串 expr 当作 Ruby 程序来运行并返回其结果。
exit
终止 Ruby 程序的运行。
exit 通过引发 SystemExit 异常来结束程序的运行。若有必要的话,可以使用 rescue 部分来捕捉到它。
loop { ... }
(只要不被中断就)反复对块进行计算。
open(file[, mode])
open(file[, mode]) {|io| ... }
打开 file 并返回 File 对象。mode 可以是下列字符串。省略时默认为 "r"。
•    "r": 以读取模式打开文件。
•    "w": 以写入模式打开文件。打开文件时,若文件已存在就清空文件内容。
•    "a": 以写入模式打开文件。通常把写入内容添加到文件结尾。
若有“+”的话,就以读写两用模式(RDWR)打开文件。
•    "r+": 将文件的读写位置设在开头。
•    "w+": 与 "r+" 一样,打开文件时,若文件已存在就清空其内容。
•    "a+": 与 "r+" 一样,打开文件时,若文件已存在,就把读写位置设在文件结尾。
可在上述任意一项后面添加“b”(如 "r+b")标志。此时,将以二进制方式打开文件。
当 open 与块同时被调用时,open 将打开文件并执行块,当块的运行终止后就关闭文件。此时返回块的计算结果。请看下例。
open(path, mode) do |f|
   ...
end

# 等效代码
f = open(path, mode)
begin
   ...
ensure
  f.close
end
p(obj, [obj2, ...])
以通俗易懂的方式输出 obj。等同于以下代码(请参考 Object#inspect)。
print obj.inspect, "\\n", obj2.inspect, "\\n", ...
Ruby 中通常输出为标准输出,然而 RGSS 重定义了该方法,变更为输出到 Windows 的信息框。
返回 nil。
print(arg[, ...])
依次输出参数。若把非字符串对象传给参数的话,将对该对象使用 to_s 方法将其变为字符串后输出。若是 nil 的话则输出字符串 "nil"。
Ruby 中通常输出为标准输出,然而 RGSS 重定义了该方法,变更为输出到 Windows 的信息框。
返回 nil。
raise
raise(message)
raise(exception)
raise(error_type, message)
引发异常。请参考 raise
rand(max)
产生一个 0 至 max(不含)之间的随机数。若未调用 srand 的话,就自动调用它。
若将 max 设为 nil 或 0 的话,将返回一个 0 至 1(不含)的实数型 Float 随机数。
sprintf(format[, arg[, ...]])
采用同 C 语言 sprintf 一样的方法对 format 字符串进行解释,格式化参数后返回结果。
详细信息请参考 sprintf 格式化。
srand([seed])
设定 rand 的随机数的种子,返回旧的初始值(第一次返回 0)。若省略初始值时,则以当前时刻生成一个种子。
throw(tag[, value])
跳到使用了相同的 tag 的 catch 块的终点(跳过方法)。若没有使用相同 tag 的 catch 的话,就以 NameError 结束线程。tag 可以是字符串或符号。value 将变为 catch 的返回值。
标准库 内部变量
内部变量是全局变量的一种,但是它的值并不仅限于全局。
根据变量值的作用域的不同,大致将内部变量划分如下。
局部域
$~
在当前作用域中,最后一次匹配成功的相关信息(MatchData 对象)。若对其进行设定的话, 则 $& 以及 $1 ... $9 等的值也会发生变化。
等同于 Regexp.last_match。
$&
在当前作用域中,正则表达式最后一次匹配成功的字符串。若最后一次匹配失败,则为 nil。
等同于 Regexp.last_match[0]。
$1
$2
$3 ...
分别存储着最后一次模型匹配成功时与第 n 个括号相匹配的值。若没有相应的括号时,其值为nil。
等同于 Regexp.last_match[1],Regexp.last_match[2],...。
全局域
$!
最近发生的异常的信息。由 raise 设定。
$DEBUG
调试模式标志。RGSS 在调试游戏时设置这个标志。
在 Ruby 的调试模式中发生异常的处理等与普通运行有一些的不同,然而对于 RGSS 没有必要了解这些。
标准库 内部类 Object
所有类的父类。它定义了对象的一般行为。
包含的模块
•    Kernel
方法
self == other
若 self 等于 other 则返回真。默认情况下,它的效果等同于 equal? 。
应该根据各类的具体性质来重新定义该方法。
self === other
该方法通常用在 case 的比较句中。默认情况下,它的运作等同于 Object#== ,但在子类中进行归属检测时,需要对其进行适当的重定义。
class
返回被调的类。
clone
dup
生成某对象的拷贝并返回它。clone 生成的是完整的拷贝,它包括 freeze、特殊方法等信息,而 dup 则只拷贝对象的内容。
请注意,clone 和 dup 生成的都是「浅层(shallow)」拷贝。它们只拷贝对象本身,而不会拷贝对象的所指(例如数组的单元等)。
另外,如果对拷贝进行如下测试的话
obj.equal?(obj.clone)
通常都不成立。但是
obj == obj.clone
通常都会成立。
若想对 true、false、nil、Numeric 对象、Symbol 对象等进行拷贝时,会引发 TypeError 异常。
equal?(other)
若 other 就是 self 自己时,即返回真。该方法不能再定义。
freeze
禁止修改对象的内容,返回self。若强行修改则会引发 TypeError 异常。
frozen?
若某对象禁止修改其内容则返回真。
inspect
将某对象转为人工可读的字符串并返回该字符串。
instance_of?(klass)
若 self 为 klass 类的直接实例时,返回真。通常,当 obj.instance_of?(c) 成立时,obj.kind_of?(c) 也是成立的。
is_a?(mod)
kind_of?(mod)
只要 self 是下列任何一个类的实例就返回真,这些类是 mod 类和它的子类,以及包括 mod 模块的类和它的子类。
module M
end
class C < Object
  include M
end
class S < C
end

obj = S.new
p obj.is_a? S       # true
p obj.is_a? M       # true
p obj.is_a? C       # true
p obj.is_a? Object  # true
p obj.is_a? Hash    # false
nil?
若被调为 nil 则返回真。
object_id
返回与各个对象对应的唯一的整数。但是,为某对象分配整数的具体情形并不固定。
to_ary
若需要将对象隐式地转换为数组时,会在内部自动调用。
to_hash
若需要将对象隐式地转换为哈希表时,会在内部自动调用。
to_int
若需要将对象隐式地转换为整数时,会在内部自动调用。
to_s
将对象转换为字符串并返回该字符串。
如果把非字符串对象当做参数传给 print 或 sprintf 时,将调用该方法把非字符串对象转换为字符串。
to_str
若需要将对象隐式地转换为字符串时,会自动调用它。
私有方法
initialize
用户定义类的对象初始化方法。在对由 Class#new 新生成的对象进行初始化时要调用该方法。默认情况下,没有任何的动作。通常会在子类中根据需要对其进行再定义。传递给 Class#new 的参数会被原封不动地传递给 initialize。
标准库 内部类 Object Array
数组类。数组的单元可以是任意的 Ruby 对象。请参考数组表达式。
父类
•    Object
包含的模块
•    Enumerable
方法
self[nth]
返回第 nth 个数组单元。首单元算做第 0 个单元。若 nth 值为负,则看作是从尾部算起的索引值(尾单元算做第 -1 个单元)。若第 nth 个单元不存在,则返回 nil。
self[start, length]
以数组形式返回从第 start 个单元算起的 length 个数组单元。若 start 值为负,则看作是从尾部算起的索引值(尾单元算做第 -1 个单元)。若 length 超出从第 start 个单元算起的剩余长度时,超过部分将被忽略。若 length 为负,则返回 nil。
self[nth]=val
将第 nth 个数组单元的值设定为 val。若 nth 超出数组范围时,自动加长数组并以 nil 对新增部分进行初始化。
返回 val。
self[start, length]=val
将从索引 start 算起的 length 个数组单元替换为 val 的内容。若 val 不是数组时,则调用 val.to_ary 或使用 [val] 进行替换。返回 val。
ary = [0, 1, 2, 3]
ary[1, 2] = ["a", "b", "c"]
p ary                        # => [0, "a", "b", "c", 3]
ary[2, 1] = 99
p ary                        # => [0, "a", 99, "c", 3]
ary[1, 0] = ["inserted"]
p ary                        # => [0, "inserted", "a", 99, "c", 3]
self + other
将 self 和 other 的内容连起来后生成新数组并返回该数组。若 other 并非数组时则使用 other.to_ary 的返回值。若该返回值依然不是数组时,则引发 TypeError 异常。
a = [1, 2]
b = [8, 9]
p a + b     # => [1, 2, 8, 9]
p a         # => [1, 2]        (没有变化)
p b         # => [8, 9]        (也没有变化)
self - other
集合的补集运算。从 self 中删除 other 的单元后生成一个新数组并返回该数组。
self & other
集合的交集运算。将同属于两个数组的单元重组为一个新数组并返回该数组。重复单元将被清除。
self | other
集合的并集运算。将任属两数组之一的单元重组为一个新数组并返回该数组。重复单元将被清除。
self <=> other
使用 <=> 来依次比较 self 和 other 中的各个单元。若 self 大则返回正整数,若相等返回 0,若小则返回负整数。如果各个单元均相等,且其中一个数组已到达尾部时,则认定较短的数组为小。
self == other
使用 == 来依次比较 self 和 other 中的各个单元,若所有单元均相等时返回真。
clear
删除数组中的所有单元。返回 self。
ary = [1, 2]
ary.clear
p ary     # => []
clone
dup
生成一个与被调内容一样的新数组并返回它。clone 会拷贝 freeze、特殊方法等信息,而 dup 则只拷贝内容。然而,无论哪个方法都不会拷贝数组单元本身。
compact
compact!
compact 从 self 中删除值为 nil 的单元后生成新数组并返回它。compact! 是具有破坏性的,若对原数组进行了改动就返回 self,若没有进行改动则返回 nil。
ary = [1, nil, 2, nil, 3, nil]
p ary.compact   # => [1, 2, 3]
p ary           # => [1, nil, 2, nil, 3, nil]
ary.compact!
p ary           # => [1, 2, 3]
p ary.compact!  # => nil
concat(other)
将 other 连接到 self 末尾(该动作具有破坏性)。返回 self。
array = [1, 2]
a     = [3, 4]
array.concat a
p array          # => [1, 2, 3, 4]
p a              # => [3, 4]       # 没有变化
delete(val)
delete(val) { ... }
用 == 来分别比较 val 与每个数组单元,若相等则删除该单元。若发现了与 val 相等的单元就返回 val。
若没有发现与 val 相等的单元则返回 nil,若指定了块的话就对块进行计算并返回结果。
array = [1, 2, 3, 2, 1]
p array.delete(2)       # => 2
p array                 # => [1, 3, 1]

# 若向无块的参数传递了 nil 时,则无法从其返回值中判断
# 到底有没有进行删除
ary = [nil,nil,nil]
p ary.delete(nil)       # => nil
p ary                   # => []
p ary.delete(nil)       # => nil
delete_at(pos)
删除 pos 所指位置的单元并返回它。若 pos 超出数组范围则返回 nil。
array = [0, 1, 2, 3, 4]
array.delete_at 2
p array             # => [0, 1, 3, 4]
each {|item| .... }
依次使用每个单元来计算块。返回 self。
# 依次显示1、2、3
[1, 2, 3].each do |i|
  puts i
end
each_index {|index| .... }
依次使用每个单元的索引来对块进行计算。同下。
(0 ... ary.size).each {|index| ....  }
返回 self。
empty?
若数组单元数目为 0 则返回真。
include?(val)
若数组中包含 ==val 的单元就返回真。
index(val)
返回数组中第一个 ==val 的单元的位置。若没有与其相等的单元则返回 nil。
insert(nth, [val[, val2 ...]])
在索引为 nth 的单元前面插入第 2 参数以后的值。返回 self。其定义如下。
class Array
  def insert( n, *vals )
    self[n, 0] = vals
    self
  end
end
ary = ["foo", "bar", "baz"]
ary.insert 2, ’a’, ’b’
p ary                  # => ["foo", "bar", "a", "b", "baz"]
若没有指定任何 val 时,将不作任何动作。
length
size
返回数组长度。若数组为空则返回 0。
nitems
返回非 nil 单元的个数。
pop
删除末尾单元并返回它。若数组为空则返回 nil。
array = [1, [2, 3], 4]
p array.pop      # => 4
p array.pop      # => [2, 3]
p array          # => [1]

p array.pop      # => 1
p array.pop      # => nil
p array          # => []
push(obj1[, obj2 ...])
依次将 obj1、obj2 ... 添加到数组结尾。
返回 self。
array = [1, 2, 3]
array.push 4
array.push [5, 6]
array.push 7, 8
p array          # => [1, 2, 3, 4, [5, 6], 7, 8]
reverse
reverse!
reverse 将所有单元以逆序重新排列生成新数组并返回它。reverse! 的逆序排列过程具有破环性。
reverse 通常返回新数组。reverse! 通常会返回 self。
shift
删除数组的首单元并返回它。剩余单元依次提前。若数组为空返回 nil。
sort
sort!
sort {|a, b| ... }
sort! {|a, b| ... }
对数组内容进行排序。若带块调用时,将把 2 个参数传给块,然后使用块的计算结果进行比较。若没有块时,使用 <=> 运算符进行比较。sort! 的对数组单元的排序过程具有破环性。
sort 将生成一个经过排序的新数组并返回它,sort! 通常会返回 self。
unshift(obj1[, obj2 ...])
依次将 obj1、obj2 ... 插到数组的头部。
返回 self。
回不到过去,去不了未来.我无路可逃.......
回复 支持 反对

使用道具 举报

10

主题

52

帖子

574

积分

⑤进阶

积分
574
 楼主| 发表于 2007-4-6 23:47:42 | 显示全部楼层
以上完了  太长了
回不到过去,去不了未来.我无路可逃.......
回复 支持 反对

使用道具 举报

好人卡的 该用户已被删除
发表于 2007-4-7 00:15:44 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|幻想森林

GMT+8, 2025-6-24 05:56 , Processed in 0.027789 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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