RMMZ的脚本基础

原文:『RPGツクールMZ』スクリプトの使い方基礎

RMMZ使用JavaScript开发。(为简洁,下文简称为js)

一般来说,无需在意,只要使用编辑器中的事件指令就能开发游戏。但总有些细节是事件命令无法顾及的,而且也找不到能解决这些问题的插件。

这种时候,使用脚本写一点js,就能解决很多问题。

另外……在移动路线设置中没有插件指令,所以有时候不得已也会使用脚本,唉唉。

官方帮助的功能说明中,只说到了“将文本作为js进行求值(执行)”。但光这么写谁懂啊!!

因此,这里来介绍一些使用脚本的基础知识。

既然要写js,按理说直接学习js本身就好了,但要到这一步就有点……毕竟有些人的目标并不是要当程序员。

本文面向这类读者,跳过那些js入门书里的繁杂的内容,希望能达到“直接复制粘贴,然后修改一下数字就差不多了”这种程度。

想学习js本身的人,请参考以下教程!

中文的话,也可以

JavaScript 教程 | 菜鸟教程

介绍脚本的页面上写着“可以轻松扩展事件指令”“比插件更轻便”之类的,本文开头也这么说,但实际上使用脚本的门槛相当高。

虽然可以在什么都不懂的情况下复制粘贴来使用,但即使如此,什么都不知道的话也还是会有些心里没底。

为了能在使用脚本的时候更有底气,让大家达到”复制粘贴+改造“的程度,接下来我会列出在使用脚本时会遇到的难点。

参考的脚本集

已经有不少公开的许多方便的脚本示例,所以脚本就从示例集拿来用吧。

这篇文章针对rmmz,不过也姑且准备了rmmv脚本的页面链接。

敬称略

关于著作权

别人写的程序,真的可以复制过来用吗,真的不会在意吗?

在意这一点的人,好眼光!请珍视这份心态,不要随意使用他人作品!

那么来说说脚本。

俳句都能被认可拥有著作权,所以你会感到不安。但仅仅几行的程序就能主张著作权的例子,目前我还没有听说过。通常,它们会被认为“只是一段信息,而不是表达思想情感之类的创作”。特别是先前链接的页面,它们就是以“前提就是复制使用”的方式公开的,所以请大胆地复制粘贴吧。

发布游戏时,不标注著作权信息也可以,不过如果在特别致谢加上脚本集作者名,感觉会更有面子,我也比较喜欢。毕竟一个人开发的话,结尾的制作人员名单会显得很冷清呢。(笑)

顺带一提,即使是范例集,如果把整个页面复制下来公开,果然还是不行的。

另外,像插件那样公开脚本时,如果被人提问却答不上来会急得冒汗,所以参考别人的代码时,也要好好理解后再实践!

此外,明明是自己写的脚本,却答不上别人的提问,这种事也相当常见(笑)

脚本集的使用方法

复制脚本,粘贴,然后改一下。

最开始的时候,就算看不懂什么意思,抱着“能跑起来就算成功”的心态去用,我觉得也ok。

能贴脚本的地方意外的多,大致可以分为“有返回值”和“无返回值”两种类型。

返回值有时也可以直接写成“结果”。

那么基于以上前提,我来介绍一下可以输入脚本的位置。

事件命令

首先在地图事件,或者公共事件的执行内容中,或者从敌群的战斗事件中打开的事件命令窗口中,有一个直截了当就叫脚本的按钮。

img

[3]-[进阶]-[脚本]

img

这里就是按下脚本后出现的窗口,在这里写js,或者直接把代码贴进去。

顺带一提,里面的alert("Hello World");是我随便写的js代码,窗口中央所显示的是右键菜单。之后我会把它写作[脚本]事件指令。

这个指令没有返回值。

设定移动路线

接下来是地图事件或公共事件中的移动路线设定,这里面也有脚本命令。

img

[2]-[移动]-[设定移动路线]

img

[移动命令]-[脚本]

img

虽然看起来很小,但功能和脚本时间命令基本一样,也能打开右键菜单。之后我会把它写作[脚本]移动命令。

没有返回值。

