提示:在学习本套教程之前,请确保你有学习过鄙人的《手把手教你入门RMXP》,或者已经能够熟练掌握RMXP默认的事件用法,并能够用自己的素材替换默认素材等。在教程中涉及基础部分的内容将不予赘述。
接下来切入正题——打开你的RMXP,然后打开脚本编辑器——直接按F11或者在“工具”菜单里都能找到,之后就会出现如下界面。也许看着堆积如山的代码会感到眼花缭乱,但是只要多摆弄一下,修修改改,时间长了就算不会杀猪也会吃猪肉的(啥)。
接下来切入正题——打开你的RMXP,然后打开脚本编辑器——直接按F11或者在“工具”菜单里都能找到,之后就会出现如下界面。也许看着堆积如山的代码会感到眼花缭乱,但是只要多摆弄一下,修修改改,时间长了就算不会杀猪也会吃猪肉的(啥)。
本套教程需要配合的教科书是F1的帮助手册。不过,我不会拿着它照本宣科从头一条条地教,它的作用只不过是查阅脚本语句及解释的一个参考。另外,在脚本编辑器的操作方面需要熟练掌握几个热键:
Ctrl + Shift + F——在整个脚本编辑器里全局搜索特定字句;
Ctrl + F ——在单篇脚本里搜索特定字句;
Ctrl + H ——在单篇脚本里替换特定字句;
Crtl + Z ——撤销上次操作;
Ctrl + C 和Ctrl + V ——复制粘贴,这个不用我再多说吧……
上述热键都记下来了吗?OK,基本上只要拿好帮助手册用熟这几个热键,你就可以开始你的修改脚本自定义游戏之路了。丑话说在前头,这套教程不可能让你达到对脚本知根知底得心应手的娴熟程度,也不会让你成为真正懂得Ruby语言随便就能写出个银河系统的程序员。但是,你可以通过教程里给出的操作方法,做出与默认不一样,甚至是很不一样的作品,获得的成就感一定大于付出的精力(因为这套教程很简单不费脑子的……囧)。在那之上如果还想深入钻研的话,再慢慢去吃透帮助手册吧。
Ctrl + Shift + F——在整个脚本编辑器里全局搜索特定字句;
Ctrl + F ——在单篇脚本里搜索特定字句;
Ctrl + H ——在单篇脚本里替换特定字句;
Crtl + Z ——撤销上次操作;
Ctrl + C 和Ctrl + V ——复制粘贴,这个不用我再多说吧……
上述热键都记下来了吗?OK,基本上只要拿好帮助手册用熟这几个热键,你就可以开始你的修改脚本自定义游戏之路了。丑话说在前头,这套教程不可能让你达到对脚本知根知底得心应手的娴熟程度,也不会让你成为真正懂得Ruby语言随便就能写出个银河系统的程序员。但是,你可以通过教程里给出的操作方法,做出与默认不一样,甚至是很不一样的作品,获得的成就感一定大于付出的精力(因为这套教程很简单不费脑子的……囧)。在那之上如果还想深入钻研的话,再慢慢去吃透帮助手册吧。
第一章:从修改字符串和数字开始
【字符串篇•范例一:选项栏的文字修改】
本范例的修改效果很简单,就是将一开始进入游戏的标题画面的三个文字选项改改名字。同样,这也是最基本的字符串修改。
首先在左边一连串的脚本列表里找到Scene_Title。点击后右边大窗口里就会显示出该条脚本的全内容。从最顶头的介绍我们知道,这是“处理标题画面的类”,『类』是什么我们先不管,但从定语可以知道标题画面就是由这个脚本负责管的。在脚本窗口里有很小的数字标识着脚本的行数,用来定位某条语句是很重要的(尤其在后期脚本出错找错处的时候)。定位到它的37行,可以看到这样一段:
# 生成命令窗口
s1 = "新游戏"
s2 = "继续"
s3 = "退出"
带#号的绿色字表示注释。在事件里也有类似的一个指令,被写作注释的字会变成绿色,无论是在脚本还是在事件里都不会被执行。所以在脚本里,注释多用来做一些备忘和标识等。只要在语句的最前面标注上井号,就能把它变成注释。在日后删改脚本的时候,也多推荐用井号注释掉语句而不是直接删除,避免误删导致错误又无法恢复。
下面的三句脚本里s1,s2和s3代表选择项目,具体是什么我们容后研究,主要是看等号后面被双引号括起来的紫色字,很明显,这就是在你的标题画面中显示出来的那三个选项——这,就是字符串。
修改字符串的时候,文字必须要被放在双引号的里面,双引号的两头都不能少,也不能直接在等号后面写汉字而忘记带双引号。
我们现在把这一段改成这样:
# 生成命令窗口
s1 = "新的故事"
s2 = "旧的梦想"
s3 = "离开舞台"
然后点击确定,保存退出并运行游戏,看看效果吧。这就是最简单的现有字符串的修改法,基本上可以用于一切已知的会在RMXP界面里直接显示出来的内容。
注意:在修改一段字符串之前,必须搞清楚它是否在RM里有显示出来的地方。依然拿Scene_Title为例,在我们刚修改的这一段脚本上方和下方同样有双引号括起来的紫色字串,里面放着一些文件路径。这个虽然也可以改,但现在不能乱改。因为它们不是在界面里『显示出来』的字符串,所以修改以后发生的也不是直观而简单的视觉改变。
练习题A:游戏的主菜单里,物品、技能和装备的名称在数据库的系统选项卡里可以修改,比如改成道具、魔法和防佩(……),但是状态、存档和结束游戏却需要在脚本中修改。现在请在主菜单的脚本Scene_Menu里,自己试着修改它们的名称。注意双引号一定不要忘记,并且要写全。
练习题B:在退出游戏的界面Scene_End里,修改你认为可以修改的字符串。并保存进入游戏通过选择结束游戏来查看修改效果。
【字符串篇•范例二:窗口文字修改】
选项的改法通过上面的范例及练习,应该有了一个大致的概念。其实窗口里显示的字符串的修改与其大同小异,初期修改时最需注意的主要便是该字符串能不能直接上去改。
整套脚本里面,前面带Window和Scene的两种脚本表示或者包括游戏里显示出来的所有窗口,能够直接修改的字符串也主要分布在这两种脚本里。
接下来,看个例子——找到Window_PlayTime。这是显示游戏时间的窗口,在游戏运行时主菜单里也能看到它。这段脚本很小,里面有两个双引号框起来的紫色字符串。
self.contents.draw_text(4, 0, 120, 32, "游戏时间")
@total_sec = Graphics.frame_count / Graphics.frame_rate
hour = @total_sec / 60 / 60
min = @total_sec / 60 % 60
sec = @total_sec % 60
text = sprintf("%02d:%02d:%02d", hour, min, sec)
那么现在请问,哪一个是可以随便修改其内容的?
——你一定立刻就能说出是”游戏时间”的那个吧。真聪明,摸头(喂给我好好上课)。因为下面的那个” %02d:%02d:%02d”,虽然现在或许不知道它具体是什么(其实它就是代表游戏时间的变量,会通过刷新而显示出时间的变化),但是在游戏里面,你并没有看到游戏窗口里直接显示这个%02d:%02d:%02d。所以,它是不可以随便修改里面内容的字符串。(好奇心强的也可以把它改掉看看,然后你会发现原本正常显示的时间就变成你修改的内容了。)
练习题A:找到Window_Status,显示人物状态的窗口——然后看看里面哪些是可以修改的字符串,并且将其修改后进入游戏察看效果。
练习题B:找到Scene_Save和Scene_Load,表示存储和读取的界面——然后修改里面你认为可以修改的字符串并查看修改后的效果。
这两段范例综合总结起来,即是说,只要在游戏界面里显示出的内容和脚本里双引号内的是一样的东西,那么这个字符串就能随便改成你想要的内容。否则改前务必三思。在现阶段,除此之外的字符串最好先不要动,等到接触得深入了之后再进行修改。
本范例的修改效果很简单,就是将一开始进入游戏的标题画面的三个文字选项改改名字。同样,这也是最基本的字符串修改。
首先在左边一连串的脚本列表里找到Scene_Title。点击后右边大窗口里就会显示出该条脚本的全内容。从最顶头的介绍我们知道,这是“处理标题画面的类”,『类』是什么我们先不管,但从定语可以知道标题画面就是由这个脚本负责管的。在脚本窗口里有很小的数字标识着脚本的行数,用来定位某条语句是很重要的(尤其在后期脚本出错找错处的时候)。定位到它的37行,可以看到这样一段:
# 生成命令窗口
s1 = "新游戏"
s2 = "继续"
s3 = "退出"
带#号的绿色字表示注释。在事件里也有类似的一个指令,被写作注释的字会变成绿色,无论是在脚本还是在事件里都不会被执行。所以在脚本里,注释多用来做一些备忘和标识等。只要在语句的最前面标注上井号,就能把它变成注释。在日后删改脚本的时候,也多推荐用井号注释掉语句而不是直接删除,避免误删导致错误又无法恢复。
下面的三句脚本里s1,s2和s3代表选择项目,具体是什么我们容后研究,主要是看等号后面被双引号括起来的紫色字,很明显,这就是在你的标题画面中显示出来的那三个选项——这,就是字符串。
修改字符串的时候,文字必须要被放在双引号的里面,双引号的两头都不能少,也不能直接在等号后面写汉字而忘记带双引号。
我们现在把这一段改成这样:
# 生成命令窗口
s1 = "新的故事"
s2 = "旧的梦想"
s3 = "离开舞台"
然后点击确定,保存退出并运行游戏,看看效果吧。这就是最简单的现有字符串的修改法,基本上可以用于一切已知的会在RMXP界面里直接显示出来的内容。
注意:在修改一段字符串之前,必须搞清楚它是否在RM里有显示出来的地方。依然拿Scene_Title为例,在我们刚修改的这一段脚本上方和下方同样有双引号括起来的紫色字串,里面放着一些文件路径。这个虽然也可以改,但现在不能乱改。因为它们不是在界面里『显示出来』的字符串,所以修改以后发生的也不是直观而简单的视觉改变。
练习题A:游戏的主菜单里,物品、技能和装备的名称在数据库的系统选项卡里可以修改,比如改成道具、魔法和防佩(……),但是状态、存档和结束游戏却需要在脚本中修改。现在请在主菜单的脚本Scene_Menu里,自己试着修改它们的名称。注意双引号一定不要忘记,并且要写全。
练习题B:在退出游戏的界面Scene_End里,修改你认为可以修改的字符串。并保存进入游戏通过选择结束游戏来查看修改效果。
【字符串篇•范例二:窗口文字修改】
选项的改法通过上面的范例及练习,应该有了一个大致的概念。其实窗口里显示的字符串的修改与其大同小异,初期修改时最需注意的主要便是该字符串能不能直接上去改。
整套脚本里面,前面带Window和Scene的两种脚本表示或者包括游戏里显示出来的所有窗口,能够直接修改的字符串也主要分布在这两种脚本里。
接下来,看个例子——找到Window_PlayTime。这是显示游戏时间的窗口,在游戏运行时主菜单里也能看到它。这段脚本很小,里面有两个双引号框起来的紫色字符串。
self.contents.draw_text(4, 0, 120, 32, "游戏时间")
@total_sec = Graphics.frame_count / Graphics.frame_rate
hour = @total_sec / 60 / 60
min = @total_sec / 60 % 60
sec = @total_sec % 60
text = sprintf("%02d:%02d:%02d", hour, min, sec)
那么现在请问,哪一个是可以随便修改其内容的?
——你一定立刻就能说出是”游戏时间”的那个吧。真聪明,摸头(喂给我好好上课)。因为下面的那个” %02d:%02d:%02d”,虽然现在或许不知道它具体是什么(其实它就是代表游戏时间的变量,会通过刷新而显示出时间的变化),但是在游戏里面,你并没有看到游戏窗口里直接显示这个%02d:%02d:%02d。所以,它是不可以随便修改里面内容的字符串。(好奇心强的也可以把它改掉看看,然后你会发现原本正常显示的时间就变成你修改的内容了。)
练习题A:找到Window_Status,显示人物状态的窗口——然后看看里面哪些是可以修改的字符串,并且将其修改后进入游戏察看效果。
练习题B:找到Scene_Save和Scene_Load,表示存储和读取的界面——然后修改里面你认为可以修改的字符串并查看修改后的效果。
这两段范例综合总结起来,即是说,只要在游戏界面里显示出的内容和脚本里双引号内的是一样的东西,那么这个字符串就能随便改成你想要的内容。否则改前务必三思。在现阶段,除此之外的字符串最好先不要动,等到接触得深入了之后再进行修改。
【数字篇•范例一:修改现有参数】
从本篇开始需要会通过脚本里的现有注释来理解某条语句的意思,另外请复习小学的四则运算及括号之类的运用。在RM的脚本里可修改的数字实在是太多了……不能确切搞明白就乱改的话,很容易出错。
接下来我们将由浅入深地分步来教一些比较基本的数字修改。
1、修改窗口的基本参数
核心语句A:super(X坐标, Y坐标, 宽, 高)
所有Window打头的脚本坐标,也就是管游戏里那些界面的窗口的脚本里,基本上你都能找到这么一句。通常它出现在def initialize的下面,表示窗口初始化——可以将其理解为这个窗口刚被造出来的状态。既然女娲要造人了,自然要有人的身高三围……大误,我是说既然脚本要造窗口,就要有个窗口的尺码。在super这句话后面的括号里的四个数字便是一个窗口最基本的参数,就跟人会有体重三围一样。修改它们,就会改变你窗口的样子。
X坐标指的是窗口左上角端点的垂直位置,Y坐标则是指水平位置。RM的窗口都是方形的,所以基准点就是左上角端点,和事件里显示图片指令的左上对称一样。宽和高的概念不用多解释。随便打开一个窗口脚本比如Window_Item(显示持有物品的窗口),试着分别改一下Super后面四个数字,然后保存进入游戏按ESC看看吧。可以每改一个数字就存一次然后测试,就能很清楚地明白该数字修改后表现的是什么效果了。
练习题:修改Window_Status(状态界面窗口),使其略小一点,并居中显示。
提示:RM默认分辨率是640×480,即打开RM之后窗口最大能显示的区域。如果你把窗口的宽和高修改为了400和300,为了让其居中显示,X坐标便是(640-400)/2=120,Y坐标是(480-300)/2=90。算不过来的可以开计算器(……
核心语句B:@xxxxx_window.x (y/width/height) = xxx
在修改窗口参数的过程中,有时你会发现即使在super里修改了它们的X坐标和Y坐标,好像测试时还是没有改变。这是因为它们的这些参数在Scene里被重新定义过了。比如在Scene_Menu里面,你会看到这样一段:
# 生成状态窗口
@status_window = Window_MenuStatus.new
@status_window.x = 160
@status_window.y = 0
Window_MenuStatus即是代表那个在主菜单里显示我方队员信息的大窗口。在这里它同@status_window这个变量关联起来了,所以@status_window就是这个窗口。然后,下面那句@status_window.x = 160,将这个窗口的X坐标固定在了160。所以即使你在Window_MenuStatus里的super后面修改了X坐标参数,也不会在游戏里看到它改变。但是如果你把@status_window.x = 160修改为180或者别的数字之后,你就会看到它的X坐标改变了。同理,Y坐标也是,将那个0改为其他数字,即可改变此窗口的Y坐标。
窗口的宽和高虽然在Scene里看到的比较少,但你也可以用.width和.height进行重新定义。如果在上面的脚本后面加上一句@status_window.height = 360,你就会发现Super里定义过的高度被改掉了。当然,因此也会出现一些显示缺失的BUG——这就是日后在自己做窗口的时候需要考虑的排版问题了。多数Scene是不会重定义宽高的,想修改的话直接在Window的脚本里修改Super中的参数即可。
练习题:重新给Scene_Menu(主菜单)排版,将金钱窗口、步数窗口、时间窗口等诸多窗口换成不一样的坐标。必要时可试着缩小这些窗口的大小。
提示:按照上面范例所教,@status_window = Window_MenuStatus.new这一句即表示状态窗口是Window_MenuStatus,其宽高可回到Window_MenuStatus里修改super。金钱窗口之类的同理。可参考注释找到相对应的窗口脚本。
核心语句C:self.x(y/z/width/height/opacity/back_opacity) = xxx
这一句还是在Window里面看到的。其中x、y、width和height都不赘述,和核心语句2里讲到的功能一样,是重定义窗口参数的,会覆盖super的定义数据。然后是这个z值——它是指代窗口的优先级,就像显示图片时的序号一样,越大的窗口就在越上面。Opacity和back_opacity是透明度参数,最小0最大255,前者是整个窗口的透明度,后者不包含窗口的边框。
这些参数在Window里修改过后也会直观地体现效果。比如你在Window_Item里的super语句下面插入一句self.back_opacity = 100,然后进入看看效果如何吧。
注意:z和opacity/back_opacity参数在核心语句2里也可以用到。比如说你可以在Scene_Menu上述提到的部分里插入一句@status_window.back_opacity = 100,然后看看效果。另外,增加z参数可以调整窗口的优先级,对排版也能起到一定作用。
2、进阶:修改战斗计算式,角色战斗图排布坐标
核心内容:基本数学运算法则
学习这一章的时候请同时打开F1,数学水平不好的建议再打开计算器(喂)。我将以修改RMXP的默认战斗数据计算方法和角色站位坐标为例进行讲解——想要用自己的战斗计算式,或者想打造横板或45度战斗的同学需要的效果,这一部分即可实现。
首先是自设战斗计算式。在F1里面的默认战斗计算式中,找到伤害计算的部分。拿普通攻击为例,可以看到在默认的计算式里它的基础伤害是这样计算的——
普通攻击
威力 = A 的攻击力 - (B 的物理防御 ÷ 2)
放大率 = 20 + A 的力量
分散度 = 15
然后,在下面还能找到最终伤害的语句——
伤害 = 威力 × 放大率 ÷ 20 × 属性修正 × 必杀修正 × 防御修正 ( ± 分散度 %)
看上去很晕很绕对吧。属性修正必杀修正和防御修正暂且不说,基础威力的计算就很麻烦,在填数据的时候为了掌握平衡度,设定起来也会比较繁琐。那么,要是想把普通攻击的计算式直接改成“威力 = A的攻击力 – B的物理防御”,并且把放大率直接改成A的力量,要怎么做呢?
在脚本里找到Game_Battler 3。它便是掌管『游戏里的战斗者』的脚本(有点英文基础的应该一眼能看懂),然后第三部分负责战斗中的数据计算。在38行你可以看到注释写着“应用通常攻击效果”,这便是普通攻击的计算部分。49行下开始,有这么一小段:
# 计算基本伤害
atk = [attacker.atk - self.pdef / 2, 0].max
self.damage = atk * (20 + attacker.str) / 20
这就是在F1的计算式里提到的那两句威力的计算方式了。只要修改这两句,即可改掉计算方式。
不过修改之前要插一些解说——关于RM里的数字运算符号问题。在脚本中,加号就是“+”,减号就是“-”,但是乘号不是“×”而是“*”,除号则是“/”。(是向左撇的斜杠方向别搞反)然后,小括号的用法和数学里一样,但是中括号的用法不同。如果想要括号里套括号,直接都用小括号即可。等号就是“=”,表示赋值(令a等于xxx),然后你在脚本里应该还会看到一个和等号样子很像的符号“==”(双等号),它是用来判断两个变量或数值『是否相等』的,不要和等号搞混。关于比较符号我们在下一章讲变量开关用法时会详细提到。
在运算上,加法、减法和乘法都和数学计算没区别,但除法有点不同。在脚本计算里面,除法运算的结果并不含小数位,而且会直接将小数位省略,不会四舍五入。比方说,如果你在式子里写了1 / 2的话,脚本对其的计算结果是0,而不是0.5或者1。如果你写了4 / 3的话,结果就是1而不是1.333333……。
另外,还有一个比较特殊的计算符号“%”,它表示取余数。比如说,4 % 3 = 1,6 % 2 = 0。能看明白意思么?只要除不尽有余数的话,余数就是答案,而如果能除尽,就等于0。
简而言之,这些内容大多数都还是诸位小学时候的数学知识,只要回顾起来,修改伤害计算式就一点不难。
还是不会的……别改脚本了,先去让小学数学老师揍你一顿再说吧。(喂喂)
基础补完,我们继续回到上面提及的两句脚本。不妨将中文版本的计算式拿来对应着看看,马上就能发现,这里atk就是威力(基础伤害),attacker.atk就是A的攻击力,self.pdef就是B的物理防御力。至于那个中括号[attacker.atk - self.pdef / 2, 0].max这个内容,现阶段不需要理解也没关系(一定要理解的话,在帮助手册里搜索max可以查到其解说:返回最大的元素。在这里,表示在“A攻击力 – B防御力除以2”的计算结果和0之间取一个最大值。这就避免了万一A攻击力减去B防御力之后为负,导致攻击敌人反倒给敌人加血的囧状)。我们只要会改计算的那一部分就够了。按照目标,我们想要威力单纯等于攻击力 – 敌方防御,那么就修改成如下内容:
atk = [attacker.atk - self.pdef, 0].max
下面那句稍显复杂,不过稍微研究一下也能看出来是有关放大率的内容。那个20 + attacker.str,正好和计算式里“20 + A 的力量”对应。那么,如果想让放大率只等于A的力量,把前面的“20 +”和包在外面的那个括号删掉即可。
再然后,可以注意到那个“/ 20”,它对应的就是最终威力里的“放大率 ÷ 20”了。如果不想再多此一举地计算,连它也可以删掉。这样经过修改之后,你的计算式就变成了——
普通攻击伤害 = (A的攻击力 – B的防御)× A的力量 ×分散度 ×各种其他影响系数
相比之下,是不是显得简洁些了呢。当然如果你想要繁琐的话,只要在相应变量后面加上数字运算就行了。比如把基础威力设计为“(attacker.atk * 10 + attacker.str) - self.pdef / 5”的话,基础威力就等于“A的攻击力×10 + A的力量 – B的物理防御/5”……(= =)
而且经过对应之后,你应该能够看得出来,战斗计算式里的各种参数在Game_Battler 3里,分别都是哪些语句。
练习题:修改技能的基本威力计算式为“威力 = 技能的数据库威力 – (B的魔法防御 / 2 +B的物理防御)”,然后再按照自己的喜好修改影响最终威力的放大率等。
提示:技能伤害的计算部分在99行下“应用特技效果”那段。
从本篇开始需要会通过脚本里的现有注释来理解某条语句的意思,另外请复习小学的四则运算及括号之类的运用。在RM的脚本里可修改的数字实在是太多了……不能确切搞明白就乱改的话,很容易出错。
接下来我们将由浅入深地分步来教一些比较基本的数字修改。
1、修改窗口的基本参数
核心语句A:super(X坐标, Y坐标, 宽, 高)
所有Window打头的脚本坐标,也就是管游戏里那些界面的窗口的脚本里,基本上你都能找到这么一句。通常它出现在def initialize的下面,表示窗口初始化——可以将其理解为这个窗口刚被造出来的状态。既然女娲要造人了,自然要有人的身高三围……大误,我是说既然脚本要造窗口,就要有个窗口的尺码。在super这句话后面的括号里的四个数字便是一个窗口最基本的参数,就跟人会有体重三围一样。修改它们,就会改变你窗口的样子。
X坐标指的是窗口左上角端点的垂直位置,Y坐标则是指水平位置。RM的窗口都是方形的,所以基准点就是左上角端点,和事件里显示图片指令的左上对称一样。宽和高的概念不用多解释。随便打开一个窗口脚本比如Window_Item(显示持有物品的窗口),试着分别改一下Super后面四个数字,然后保存进入游戏按ESC看看吧。可以每改一个数字就存一次然后测试,就能很清楚地明白该数字修改后表现的是什么效果了。
练习题:修改Window_Status(状态界面窗口),使其略小一点,并居中显示。
提示:RM默认分辨率是640×480,即打开RM之后窗口最大能显示的区域。如果你把窗口的宽和高修改为了400和300,为了让其居中显示,X坐标便是(640-400)/2=120,Y坐标是(480-300)/2=90。算不过来的可以开计算器(……
核心语句B:@xxxxx_window.x (y/width/height) = xxx
在修改窗口参数的过程中,有时你会发现即使在super里修改了它们的X坐标和Y坐标,好像测试时还是没有改变。这是因为它们的这些参数在Scene里被重新定义过了。比如在Scene_Menu里面,你会看到这样一段:
# 生成状态窗口
@status_window = Window_MenuStatus.new
@status_window.x = 160
@status_window.y = 0
Window_MenuStatus即是代表那个在主菜单里显示我方队员信息的大窗口。在这里它同@status_window这个变量关联起来了,所以@status_window就是这个窗口。然后,下面那句@status_window.x = 160,将这个窗口的X坐标固定在了160。所以即使你在Window_MenuStatus里的super后面修改了X坐标参数,也不会在游戏里看到它改变。但是如果你把@status_window.x = 160修改为180或者别的数字之后,你就会看到它的X坐标改变了。同理,Y坐标也是,将那个0改为其他数字,即可改变此窗口的Y坐标。
窗口的宽和高虽然在Scene里看到的比较少,但你也可以用.width和.height进行重新定义。如果在上面的脚本后面加上一句@status_window.height = 360,你就会发现Super里定义过的高度被改掉了。当然,因此也会出现一些显示缺失的BUG——这就是日后在自己做窗口的时候需要考虑的排版问题了。多数Scene是不会重定义宽高的,想修改的话直接在Window的脚本里修改Super中的参数即可。
练习题:重新给Scene_Menu(主菜单)排版,将金钱窗口、步数窗口、时间窗口等诸多窗口换成不一样的坐标。必要时可试着缩小这些窗口的大小。
提示:按照上面范例所教,@status_window = Window_MenuStatus.new这一句即表示状态窗口是Window_MenuStatus,其宽高可回到Window_MenuStatus里修改super。金钱窗口之类的同理。可参考注释找到相对应的窗口脚本。
核心语句C:self.x(y/z/width/height/opacity/back_opacity) = xxx
这一句还是在Window里面看到的。其中x、y、width和height都不赘述,和核心语句2里讲到的功能一样,是重定义窗口参数的,会覆盖super的定义数据。然后是这个z值——它是指代窗口的优先级,就像显示图片时的序号一样,越大的窗口就在越上面。Opacity和back_opacity是透明度参数,最小0最大255,前者是整个窗口的透明度,后者不包含窗口的边框。
这些参数在Window里修改过后也会直观地体现效果。比如你在Window_Item里的super语句下面插入一句self.back_opacity = 100,然后进入看看效果如何吧。
注意:z和opacity/back_opacity参数在核心语句2里也可以用到。比如说你可以在Scene_Menu上述提到的部分里插入一句@status_window.back_opacity = 100,然后看看效果。另外,增加z参数可以调整窗口的优先级,对排版也能起到一定作用。
2、进阶:修改战斗计算式,角色战斗图排布坐标
核心内容:基本数学运算法则
学习这一章的时候请同时打开F1,数学水平不好的建议再打开计算器(喂)。我将以修改RMXP的默认战斗数据计算方法和角色站位坐标为例进行讲解——想要用自己的战斗计算式,或者想打造横板或45度战斗的同学需要的效果,这一部分即可实现。
首先是自设战斗计算式。在F1里面的默认战斗计算式中,找到伤害计算的部分。拿普通攻击为例,可以看到在默认的计算式里它的基础伤害是这样计算的——
普通攻击
威力 = A 的攻击力 - (B 的物理防御 ÷ 2)
放大率 = 20 + A 的力量
分散度 = 15
然后,在下面还能找到最终伤害的语句——
伤害 = 威力 × 放大率 ÷ 20 × 属性修正 × 必杀修正 × 防御修正 ( ± 分散度 %)
看上去很晕很绕对吧。属性修正必杀修正和防御修正暂且不说,基础威力的计算就很麻烦,在填数据的时候为了掌握平衡度,设定起来也会比较繁琐。那么,要是想把普通攻击的计算式直接改成“威力 = A的攻击力 – B的物理防御”,并且把放大率直接改成A的力量,要怎么做呢?
在脚本里找到Game_Battler 3。它便是掌管『游戏里的战斗者』的脚本(有点英文基础的应该一眼能看懂),然后第三部分负责战斗中的数据计算。在38行你可以看到注释写着“应用通常攻击效果”,这便是普通攻击的计算部分。49行下开始,有这么一小段:
# 计算基本伤害
atk = [attacker.atk - self.pdef / 2, 0].max
self.damage = atk * (20 + attacker.str) / 20
这就是在F1的计算式里提到的那两句威力的计算方式了。只要修改这两句,即可改掉计算方式。
不过修改之前要插一些解说——关于RM里的数字运算符号问题。在脚本中,加号就是“+”,减号就是“-”,但是乘号不是“×”而是“*”,除号则是“/”。(是向左撇的斜杠方向别搞反)然后,小括号的用法和数学里一样,但是中括号的用法不同。如果想要括号里套括号,直接都用小括号即可。等号就是“=”,表示赋值(令a等于xxx),然后你在脚本里应该还会看到一个和等号样子很像的符号“==”(双等号),它是用来判断两个变量或数值『是否相等』的,不要和等号搞混。关于比较符号我们在下一章讲变量开关用法时会详细提到。
在运算上,加法、减法和乘法都和数学计算没区别,但除法有点不同。在脚本计算里面,除法运算的结果并不含小数位,而且会直接将小数位省略,不会四舍五入。比方说,如果你在式子里写了1 / 2的话,脚本对其的计算结果是0,而不是0.5或者1。如果你写了4 / 3的话,结果就是1而不是1.333333……。
另外,还有一个比较特殊的计算符号“%”,它表示取余数。比如说,4 % 3 = 1,6 % 2 = 0。能看明白意思么?只要除不尽有余数的话,余数就是答案,而如果能除尽,就等于0。
简而言之,这些内容大多数都还是诸位小学时候的数学知识,只要回顾起来,修改伤害计算式就一点不难。
还是不会的……别改脚本了,先去让小学数学老师揍你一顿再说吧。(喂喂)
基础补完,我们继续回到上面提及的两句脚本。不妨将中文版本的计算式拿来对应着看看,马上就能发现,这里atk就是威力(基础伤害),attacker.atk就是A的攻击力,self.pdef就是B的物理防御力。至于那个中括号[attacker.atk - self.pdef / 2, 0].max这个内容,现阶段不需要理解也没关系(一定要理解的话,在帮助手册里搜索max可以查到其解说:返回最大的元素。在这里,表示在“A攻击力 – B防御力除以2”的计算结果和0之间取一个最大值。这就避免了万一A攻击力减去B防御力之后为负,导致攻击敌人反倒给敌人加血的囧状)。我们只要会改计算的那一部分就够了。按照目标,我们想要威力单纯等于攻击力 – 敌方防御,那么就修改成如下内容:
atk = [attacker.atk - self.pdef, 0].max
下面那句稍显复杂,不过稍微研究一下也能看出来是有关放大率的内容。那个20 + attacker.str,正好和计算式里“20 + A 的力量”对应。那么,如果想让放大率只等于A的力量,把前面的“20 +”和包在外面的那个括号删掉即可。
再然后,可以注意到那个“/ 20”,它对应的就是最终威力里的“放大率 ÷ 20”了。如果不想再多此一举地计算,连它也可以删掉。这样经过修改之后,你的计算式就变成了——
普通攻击伤害 = (A的攻击力 – B的防御)× A的力量 ×分散度 ×各种其他影响系数
相比之下,是不是显得简洁些了呢。当然如果你想要繁琐的话,只要在相应变量后面加上数字运算就行了。比如把基础威力设计为“(attacker.atk * 10 + attacker.str) - self.pdef / 5”的话,基础威力就等于“A的攻击力×10 + A的力量 – B的物理防御/5”……(= =)
而且经过对应之后,你应该能够看得出来,战斗计算式里的各种参数在Game_Battler 3里,分别都是哪些语句。
练习题:修改技能的基本威力计算式为“威力 = 技能的数据库威力 – (B的魔法防御 / 2 +B的物理防御)”,然后再按照自己的喜好修改影响最终威力的放大率等。
提示:技能伤害的计算部分在99行下“应用特技效果”那段。
接下来,我们转到角色战斗图坐标的修改。
在RM默认战斗中,角色都是在画面下方一字排开的。如何将其修改为横版,或者45度的战斗模式呢?其实只要改掉战斗图的数字坐标就能做到。在脚本列表里,找到Game_Actor。这里就是关于游戏的角色的数据控制。一路向下拖到570行,“取得战斗画面的 X 坐标”,可看到下面的这段脚本。
def screen_x
# 返回计算后的队伍 X 坐标的排列顺序
if self.index != nil
return self.index * 160 + 80
else
return 0
end
end
这里解释一下self.index的含义,它代表队伍成员序号(并非角色编号),概念上和你在使用事件指令的『强制行动』时指令角色的那个1人2人一样,也就是目前在队的角色的序号。所以self.index最大数目是3,最小数目是0(在这里0代表队伍里第一个角色)。所以,在这个计算式里,角色战斗图的X坐标就是——第一个角色为80,第二个角色为240,第三个角色为400,第四个角色为560(当self.index分别为0、1、2、3时将其代入self.index * 160 + 80计算可得)要改动角色在画面上的垂直位置,改动这个self.index * 160 + 80就可以了。
同理,下面那一截关于Y坐标的脚本也一样,只不过因为角色在水平线上一字排开,所以Y坐标是一样的。要改得不一样的话,照猫画虎地把X坐标里那堆复制粘贴下来再修改数字就行了。Z坐标(讲窗口时提到过它指代优先级系数,没忘记吧?)也是一样,默认的是4-self.index,序号越大优先级越小,你可以把大家的优先级都调得一致,或者反过来直接改成self.index,这样序号越大优先级就越大了。
修改的过程就不用特别废话了,可以先设定好角色的坐标在哪里,也可以自己慢慢地代入数字来尝试。以下是一个改好的横版范例(附截图),你也可以改一改你自己喜欢的排布坐标然后在游戏里看看效果。
X坐标return self.index * 60 + 380
Y坐标 return self.index % 2 * 150 + 220
(这里加了个%2的效果,令角色站成了两行,请通过计算自行理解)
Z坐标 return self.index
在RM默认战斗中,角色都是在画面下方一字排开的。如何将其修改为横版,或者45度的战斗模式呢?其实只要改掉战斗图的数字坐标就能做到。在脚本列表里,找到Game_Actor。这里就是关于游戏的角色的数据控制。一路向下拖到570行,“取得战斗画面的 X 坐标”,可看到下面的这段脚本。
def screen_x
# 返回计算后的队伍 X 坐标的排列顺序
if self.index != nil
return self.index * 160 + 80
else
return 0
end
end
这里解释一下self.index的含义,它代表队伍成员序号(并非角色编号),概念上和你在使用事件指令的『强制行动』时指令角色的那个1人2人一样,也就是目前在队的角色的序号。所以self.index最大数目是3,最小数目是0(在这里0代表队伍里第一个角色)。所以,在这个计算式里,角色战斗图的X坐标就是——第一个角色为80,第二个角色为240,第三个角色为400,第四个角色为560(当self.index分别为0、1、2、3时将其代入self.index * 160 + 80计算可得)要改动角色在画面上的垂直位置,改动这个self.index * 160 + 80就可以了。
同理,下面那一截关于Y坐标的脚本也一样,只不过因为角色在水平线上一字排开,所以Y坐标是一样的。要改得不一样的话,照猫画虎地把X坐标里那堆复制粘贴下来再修改数字就行了。Z坐标(讲窗口时提到过它指代优先级系数,没忘记吧?)也是一样,默认的是4-self.index,序号越大优先级越小,你可以把大家的优先级都调得一致,或者反过来直接改成self.index,这样序号越大优先级就越大了。
修改的过程就不用特别废话了,可以先设定好角色的坐标在哪里,也可以自己慢慢地代入数字来尝试。以下是一个改好的横版范例(附截图),你也可以改一改你自己喜欢的排布坐标然后在游戏里看看效果。
X坐标return self.index * 60 + 380
Y坐标 return self.index % 2 * 150 + 220
(这里加了个%2的效果,令角色站成了两行,请通过计算自行理解)
Z坐标 return self.index
练习题:自行尝试着改造出一个45度或者三角形队列(……)的战斗画面。
提示:现在还没有教大家使用case分歧,到后面掌握了脚本的分歧用法之后,也可以不需要让self.index参与计算。不过现在为了熟悉数字修改,还是按默认的格式修改吧。
【数字篇•范例二:了解数字的源头在哪里】
1、从Window_Status追溯到Window_Base
核心语句:draw_actor_xxxxxx(@actor,x,y)
修改窗口内的文字坐标、大小与宽高,同样是排版的重要一环。我们已经学会了修改窗口的数字,那么怎么修改窗口内文字的位置与大小呢。以Window_Status为例(人物的状态窗口),打开之后你可以看到,里面有很多draw_actor_xxxx的语句,后面还跟着一个装有不少数字的括号。
这些其实就是游戏里,用来表示角色数据的描绘语句。其具体内容稍后再讲,首先我们看那些括号里的内容。@actor表示与角色挂钩,而后面的两个数字,就是坐标位置。可以随意进行修改,进而改变描绘数值的坐标。
比如说draw_actor_hp(@actor, 96, 112, 172)这一句。看到hp我们大概能够推测得出,它是和角色hp相关的内容。把96和112两个数字修改一下,然后进入游戏看看吧。你可以看到描绘HP的那一部分整个都挪动了。至于172那个数字暂时不要动,同理下面的draw_actor_parameter(@actor, 96, 192, 0)里,也只先修改前两个数字,不要动最后一个。
好,现在所有draw_actor_xxxx的句子你应该已经会调坐标了。那么大小呢?这个也先放着不说,因为接下来我们要做的是吃透draw_actor_xxxx这套语句。用全局搜索Ctrl+Shift+F这一热键呼叫出搜索窗口,然后输入“draw_actor_name”并按“开始搜索”。
你可以看到下面这个窗口,列出了很多用到这句话的地方。我们转到第一个地方,Window_Base。
提示:现在还没有教大家使用case分歧,到后面掌握了脚本的分歧用法之后,也可以不需要让self.index参与计算。不过现在为了熟悉数字修改,还是按默认的格式修改吧。
【数字篇•范例二:了解数字的源头在哪里】
1、从Window_Status追溯到Window_Base
核心语句:draw_actor_xxxxxx(@actor,x,y)
修改窗口内的文字坐标、大小与宽高,同样是排版的重要一环。我们已经学会了修改窗口的数字,那么怎么修改窗口内文字的位置与大小呢。以Window_Status为例(人物的状态窗口),打开之后你可以看到,里面有很多draw_actor_xxxx的语句,后面还跟着一个装有不少数字的括号。
这些其实就是游戏里,用来表示角色数据的描绘语句。其具体内容稍后再讲,首先我们看那些括号里的内容。@actor表示与角色挂钩,而后面的两个数字,就是坐标位置。可以随意进行修改,进而改变描绘数值的坐标。
比如说draw_actor_hp(@actor, 96, 112, 172)这一句。看到hp我们大概能够推测得出,它是和角色hp相关的内容。把96和112两个数字修改一下,然后进入游戏看看吧。你可以看到描绘HP的那一部分整个都挪动了。至于172那个数字暂时不要动,同理下面的draw_actor_parameter(@actor, 96, 192, 0)里,也只先修改前两个数字,不要动最后一个。
好,现在所有draw_actor_xxxx的句子你应该已经会调坐标了。那么大小呢?这个也先放着不说,因为接下来我们要做的是吃透draw_actor_xxxx这套语句。用全局搜索Ctrl+Shift+F这一热键呼叫出搜索窗口,然后输入“draw_actor_name”并按“开始搜索”。
你可以看到下面这个窗口,列出了很多用到这句话的地方。我们转到第一个地方,Window_Base。
所谓Base,意思便是基础。我们可以将其理解成种出蔬菜的菜地。在这里生长的蔬菜(定义出的基本语句)被拿去到厨房(别的Window类)里做成菜肴(用来组成不同窗口的内容),但蔬菜的本质没有改变。看到我们转到的部分——
#--------------------------------------------------------------------------
# ● 名称的描绘
# actor : 角色
# x : 描画目标 X 坐标
# y : 描画目标 Y 坐标
#--------------------------------------------------------------------------
def draw_actor_name(actor, x, y)
self.contents.font.color = normal_color
self.contents.draw_text(x, y, 120, 32, actor.name)
end
在这里很明显就给出了描绘角色名字的解释。def这个关键字就是“种出一种蔬菜”的概念,我们姑且理解成——def(种) draw_actor_name(萝卜)这样的概念。后面的括号里,则是关于它的具体参数,与角色挂钩,然后还有它能够描绘的x和y坐标。把这三个内容装进括号之后,只要在Window_status里想描绘角色的名字,直接写draw_actor_name出来,然后再在括号里写出@actor(与角色挂钩,为何要加@我们回头再说),并用数字定义出x坐标和y坐标就行了。——所谓的,萝卜就种在这里,下锅前直接把萝卜拿去切片切丝切丁都随你处置。这个x与y,就是切丝切丁之类的,是你可以随意处置的数字。
再来搜索一个draw_actor_parameter。这里你可以看到括号里多了一个数字出来。
def draw_actor_parameter(actor, x, y, type)
这个type,就对应了刚才说过的不能乱改的第3个数字。它指代什么呢?角色能力类型。也就是攻击力、防御力、魔力、力量这样的参数。在这里有一个case分歧,它将type硬性规定在了0~6之间,所以type只能被赋予0~6之间的某个数字。当然,每个数字都对应不同的一种能力描绘。比如draw_actor_parameter(@actor, 96, 192, 0)表示描绘攻击力,而draw_actor_parameter(@actor, 96, 224, 1)就表示描绘物理防御了。
最后再以HP的描绘为例。定位到这里:def draw_actor_hp(actor, x, y, width = 144)。在这里括号里多出了一个width参数,它表示整体宽度。在游戏里描绘HP的时候,并不是一两个字,而是类似【HP 765/765】这样的模式。这个width就表示它整体的可用宽度空间。在这里被初始化成了144,但在你于别的窗口里使用draw_actor_hp时,这个数字就能改的。通过拉长或者压缩它的宽度,你可以发现这串字可使用的空间在改变。(如果改到100,这串字就会被切掉一部分了)。具体的空间计算方法也在下面,是很直观的数字计算,你可以把width代入计算一下看看就能明白了。
2、基本描绘语句与相关系数
核心语句:self.contents.draw_text(x,y,字符串宽度,字符串高度,字符串内容,对齐方式)
这一部分内容本来应该在第三章才开始讲,不过因为也涉及了数字的内容并且如果不吃透这句话就没法吃透Window_Base的大多数def里的内容,所以提到这里先说吧。这一句就是描绘字符串的基本语句。基本上只要是在窗口内用脚本写字,就不能少了它。
self.contents.draw_text先照搬下来,然后我们看括号里的几个参数。X和Y不用多说了是表示坐标的,在Window_Base里大多数时候它们没有直接写成数字,而是用未知数X与Y直接替代,这样你在未来调用语句的时候,可以为X和Y赋值进而随意改变它的坐标(这也是为什么上面说x坐标和y坐标你可以随便改但别的数字先不要轻易动)。
字符串宽度,所谓的width,就是指你给你的字符串提供的描绘宽度。我没有细致计算过RM里每一个字的宽度,但一个中文大概宽度等于32,一个英文或数字大约等于16。要根据你想描绘的字符串的总宽度为它安排大于或等于的空间,否则就会出现装不下而切字的状况。
然后是字符串高度。同理不能太小,否则会把字给腰斩。大多数时候默认为32。
再后面就是具体的字符串内容了。有些变量本身就是字符串,比如actor_name(角色名字),但有些并不是,而是一个数值,比如actor.level(等级)。后者是不能直接写进来的,需要加一个.to_s在后面,表示将数字转化为字符串。(请对比def draw_actor_name和下面def draw_actor_level的区别)如果你想要写自己随意定义内容的字符串,就要用双引号框起来,这一点千万不能忘记。
但如果直接描绘一个定义好的变量就不需要用双引号。比如说:
blx = “老子世界第一”
self.contents.draw_text(x,y,144,32,blx)
这两句的效果和
self.contents.draw_text(x,y,144,32,”老子天下第一”)
所描绘出来的内容是一样的。
最后一个数字可加可不加,有时候你也会看到它。这代表字符串的对齐方式。即是说在你给出的描绘空间里,字符串是如何对齐的。0代表左对齐,1代表居中,2代表右对齐。当你把宽度拉得很大,有比较多空间的时候,改变这个参数会让你的字符串有不同的坐落位置。
接下来我们找到def draw_actor_hp,对其中的每一句字符描绘进行解说。
def draw_actor_hp(actor, x, y, width = 144)
# 描绘字符串 "HP"
self.contents.font.color = system_color
【↑这句话是字符颜色定义。system_color也是之前就被“种”好的内容,你可以在Window_Base里同样找到def system_color。关于颜色的语句内容下面再讲。】
self.contents.draw_text(x, y, 32, 32, $data_system.words.hp)
【↑关于“HP”这个名称的描绘。$data_system.words.hp是数据库变量,代替你在数据库“系统”选项卡里填的HP称呼。你要是在数据库改成了“生命”它就会描绘“生命”,但是这样一来你会发现32的宽度就太窄了,字被压扁了。试着改成64来看看是不是好些了吧。】
# 计算描绘 MaxHP 所需的空间
if width - 32 >= 108
hp_x = x + width - 108
flag = true
elsif width - 32 >= 48
hp_x = x + width - 48
flag = false
end
【↑这里是一堆计算和分歧的应用,计算一个新变量hp_x的数值(用于下面的描绘)以及flag这个变量的成立与否。分歧的知识我们会在第二章细讲。】
# 描绘 HP
self.contents.font.color = actor.hp == 0 ? knockout_color :
actor.hp <= actor.maxhp / 4 ? crisis_color : normal_color
【↑这一句很长也很绕,是关于hp字符串颜色的判定,在hp小于一定数值的时候,用不同的颜色来描绘。】
self.contents.draw_text(hp_x, y, 48, 32, actor.hp.to_s, 2)
【↑描绘角色的当前hp(变量actor.hp,加了.to_s表示转换为字符串,最后那个2表示靠右端对齐)。要注意的是,在这里用到的x坐标并不是你在Window_status里赋值的那个x坐标,而是在上面重新计算过的hp_x。也就是说在Window_status里面你写了draw_actor_hp(@actor, 96, 112, 112)之后,它实际描绘的坐标是x + width – 48,即是96 + 112 - 48 = 160。……= =特多此一举是不是?把hp_x直接改成x就能更清静了。其实在运用熟练之后,你完全可以改掉默认的描绘方式使用更简洁的描绘法。】
# 描绘 MaxHP
if flag
【↑条件分歧,如果flag变量成立(判断是否成立见上面的计算过程),即指有地方给你描绘maxhp的时候】
self.contents.font.color = normal_color
【↑给Maxhp设定文字颜色】
self.contents.draw_text(hp_x + 48, y, 12, 32, "/", 1)
【↑描绘夹在当前HP和MAXHP之间的那个斜杠。这里就是自定义的字符串了,注意这里的双引号和对齐方式,是居中对齐。同样它的x坐标也是那个需要重计算的hp_x……】
self.contents.draw_text(hp_x + 60, y, 48, 32, actor.maxhp.to_s)
【↑描绘最大hp数值。同样因为actor.maxhp这个变量是一数字所以要用.to_s转换。】
end
end
练习题:
把在def draw_actor_hp里面的这两段
if width - 32 >= 108
hp_x = x + width - 108
flag = true
elsif width - 32 >= 48
hp_x = x + width - 48
flag = false
end
用#号注释掉。把下面的if flag用#号注释掉,再注释掉一个end。然后把括号里面的width=xxx也删掉。(去掉判断maxhp/maxsp是否有位置的这个宽度系数)将hp_x全改为x。
然后调整各个字符串的坐标,确保无论你的hp和maxhp是三位数还是四位数,在菜单里都能正常和完整地显示出来。(必要的时候可改文字大小,具体改法见下面的教学)
def draw_actor_sp进行同理修改。
提示:这样改过之后,draw_actor_hp后面括号里除了actor外就只有两个数字了,在Window_Status以及其他draw_actor_hp的地方也要记得进行更正。(利用好全局搜索)
3、文字颜色与大小的修改(附加)
核心语句:self.contents.font.size = 字号/ self.contents.font.color = Color.new(R,G,B,强度)
这两句是依附于self.contents.draw_text的,用来更改你接下来要描绘的文字的大小和属性。Size那句不用说了,直接在后面写上字号即可。默认的字号是22号,可以改大改小都没问题。当你改小之后,如果在self.contents.draw_text保持原本的宽高,那么字间距也会拉大。而且要注意的是一旦在哪里加上self.contents.font.size = 20的话,下面所有描绘的字都会变成20号。想恢复的话就要再补一句self.contents.font.size = 22才行。
文字颜色的话,在Window_Base里面应该能看到很多。self.contents.font.color = normal_color是最常见的一句,但是normal_color又是什么呢?进行全局搜索之后你可以看到它是这么被『种』出来的:
def normal_color
return Color.new(255, 255, 255, 255)
end
Color.new(xxx,xxx,xxx,xxx)在这里就是关键语句了。它是定义颜色用的。括号里的四个数字分别代表R,G,B数值和颜色强度。如果要特定一种颜色该怎么设呢?有个简单的方法。打开你的数据库,选择“动画”,随便在“SE与闪烁时机”那里点一下叫出窗口,选择“对象”。然后你可以通过拖动滑块来看到颜色的变化,而右边的几个数字正是它的RGB数值。强度变量看得不够直观,你可以将其理解成透明度。也就是说第四个数字越小,透明度越低。
#--------------------------------------------------------------------------
# ● 名称的描绘
# actor : 角色
# x : 描画目标 X 坐标
# y : 描画目标 Y 坐标
#--------------------------------------------------------------------------
def draw_actor_name(actor, x, y)
self.contents.font.color = normal_color
self.contents.draw_text(x, y, 120, 32, actor.name)
end
在这里很明显就给出了描绘角色名字的解释。def这个关键字就是“种出一种蔬菜”的概念,我们姑且理解成——def(种) draw_actor_name(萝卜)这样的概念。后面的括号里,则是关于它的具体参数,与角色挂钩,然后还有它能够描绘的x和y坐标。把这三个内容装进括号之后,只要在Window_status里想描绘角色的名字,直接写draw_actor_name出来,然后再在括号里写出@actor(与角色挂钩,为何要加@我们回头再说),并用数字定义出x坐标和y坐标就行了。——所谓的,萝卜就种在这里,下锅前直接把萝卜拿去切片切丝切丁都随你处置。这个x与y,就是切丝切丁之类的,是你可以随意处置的数字。
再来搜索一个draw_actor_parameter。这里你可以看到括号里多了一个数字出来。
def draw_actor_parameter(actor, x, y, type)
这个type,就对应了刚才说过的不能乱改的第3个数字。它指代什么呢?角色能力类型。也就是攻击力、防御力、魔力、力量这样的参数。在这里有一个case分歧,它将type硬性规定在了0~6之间,所以type只能被赋予0~6之间的某个数字。当然,每个数字都对应不同的一种能力描绘。比如draw_actor_parameter(@actor, 96, 192, 0)表示描绘攻击力,而draw_actor_parameter(@actor, 96, 224, 1)就表示描绘物理防御了。
最后再以HP的描绘为例。定位到这里:def draw_actor_hp(actor, x, y, width = 144)。在这里括号里多出了一个width参数,它表示整体宽度。在游戏里描绘HP的时候,并不是一两个字,而是类似【HP 765/765】这样的模式。这个width就表示它整体的可用宽度空间。在这里被初始化成了144,但在你于别的窗口里使用draw_actor_hp时,这个数字就能改的。通过拉长或者压缩它的宽度,你可以发现这串字可使用的空间在改变。(如果改到100,这串字就会被切掉一部分了)。具体的空间计算方法也在下面,是很直观的数字计算,你可以把width代入计算一下看看就能明白了。
2、基本描绘语句与相关系数
核心语句:self.contents.draw_text(x,y,字符串宽度,字符串高度,字符串内容,对齐方式)
这一部分内容本来应该在第三章才开始讲,不过因为也涉及了数字的内容并且如果不吃透这句话就没法吃透Window_Base的大多数def里的内容,所以提到这里先说吧。这一句就是描绘字符串的基本语句。基本上只要是在窗口内用脚本写字,就不能少了它。
self.contents.draw_text先照搬下来,然后我们看括号里的几个参数。X和Y不用多说了是表示坐标的,在Window_Base里大多数时候它们没有直接写成数字,而是用未知数X与Y直接替代,这样你在未来调用语句的时候,可以为X和Y赋值进而随意改变它的坐标(这也是为什么上面说x坐标和y坐标你可以随便改但别的数字先不要轻易动)。
字符串宽度,所谓的width,就是指你给你的字符串提供的描绘宽度。我没有细致计算过RM里每一个字的宽度,但一个中文大概宽度等于32,一个英文或数字大约等于16。要根据你想描绘的字符串的总宽度为它安排大于或等于的空间,否则就会出现装不下而切字的状况。
然后是字符串高度。同理不能太小,否则会把字给腰斩。大多数时候默认为32。
再后面就是具体的字符串内容了。有些变量本身就是字符串,比如actor_name(角色名字),但有些并不是,而是一个数值,比如actor.level(等级)。后者是不能直接写进来的,需要加一个.to_s在后面,表示将数字转化为字符串。(请对比def draw_actor_name和下面def draw_actor_level的区别)如果你想要写自己随意定义内容的字符串,就要用双引号框起来,这一点千万不能忘记。
但如果直接描绘一个定义好的变量就不需要用双引号。比如说:
blx = “老子世界第一”
self.contents.draw_text(x,y,144,32,blx)
这两句的效果和
self.contents.draw_text(x,y,144,32,”老子天下第一”)
所描绘出来的内容是一样的。
最后一个数字可加可不加,有时候你也会看到它。这代表字符串的对齐方式。即是说在你给出的描绘空间里,字符串是如何对齐的。0代表左对齐,1代表居中,2代表右对齐。当你把宽度拉得很大,有比较多空间的时候,改变这个参数会让你的字符串有不同的坐落位置。
接下来我们找到def draw_actor_hp,对其中的每一句字符描绘进行解说。
def draw_actor_hp(actor, x, y, width = 144)
# 描绘字符串 "HP"
self.contents.font.color = system_color
【↑这句话是字符颜色定义。system_color也是之前就被“种”好的内容,你可以在Window_Base里同样找到def system_color。关于颜色的语句内容下面再讲。】
self.contents.draw_text(x, y, 32, 32, $data_system.words.hp)
【↑关于“HP”这个名称的描绘。$data_system.words.hp是数据库变量,代替你在数据库“系统”选项卡里填的HP称呼。你要是在数据库改成了“生命”它就会描绘“生命”,但是这样一来你会发现32的宽度就太窄了,字被压扁了。试着改成64来看看是不是好些了吧。】
# 计算描绘 MaxHP 所需的空间
if width - 32 >= 108
hp_x = x + width - 108
flag = true
elsif width - 32 >= 48
hp_x = x + width - 48
flag = false
end
【↑这里是一堆计算和分歧的应用,计算一个新变量hp_x的数值(用于下面的描绘)以及flag这个变量的成立与否。分歧的知识我们会在第二章细讲。】
# 描绘 HP
self.contents.font.color = actor.hp == 0 ? knockout_color :
actor.hp <= actor.maxhp / 4 ? crisis_color : normal_color
【↑这一句很长也很绕,是关于hp字符串颜色的判定,在hp小于一定数值的时候,用不同的颜色来描绘。】
self.contents.draw_text(hp_x, y, 48, 32, actor.hp.to_s, 2)
【↑描绘角色的当前hp(变量actor.hp,加了.to_s表示转换为字符串,最后那个2表示靠右端对齐)。要注意的是,在这里用到的x坐标并不是你在Window_status里赋值的那个x坐标,而是在上面重新计算过的hp_x。也就是说在Window_status里面你写了draw_actor_hp(@actor, 96, 112, 112)之后,它实际描绘的坐标是x + width – 48,即是96 + 112 - 48 = 160。……= =特多此一举是不是?把hp_x直接改成x就能更清静了。其实在运用熟练之后,你完全可以改掉默认的描绘方式使用更简洁的描绘法。】
# 描绘 MaxHP
if flag
【↑条件分歧,如果flag变量成立(判断是否成立见上面的计算过程),即指有地方给你描绘maxhp的时候】
self.contents.font.color = normal_color
【↑给Maxhp设定文字颜色】
self.contents.draw_text(hp_x + 48, y, 12, 32, "/", 1)
【↑描绘夹在当前HP和MAXHP之间的那个斜杠。这里就是自定义的字符串了,注意这里的双引号和对齐方式,是居中对齐。同样它的x坐标也是那个需要重计算的hp_x……】
self.contents.draw_text(hp_x + 60, y, 48, 32, actor.maxhp.to_s)
【↑描绘最大hp数值。同样因为actor.maxhp这个变量是一数字所以要用.to_s转换。】
end
end
练习题:
把在def draw_actor_hp里面的这两段
if width - 32 >= 108
hp_x = x + width - 108
flag = true
elsif width - 32 >= 48
hp_x = x + width - 48
flag = false
end
用#号注释掉。把下面的if flag用#号注释掉,再注释掉一个end。然后把括号里面的width=xxx也删掉。(去掉判断maxhp/maxsp是否有位置的这个宽度系数)将hp_x全改为x。
然后调整各个字符串的坐标,确保无论你的hp和maxhp是三位数还是四位数,在菜单里都能正常和完整地显示出来。(必要的时候可改文字大小,具体改法见下面的教学)
def draw_actor_sp进行同理修改。
提示:这样改过之后,draw_actor_hp后面括号里除了actor外就只有两个数字了,在Window_Status以及其他draw_actor_hp的地方也要记得进行更正。(利用好全局搜索)
3、文字颜色与大小的修改(附加)
核心语句:self.contents.font.size = 字号/ self.contents.font.color = Color.new(R,G,B,强度)
这两句是依附于self.contents.draw_text的,用来更改你接下来要描绘的文字的大小和属性。Size那句不用说了,直接在后面写上字号即可。默认的字号是22号,可以改大改小都没问题。当你改小之后,如果在self.contents.draw_text保持原本的宽高,那么字间距也会拉大。而且要注意的是一旦在哪里加上self.contents.font.size = 20的话,下面所有描绘的字都会变成20号。想恢复的话就要再补一句self.contents.font.size = 22才行。
文字颜色的话,在Window_Base里面应该能看到很多。self.contents.font.color = normal_color是最常见的一句,但是normal_color又是什么呢?进行全局搜索之后你可以看到它是这么被『种』出来的:
def normal_color
return Color.new(255, 255, 255, 255)
end
Color.new(xxx,xxx,xxx,xxx)在这里就是关键语句了。它是定义颜色用的。括号里的四个数字分别代表R,G,B数值和颜色强度。如果要特定一种颜色该怎么设呢?有个简单的方法。打开你的数据库,选择“动画”,随便在“SE与闪烁时机”那里点一下叫出窗口,选择“对象”。然后你可以通过拖动滑块来看到颜色的变化,而右边的几个数字正是它的RGB数值。强度变量看得不够直观,你可以将其理解成透明度。也就是说第四个数字越小,透明度越低。
确定了你需要的颜色后,把这几个数字填入Color.new后面的括号里即可。需要改变文字颜色的时候,即可直接用self.contents.font.color = Color.new(R,G,B,强度)来进行定义了。同样,一旦设好颜色,下面的所有描绘的数值颜色都会改掉了。所以每次只要想变颜色,必须加这么一句进行定义。由于normal_color这个变量已经定义过是白色,你想要白色字的时候,直接写上self.contents.font.color = normal_color就好了。
练习题:找到system_color的『种』点,并更改其颜色。
练习题:找到system_color的『种』点,并更改其颜色。
到此,比较基础的字符串和数字的修改就讲完了。
其实废话了这么多,需要强调的依然是,在更改数字的时候,需要搞清楚数字指代什么,在游戏里显示出来的样子是什么。这一章所讲的内容看似很少,但关键在于举一反三,知道向回追溯。接下来要做的就是发散思维,只要看到带着装有数字的括号,就把前面的语句拿来查查,看看这些数字原本代表的参数为何,然后尝试进行修改。
===本章结束===
其实废话了这么多,需要强调的依然是,在更改数字的时候,需要搞清楚数字指代什么,在游戏里显示出来的样子是什么。这一章所讲的内容看似很少,但关键在于举一反三,知道向回追溯。接下来要做的就是发散思维,只要看到带着装有数字的括号,就把前面的语句拿来查查,看看这些数字原本代表的参数为何,然后尝试进行修改。
===本章结束===