Project1

标题: 对RMXP GameBattler类的一些看法 [打印本页]

作者: 唐门草楹    时间: 2012-11-16 19:02
标题: 对RMXP GameBattler类的一些看法
本帖最后由 唐门草楹 于 2012-11-24 11:49 编辑

       这个学期开了“面向对象”课程,再回过头来看RMXP的脚本,感觉瞬间升华了。

    首先我搞懂了一直以来弄不清楚的地方,RMXP脚本里没有数据类型,访问区分符也很奇葩。按照我的理解,第一个字符以小写英文字母或下划线开头代表局部变量,只在块内有效;第一个字符以$开头代表程序的全局变量,在整个工程中有效;第一个字符以@开头代表实例变量也就是类的成员变量,访问权限要在类头部定义:attr_reader代表只读,attr_writer代表只写,attr_accessor代表可读可写。不知道出于什么目的,这款编译器要对读写进行区分;也不知道为什么不分数据类型。

    再回过头来看默认脚本的GameBattler类,觉得框架构建的些许不合理。

    首先,原始的脚本中GameActor类与Game_Battler类中的很多成员变量是只读的,因此如果在默认脚本的基础上,我们不能通过脚本直接修改战斗者的一些属性。
   
    第二,数据库写死了很多东西,所以如果要进行大规模的自定义修改的话,$data_actors 与 $data_enemies这两个全局变量很不好用。例如我要在脚本中把二号队员的HP改成100,$data_actors[2].hp = 100这种写法根本不行。推测是内部的结构没有开放hp的修改权限。

    第三, Game_Actor类与Game_Enemy类的虽然都继承自Game_Batller类,但是两者的数据库结构差异实在很大。这给“召唤兽”、队友变敌人之类的算法造成了很大的障碍。Game_Enemy中没有level,没有final_level,没有exp,也没有任何武器等实例变量。而Game_Actor则没有actions变量与生成行动(make_action)函数等等。角色与敌人两套路线的方法实在不利于某些方面的扩展。

    因此在这个周末,我打算重新编写一下Game_Battler、Game_Actor以及Game_Enermy类,最好是希望把Game_Actor与Game_Enemy类合并,这样敌人也可以转换成角色,角色也可以转换成敌人,很适合做佣兵系列或者召唤兽系列的游戏。
作者: 电子最终龙    时间: 2012-11-21 10:36
動這些就意味著要重寫RPG下面的數據結構,就意味著RM自帶的數據庫編輯器不能用了。
作者: 唐门草楹    时间: 2012-11-21 10:42
电子最终龙 发表于 2012-11-21 10:36
動這些就意味著要重寫RPG下面的數據結構,就意味著RM自帶的數據庫編輯器不能用了。 ...

用是能用,只要我们不全依赖$game_actor 和 $game_enemy 就好。比如我还可以载入数据库里的怪物属性信息,但是我如果想将它转化成一个我方角色,还需要给它定义经验、等级之类的属性。不过如果是把角色变成敌人相应来说要简单很多,因为actor的很多属性都包含了enemy的属性,只有一个make_action函数改起来比较麻烦。正好我也要把智能战斗的AI算法重写一遍。
作者: zhangbanxian    时间: 2012-11-23 16:02
- -b其实,ruby没有属 性这一说,要访问实例变量只有通过方法,attr accessor只是相当于def a
@a
end的
def a=(val)
@a =val
end的一个宏(ruby还可以定义许多有趣的方法,比如[],[]=等等,你以前可能觉得是运算符的东西其实它也是个方法,可以任意覆写)。
数据类型一般动态语言都不会有的说,限制自由度啊,需要类型安全时完全可以用is a? class自行raise...
顺便吐槽下armors当然没有hp了,应该改game actors...
作者: 唐门草楹    时间: 2012-11-24 11:49
zhangbanxian 发表于 2012-11-23 16:02
- -b其实,ruby没有属 性这一说,要访问实例变量只有通过方法,attr accessor只是相当于def a
@a
end的

谢谢指点,不过,armor是怎么乱入的?你怎么会从actor联想到armor?
作者: 晴兰    时间: 2012-11-29 10:03
提示: 作者被禁止或删除 内容自动屏蔽
作者: viktor    时间: 2012-11-29 15:42
本帖最后由 viktor 于 2012-11-29 16:07 编辑

我也来说说我的看法吧。
首先,ruby是强类型语言。一个变量可能有各种各样不同类型的值,但是在某一个特殊时刻,他的值和类型都是确定的。总之,类型不兼容会报TypeError的。但是ruby又有duck typing,在调用方法的时候,只要目标响应,就会执行,这样就造成了“不分数据类型”的假象。具体的我没法讲得更清楚,请LZ搜索一下强类型语言和duck typing。

至于访问区分符和权限。作为一门脚本语言,ruby肯定受了其他的脚本比如perl,shell的影响。shell里面引用变量就是使用的$filename, $~, $?这样的方式。其实习惯了以后,使用$@这样的前缀会比用private extern xxx的方便。attr_reader只是一个方法,实现的功能类似于修饰器,在这里用来改变对象的行为。了解原理以后也可以自己写类似的修饰器 比如在修改变量的值的时候,刷新画面之类的。而因为有instance_eval, instance_variable_get/set这几个穿透性的方法存在,也并不存在绝对的只读和不可访问。

第二, 想修改血量?直接改Game_Actor啊,改数据库没用的。(也就是兰兰的【碗里的和锅里的】的比方了)。实际使用的,存档里的数据都在Game_Actor里面。
第三。原始的Game_Actor/Enemy的确不合理。按说Enemy应该是简化版的Actor,所以可以做一个转换器把Enemy cast成Actor。然后战斗的时候全部都是Actor在作战。这样可以实现更加复杂灵活的战斗系统。期待楼主了。



作者: feizhaodan    时间: 2012-11-29 18:46
你可以去Ruby官方网站找一下参考文档。你绝对找不到比这个更充实的文档,把几乎所有的追加库的内容和标准库的内容全都收录,而且也有语法、语句参考。

另外你觉得Game_Battler的功能不够高的话,你完全可以自己在Game_Battler内定义新的函数们。而且他们绝对不会对Game_Actor造成影响,当然前提是你没有破坏他们的结构。

RMXP,或者说RM为什么默认的脚本功能比较少?因为他只定义了默认数据库提供的功能的使用方法。数据库内,敌人和角色的设置里有什么重复的,就定义在Game_Battler,只有一个有的就定义在各个的类中。至少我感觉很简单很单纯也很好修改。

其实还有一个原因就是写RMXP的默认脚本的人可能有点不习惯Ruby,至少看着那一大串Scene_XXX但却没有VX以后的Scene_Base的时候我就觉得有点晕囧




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1