自定义移动路线

接下来是地图事件的自主移动的脚本。

img选择[自主移动]-[类型]-[自定义]出现[路线]

img

和设置移动路线事件命令里的脚本基本一样,最大的区别就是不能指定左上角的目标角色。之后我会称其为[脚本]移动指令。

咦,这不是和之前那个一样吗?

确实。只在必要时候我会写成自主移动的脚本。

没有返回值。

变量操作

接下来在地图事件、公共事件或战斗事件里打开事件命令,找到变量操作,里面也有脚本。

img

[1]-[游戏进程]-[变量操作]

img

[操作数]-[脚本]

之后,我会称其为变量的脚本。

它有返回值,会把返回值设置到你指定的变量里。

条件分岐

最后在地图事件、公共事件或战斗事件打开事件指令窗口,里面也有脚本

img

[1]-[流程控制]-[条件分岐]

img

[4]-[脚本]

之后我会称其为条件的脚本。

它有返回值,会根据返回值来进行条件分歧。

计算公式

好吧,其实还有一个!

实际上,伤害公式那里就是js脚本。

可以直接用已经自带值的a和b(使用者和对象)。另外,虽然不是js功能,但作为计算公式特有的功能,还可以把v[n]当变量来用。

它有返回值,会作为造成的伤害数值。

那么到此结束!

去逛逛我介绍的那些网站,然后找些有趣的脚本复制粘贴玩玩吧!

话虽如此,虽然在这可以结束了,但这次的文章,从这里开始才是重头戏。


为了为今后进一步扩大适用范围做个铺垫,我会适当加上rmmz 非官方js参考的链接,不过没必要一个个去翻看。

等你把这页从头到尾读一遍,对写脚本有了一定程度的习惯后,再去看那个参考手册比较好。

另外,我觉得很多地方不达到一定的熟练度是看不懂的,所以跳着读就行了。

关于脚本写法中那些让人在意的细节

看各个地方的脚本时,会发现虽然说明差不多,但写法上却有微妙的差别。

我觉得如果不讲清楚,有些人可能会不安,所以我来解释一下几个典型的地方。

字母的大小写

js是严格区分字母大小写的!所以 aA 是两个不同的东西。

虽然标识符的大小写不同不会带来功能上的差异,但在js里,作为一种书写惯例,大致有以下几种:

标识符示例 说明 用途
SampleValue 首字母大写,后面用大写字母分隔单词 类(class)
sampleValue 首字母小写,后面用大写字母分隔单词 变量、函数、属性、方法、以及会被赋予可变值的常量
SAMPLE_VALUE 全部大写,用下划线分隔单词 被赋予固定值(字面量)的常量

这些“用途”是什么意思看不懂也没关系,总之它们全都是不同的东西,所以要注意别打错大小写。

果然最安心的办法还是“复制 & 粘贴”!

另外虽然从js本身来说并非固定的格式,但在rmmz中有如下写法:

标识符示例 说明 用途
Sample_Value 首字母大写,用下划线分隔单词 核心脚本里的类
_sampleValue 下划线开头,后面首字母小写并用大写分隔单词 类内部使用的属性
$sampleValue $ 符号开头,后面首字母小写并用大写分隔单词 全局变量

关于这些的详细内容,我会在别的地方再解释。

关于脚本末尾的 ;

看各处介绍的脚本时,会发现有的末尾有 ;,有的没有。

你可能会担心“到底需不需要?没有行不行?”,但基本上是不需要的!

那么 ; 是什么呢?它是“用来分隔脚本的东西”。而且写在脚本里的js都很短,所以大部分情况下没有分隔符也能正常运行。

反过来,像移动路线、条件分歧、计算式这些地方,通常只能写一行,但加上 ; 之后,就可以把多行“叠”在一起写。

如果有返回值的话,会返回最后一个分隔的结果。

比如在变量操作的脚本里写下下面这样,就会按 ; 的每个分隔顺序执行,并返回最后一个分隔的结果 20

1
const a = 4;a * a + a;

我个人经常写比较长的脚本,所以在那种情况下我都会加上 ;

