赞 | 342 |
VIP | 10 |
好人卡 | 8 |
积分 | 262 |
经验 | 235776 |
最后登录 | 2024-9-23 |
在线时间 | 2387 小时 |
Lv5.捕梦者 (版主) 遠航の猫咪
- 梦石
- 3
- 星屑
- 23191
- 在线时间
- 2387 小时
- 注册时间
- 2005-10-15
- 帖子
- 1166
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
第四章 我的第一个Ruby程序
第一节 事件中的脚本
在RMXP里,一般开始进行游戏时,当然都是用事件来构成整个游戏的进程。而Ruby脚本,可以从属于事件,作为事件的一个部分来执行。在事件中调用脚本,一共有3种方式:
第一种就是我们曾经在第一章里所讲到的方式:通过事件第三页最后一个按钮“脚本...”来插入一个脚本,这个12行*40列的方框里可以填入较长的一段脚本,实现一些用普通事件很难实现或者无法实现的功能。
第二种是在“条件分歧”这个事件中,翻到最后一个选项卡,点选“脚本”,可以在后面的那个文本框里输入脚本。这个脚本只有一行,但是长度没有限制,不过编写一些复杂的控制结构等也是可能的,只是不直观。更多的情况下,这个脚本里是填写一些返回值为true或false的表达式。学会使用“条件分歧”中的脚本非常重要,由于我们还没有讲到Ruby的控制结构,这是惟一一种你可以用脚本来控制事件运行规则的方法,即使以后学到了Ruby的控制结构,这仍然是惟一一个可以将事件内嵌在脚本中而不是反过来的方法。
第三种用的比较少,在“设置移动路线”事件,也包括设置事件的移动类型为自定义然后设置路径的对话框中,最后一个选项是“脚本”,也是只有一行,也没有条件限制。不过这个脚本的应用可要少得多,因为它能控制的东西很少,但用来做一些特殊移动是很方便的,比如站上的教程“如何让NPC移动后位置固定”就是用移动路线的脚本来实现的。
第二节 脚本中的游戏对象
Ruby是一种面向对象的程序语言,而在RMXP中它主要和各种游戏对象打交道,这个解释,似乎听上去很难懂。不过我们可以从另一个角度来阐述它。
在前面的教程中,我们已经说到Ruby的变量构造,你在事件中所碰到的那些诸如“开关”“变量”“本事件”“角色”“图片”“武器”“金钱”“定时器”甚至于复杂的事件如“显示选择项”“战斗”“强制行动”等,其实都是通过操作游戏中的全局变量(以$接头符开头的变量)来实现,这些全局变量代表了游戏中的各个游戏对象。RMXP内部是通过解释你的事件指令,来对它们进行操作达到你想要的各种效果的。
如果你想在脚本中操作它们——说白了,操作一个全局变量,你当然要知道它们的名字,不是像[角色的地形标记][开关0005]等这种你所熟知的名字,而是——它们在脚本中的写法。
代表游戏对象的全局变量一共有11个,全部命名为$game_xxxx,这些命名都是很容易就能看出其代表的内容的。在我们的第一个Ruby程序中,我们首先只介绍4个最常用(也许是最常用)在事件脚本中的游戏对象:
开关:$game_switches[开关编号]
变量:$game_variables[开关编号]
主角:$game_player
事件:$game_map.events[事件编号]
第三节 小试牛刀:开关和变量
也许在一些机关迷宫中我们经常需要做这样一些事件:
调查某个机关,开关1开启,再调查之,开关1关闭。
最容易想到的是两个事件页:
事件页一:出现条件[无],执行[开关操作:0001=ON]
事件页二:出现条件[开关0001为ON],执行[开关操作:0001=OFF]
这个方法意味着每执行一次开关,要刷新两次事件。
如果合并在一个事件页中当然也可以
事件页:出现条件[无],执行:
条件分歧 开关[0001]=ON
开关操作 [0001]=OFF
除此以外的情况下
开关操作 [0001]=ON
分歧结束
这样要省下一个事件页面,但是用了3条事件指令。然而,如果想用脚本来达到这个效果的话,只需要一个事件指令:
事件页:出现条件[无],执行:
脚本:$game_switches[1]=not $game_switches[1]
从前面一章的教程中,很容易看出,这条脚本的意思是:将开关1的值取相反值(true变为false, false变为true)后,再赋值给开关1。
这不就实现了我们的要求——调查一次开启开关,再调查一次关闭开关吗?
再来看一个复杂些的例子,我们想在进入某个场景后,自动执行事件,在角色正上方出现一个NPC(假设为事件2)。
用事件指令来做,应该是这个样子:
变量操作 [0001]=角色的X坐标
变量操作 [0002]=角色的Y坐标
变量操作 [0002]-=1
设置事件位置,[事件2],[0001][0002]
下面我们用脚本来完成这个功能:
脚本:$game_map.events[2].moveto($game_player.x,\
$game_player.y-1)
这里解释一下:$game_map.events[2]是指地图上的2号事件,而moveto(x,y)是它的一个方法(或者函数),作用是将事件移动到坐标(x,y)的位置上,而$game_player是指主角,.x, .y分别对应这个对象内部的@x @y两个变量,取得主角所在的坐标值。
这个脚本翻译过来就是:取得主角的X和Y坐标值,并且将Y坐标值减去1,然后将事件2移动到相对应的位置。
显而易见的好处是,它不需要占用任何变量。
在事件操作中,为了统一也是安全起见,当你要用到某个武器的ID、或者角色的坐标、地形编号来做一些其他事情时,你不得不将它代入一个变量然后对这个变量进行判断、运算等操作,但只要使用了脚本,你就可以直接访问游戏对象的值,如果你被允许从外部访问它们的话。
第四节 实战事件脚本:十步杀一人
这里我们通过一个详尽的例子,来实现这样一个系统:
角色正在危机四伏的地牢中行走,如果不慎踏中了有埋伏的格子(地形标记为4),恰好此时的步数能被10整除,那么发生战斗,这样的战斗无法逃跑,也不允许失败。
先来看看用纯粹的事件指令实现这个系统:一个并行事件
变量操作:[0001]=角色的地形标记
变量操作:[0002]=步数
变量操作:[0002]%=10
条件分歧:变量[0001]==4
条件分歧:变量[0002]==0
战斗处理
分歧结束
分歧结束
好像并不算很复杂。但是实际处理中就会发现,如果发生了一场战斗以后,好不容易战胜,刚退出来发现马上又开始了一场战斗。如此往复,无尽循环。“十步杀一人”变成了“身陷重围”,角色纵使带了100个大补药,也无济于事了……
事实上,如果不用脚本的话,这个系统是不能实现的,因为在默认的条件分歧等操作中,没有提供“判断角色是不是在移动”这样的功能。导致角色一旦进入一个满足了战斗条件的格子,就会一直在里面战斗……无法出来。
那么应该怎么办呢?
条件分歧:$game_player.moving?
变量操作:[0001]=角色的地形标记
变量操作:[0002]=步数
变量操作:[0002]%=10
条件分歧:变量[0001]==4
条件分歧:变量[0002]==0
战斗处理
分歧结束
分歧结束
分歧结束
这样,只有在角色移动时,才会判断是不是要进行战斗处理。$game_player.moving?是判断主角是否在移动中的脚本,返回一个true或false的值,当该值为true时,执行分歧里面的操作。
现在来看看能不能优化一下这个系统,可以发现,每次战斗处理,要计算3次变量的值,比较2次。
我们来试图直接获得游戏对象的值,替代烦人的变量操作
条件分歧:$game_player.moving?
条件分歧:$game_player.terrain_tag == 4 and $game_party.steps % 10 == 0
战斗处理
分歧结束
分歧结束
好了,完成了,大家可以自己测试一下。
关于如何在脚本中调用那些游戏对象的值,在本教程全系列完成后的附录里会专门列一张表,大家也可以查看站上的教程“在事件中使用的常用脚本”,里面给出了部分游戏对象的脚本引用方法。 |
|