写短脚本的时候我也会习惯性地加上,所以在这个页面里基本上都会带着 ; 来写!

结论:加上分号的话,看起来会比较像专业人士啦 ;(分号)

关于引号

首先,“クォーテーション”这玩意儿是啥啊!——话说,就是引号啦。就是用来括住台词之类的符号。

在js中,被引号括起来的部分会被解释为与程序代码不同的字符串数据。

而在脚本里出现的引号有三种。

值与操作 功能
‘单引号’ 用来括住字符串
“双引号” 用来括住字符串
`反引号` 用来括住字符串

……功能不是一样的嘛!好啦,你先冷静一下。

1
2
"想在文本中使用'单引号'"
'反过来"双引号"也想用'

就像这样,在遇到同一个引号之前,都会被认为是处于被括住的状态,所以就可以把另一种引号写在里面。

……为了这个而存在两种引号,是不是有点傻?你可能会这么想,但js它就是这样的设计啦!!

从编程的角度来说,想把程序代码本身当作字符串来写的情况也时有发生,这时候就方便了。

那么,rmmz游戏本体的脚本,我们称之为核心脚本

核心脚本中基本上使用的是 "(双引号),所以这里我也用 "

尽量把书写格式和核心脚本统一起来,这样在读核心脚本的时候就能没有违和感地读下去(很重要)。

话说回来,你是不是想问“那反引号呢?”!

厉害,你还真记住了。这是在js中后来才引入的方式,可以在字符串中间嵌入js的处理,也可以换行,是一种稍微高性能一点的引号。

1
2
`就像这样,可以嵌入编号 ${id},
也可以直接换行写出来。`

所以,如果把反引号改成双引号或单引号,可能会导致程序无法运行,请注意这一点。

反过来说,双引号和单引号是不能直接换行的,必须用 \n 这个特殊符号来表示换行。

顺便一提,你可能会问:truefalse 或者数字之类的,没有被引号括起来,这样没问题吗?

这些是和字符串不同类型的值,所以就直接写。就是这么回事。

反过来,如果像 "true" 这样用引号括起来,它就会被判断为字符串,然后导致程序无法运行……如果能立刻出问题倒还好,但它往往看起来好像还在正常运作,然后突然就出毛病。所以,没带引号的裸值就直接留着别动,绝对不要加引号!别好心办坏事,千万别加引号!!

关于注释

在js中,// 之后直到行末的字符都会被忽略。这部分可以用来写各种注解,这就叫做注释。

还有用 /**/ 括起来的注释形式,不过我觉得在脚本示例中不太常用。

1
2
3
let a = 0;// 这部分是注释
console.log( a );/* 这部分也是注释
这里还可以换行! */

注释在执行时会被忽略,所以可以不复制,或者复制之后删掉也没关系。

当然,既然会被忽略,就那么留着也行,或者按自己的喜好随便改写里面的文字也可以。

关于脚本中的空白(空格)

脚本里各处都会出现空格,看起来好像有某种规律,但实际上每个脚本的写法都有微妙的不同。

其实并没有什么规律,全凭个人喜好加的!

大家通常都以为编程必须写得很严谨,所以这还挺让人吃惊的吧。

不过,单词(也就是所谓的标识符)中间是不能插入空格的。

1
func ( 12 + 1 , "文本" ) ;

即使把这里的空格去掉,写成下面这样,意思也是一样的。

1
func(12+1,"文字");

另外,全角空格不能用在脚本代码中。但可以用在字符串数据或者注释里面。

杂谈

就我个人而言,大概是这样的风格:「单词前后、逗号等分隔符号的后面、括号内侧、数学符号前后加空格」,以及「函数、方法、控制语句和 ( 之间不加空格」。

func( 12 + 1, "文本" );

说实话,这些地方其实都无所谓,但如果不事先定好,每次写的时候都会纠结“到底要不要加空格呢”,白白浪费时间,真的是纯属浪费。

程序员通常都会定好规则再写,多人协作的时候更是会统一规则(有时甚至是整个公司统一)。

在最近的开发环境中,大多都可以在设置里详细指定空格的添加方式,然后自动帮你格式化代码。真方便!

即使看不懂js,如果看一个插件的内容发现空格的用法没有一致性,那基本上可以断定它的js写法也很随意。

请用这个标准去判断插件的质量。至于我的插件嘛,“因为开发环境会自动整理,所以很整洁!”(笑)

关于方法、属性、数组和对象

……什么鬼?你肯定会这么想。

用脚本的时候,有时候会遇到明明在做类似的事情,写法却微妙地不一样的情况

1
2
$gameMessage._positionType = 2;
$gameMessage.setPositionType( 2 );

看起来这两行都想给 positionType 设置成 2,那这个区别使用到底是怎么回事呢?

另外括号也是,有用 [] 的,有用 () 的…完全搞不懂对吧。

这个解释起来非常麻烦,主要原因大概有两个:

  • 强行使用了没有设想会让用户去用的部分。
  • 本来就没有什么特别的理由,就是用了不同的写法。

我觉得rmmz在区分使用上算是比较没有条理的(个人感想)。

因为编程嘛,这方面不统一也能跑啊!它就是能跑起来!!

要说细节的话,也有那种“不这么写就不行”的场景,但解释起来又琐碎又长,我觉得也听不懂。

所以,这里的结论就是:“就当是那么回事吧,别太纠结了!” —— 就这么定了!!

因为存在叫做“方法”、“属性”、“数组”、“对象”的机制,各自的写法都不一样。

关于这些术语,你暂时先理解到“哦,有这种东西啊”这个程度就可以了。

等你想认真学js的时候,再去查吧。

关于 this

脚本里经常会出现 this 这个词,但要解释它到底是什么,还挺麻烦的。

净是些麻烦事儿呢。

仅限在rmmz的脚本里来说,它是一个根据你写脚本的位置不同,内容也会跟着变的变量。

脚本位置 this 的值
事件指令 Game_Interpreter
移动指令 Game_PlayerGame_Event
变量操作 Game_Interpreter
条件分支 Game_Interpreter

Game_Interpreter 是处理事件指令的机制。

Game_Player 是 [玩家] 角色。

Game_Event 顾名思义就是 [事件]。

所以,即便是同一个 this,在不同位置也拥有完全不同的性质。

参考: Game_Interpreter

参考: Game_Player

参考: Game_Event

具体来说就是,含有 this 的脚本如果写在别的位置,大概率是没法运行的。

因为会出现 “明明写的内容完全没错,可就是跑不起来” 的情况,所以很难找到原因。

请确认好脚本是给事件指令用的,还是给移动指令用的,然后再使用!

如果没有特别说明,基本上可以认为是给事件指令用的,基本不会错。

另外,如果是给 [变量操作] 或 [条件分支] 用的脚本,我觉得应该会有所说明(不会不写的)。

RPG Maker MZ 中常见的模式

虽然从js本身来说没什么特别的意思,但我会介绍一些rmmz特有的、知道了就能加深理解的信息。

小键盘对应

在rmmz中,指定角色的朝向或移动方向等时,会使用数字。

小键盘 | 方向

7 8 9 ↖︎ ↗️
4 5 6
1 2 3 ↙︎ ↘︎

就是这样对应的,比如数字 4 就是 ← 方向。顺便一提,数字 5 基本上会被忽略。

这个知道了的话还挺好懂的,但如果不知道,我觉得就很难消除“为什么 4 是左?”这样的疑问了。

以 $ 开头的标识符

看脚本的时候,会时不时碰到以 $ 开头的标识符。

这在js本身中并没有什么特殊含义,是核心脚本独有的一个规则,用来表示这是一个全局变量。

全局变量无论是在 [脚本] 事件指令、移动路线设置里的 [脚本]、变量的 [脚本],还是条件的 [脚本] 中,都可以同样地使用。

另外,在测试游戏时按 [F8] 键调出的 [开发者工具] 的 [控制台] 里,也可以使用它们。

参考:全局变量一览

以大写字母开头的标识符

除了以 $ 开头的标识符之外,还有一些全局可用的东西是以大写字母开头的标识符。
这在js本身中也没什么特别的意思,但几乎所有人都在遵守,所以可以说是事实上的标准。
rmmz主要有以下这些

标识符 说明
AudioManager 音频环境的管理
BattleManager 战斗的管理
ColorManager 颜色数据的管理
ConfigManager 设置的管理
DataManager 数据输入的管理
EffectManager 特效的管理
FontManager 字体的管理
ImageManager 图像数据的管理
PluginManager 插件的管理
SceneManager 场景的管理
SoundManager 声音数据的管理
StorageManager 存档数据的管理
TextManager 文本的管理
Graphics 图像的处理
Input 手柄・键盘输入的处理
TouchInput 鼠标・触摸输入的处理
Utils 其他处理
Video 视频的处理

除此之外,还有其他以大写字母开头的全局可用标识符,不过主要的应该就是这些了。

以 _ 开头的标识符

看脚本的时候,会时不时碰到以 _ 开头的标识符。

这在js本身中并没有什么特殊含义,是核心脚本独有的一个规则,用来表示这是一个局部性质的值。

虽然说是“局部”,但实际上并不是只能局部使用,它的意思大概只是比较宽松地提醒一下:“带 _ 的,大家尽量别用哦”,仅此而已。

(顺便一提,带 $ 的全局变量确实可以全局使用,但并不是因为带了 $ 所以就能全局用,只是核心脚本采用了给全局变量加上 $ 这个规则而已。)

这是因为js缺乏把东西真正局部隐藏起来的手段,所以只能用“提个请求”这种方式来凑合,是个挺悲伤的理由。

实际上,大家并没有太在意,还是用得很欢的(笑)。

但是,如果同时存在 _namename() 并且都能取到相同的值,那么使用后者 name() 才是正规方法,而且两者的行为有时也会不一样。

比如,取到的值可能会被转换成整数之类的,就是这样的区别。

反过来,如果不需要那种额外的处理,有时也会故意直接用 _name

另外,有时候虽然有 _name,但核心脚本里并没有准备 name(),这种情况下就只能用 _name 了。

真是够复杂的呢。

顺便一提,标识符末尾如果带有表示复数的 s,手抄的时候也容易漏掉,所以这点也要注意。

结论就是:如果你用复制粘贴的方式使用,就不需要在意这些;但如果你要手抄,小心别漏掉那个 _

话说回来……标识符这种东西,总之还是尽量用复制粘贴吧![⌘C] 和 [⌘V] 走起!

js控制台

在测试游戏时,按 [F8](或者 [F12])键,就会打开[开发者工具]窗口。

使用这个工具,可以进行各种开发方面的调查。

其中特别重要的是js控制台。

打开控制台

在[帮助] - [辅助工具的使用方法] - [测试游戏]里,只写了一句话“开发者工具的功能与 Google Chrome 内置的工具相同”,就这么甩锅给 Chrome 的帮助文档了!

去看 Google 官方帮助网站就行了,说没问题倒也没问题……哇哦!This is English!

所以呢,我推荐JAVASICIPT.INFO 开发者控制台这个网站。

另外,在实际的 Chrome 浏览器中,可以用 [⌥⌘I] 打开开发者工具。用 [⌥⌘J] 的话,可以直接打开js控制台。

[开发者工具] 的功能非常强大,如果要正经地用js进行开发,它是绕不开的,而且用起来会非常方便!

不过因为它能做的事情太多了,所以这里我先只挑一些在写[脚本]时知道会比较有用的部分,摘出来介绍给大家。

用 [F8] 打开的[开发者工具]中,写着 [Console] 的那个标签页就是js控制台。

img

DevTools failed to load SourceMap: Could not load content for chrome-extension://njgcanhfjdabfmnlmpmdedalocpafnhl/js/libs/pixi.js.map: System error: net::ERR_FILE_NOT_FOUND

会显示这样一条信息对吧。

这个信息根据环境(OS 或 NW.js 的版本)不同,显示上可能会有些差异,但总之就是告诉你 “pixi.js.map” 这个文件不存在。

<Bad!> 要说这个文件是否需要,其实是不需要的,但就因为能正常运行就把这种错误信息放着不管,我觉得作为产品来说有点不太好。

NW.js 是一种应用,为了让rmmz的游戏能以应用程序的形式运行,而提供接近浏览器环境的运行环境。

小知识

“pixi.js.map” 这个文件,里面装的是在发布时不需要、但在开发时需要的信息,也就是用于关联相关信息的东西。

rmmz使用了名为 “pixi.js” 的js库(一个集合了可供程序调用的功能的程序),但在用 RPG Maker 开发游戏时,虽然会看到核心脚本,但作为其基础的 pixi.js 库本身的开发是不需要的,所以没有附带 “pixi.js.map” 这个文件。

如果在 “pixi.js.map” 文件里写下以下内容,然后把它放到 “js/libs/“ 文件夹中,上面的错误就不会再出现了。

1
2
3
{
"sources": []
}

正如你所见,这是一个没什么实际内容的虚拟文件。

或者,删除 “js/libs/“ 文件夹中 “pixi.js” 文件末尾的注释,错误也不会再出现。

1
//# sourceMappingURL=pixi.js.map

另外,对于进行此更改后可能出现的任何问题,我不提供任何保证。

话说回来,这篇文章整体都是这样。出了问题我也不管哦!请自行承担责任,please!

运行 JavaScript

点击控制台中显示 > 的地方,就可以输入并执行 JavaScript。

试着做一下最基本的计算。

1
1+1

对于输入的内容,结果会实时显示出来。哦哦,高科技!

如果是像计算这样只要知道答案就好,那没问题;但如果需要让什么东西动起来,就按 [回车] 键执行。

注意,图像等画面如果不选中游戏窗口,显示是不会更新的。

在控制台中,this 里面是(浏览器的)Window。粗略来说,它处于“最外层”的位置。

在 [脚本] 中不会出现这种状态,所以无法测试含有 this 的脚本。

这么一来,你可能会觉得没法测试脚本了,但请回想一下:带 $ 的全局变量等是可以随处使用的。

没错,如果是全局变量,就可以在控制台中执行。

没必要每次都在 [脚本] 事件指令里写好,然后测试游戏,再去触发 [执行内容]!

如果示例代码是以 $ 开头的,那基本上肯定可以在 [控制台] 中执行,所以请灵活运用,多多尝试。

1
$gamePlayer.setDirection(6);

在地图上显示着玩家的时候,试着把这个脚本复制粘贴,然后按 [回车] 键执行。

正如之前所说,别忘了选中游戏窗口!

怎么样?是不是感觉js离自己近了不少?

输入过的脚本可以用 [↑] 键调出来,而且js自带的标识符以及《RPG Maker MZ》中定义的标识符都会有自动补全。用 [↑] [↓] 键选择,按 [Tab] 键确定。也可以用鼠标来选。

<Nice!> 超级方便!!

感觉你已经可以自己批量生产脚本了呢!

……虽然可能还到不了那个程度吧(笑),但我觉得只是改造一下的话,应该会变得相当轻松。

开发者工具里还准备了各种用于处理错误的功能……但如果要说明这些,就不是这篇文章的量能搞定的了,所以请自己去搜索讲解这些功能的网站吧!

老实说,我自己也没有完全掌握这些功能!!

另外,在rmmz中,开发者工具不能正常工作,所以这里写的步骤可能无法执行。但这一页毕竟只是rmmz的解说,敬请谅解。

最后

说实话,从“事件指令”到“脚本(JavaScript)”之间的这个过渡部分,对于从 RPG Maker 入门的人来说,几乎完全没有人引导,感觉就像一道相当陡峭的悬崖绝壁。

它看起来好像近在咫尺,但实际上甚至会让人忍不住想:是不是先好好研究一下插件反而更是一条捷径呢?

话虽如此,既然它好不容易就在眼前,那还是想直接爬上去看看。

这篇文章虽然还谈不上装了个电梯……但至少楼梯……可能也还算不上,大概也就是在悬崖上敲了个岩钉的程度吧?没敲上?结果拴上绳子一拉,岩钉就掉了?

嘛……有时候也可能会这样吧。

当你习惯了脚本的复制粘贴后,请继续阅读RMMZ的脚本应用