Project1

标题: RPGMAKERMZ从零制作一个新手向插件 [打印本页]

作者: Zackyooo    时间: 2022-5-17 23:59
标题: RPGMAKERMZ从零制作一个新手向插件
本帖最后由 Zackyooo 于 2022-5-18 00:10 编辑

相信对于每一个RPG游戏制作爱好者来说,插件在其中的地位是非常非常重要的。但是自己开发插件起来却是困难重重,尤其是对于新手而言,想自己写插件但又不知道从哪入手,只能像一只无头苍蝇一样乱撞。
本人我也只是个刚接触MZ两天的新手,通过自己的努力写了一个插件(虽然用处好像不大,其实就是自带的显示文字功能),但我想把制作插件的整个过程记录下来,供那些新手们参考参考,适合有一定编程基础的人,给他们提供一个思路。同时也希望能有许多大佬也来指点指点。

首先,在我个人看来,插件其实是和事件脚本差不多的东西,插件更像是把事件脚本进行各种操作然后再整合,变成一个完整的可供执行的流程方法。这里附上一个官方开发组的事件脚本文档,我们以后会经常用到。

话不多说,我们直接进入正题。*因为楼主本人也是新手,所讲的都是自己的理解,如有不对,欢迎指正*

我们先做一个最简单的显示文字的事件。



相信这一步绝大多数的人多可以做到,那么接下来我们加大一点难度,假设我们不用自带的事件指令,而是使用脚本该怎么写呢,这里我们就需要查看上面发的事件脚本文档了,我们找到message-showtext这一栏。



因为我们写的是MZ的插件,所以只要看MZ这一栏。我们可以看到一共有六条指令。
JAVASCRIPT 代码复制
  1. $gameMessage.setFaceImage(faceName, faceIndex);
  2. $gameMessage.setBackground(bgType);
  3. $gameMessage.setPositionType(posType);
  4. $gameMessage.setSpeakerName(speakerName);
  5. $gameMessage.add(text);
  6. interpreter.setWaitMode('message');


这六条指令分别对应的是设置人物头像、设置背景、设置窗口位置,设置说话人姓名,设置说话的文本,以及设置等待模式。
每个参数在examples里也有详细的讲解。我们先直接拷贝过来模拟出之前的事件指令效果代码如下:
JAVASCRIPT 代码复制
  1. $gameMessage.setFaceImage('Actor1',0);
  2. $gameMessage.setBackground(0);
  3. $gameMessage.setPositionType(2);
  4. $gameMessage.add("hello world");
  5. $gameMessage.setSpeakerName("我是说话的人");
  6. this.setWaitMode('message');





现在可以看到,我们已经完美还原系统自带的显示文字事件了。现在来讲一下每个参数到底是什么。
$gameMessage.setFaceImage(faceName, faceIndex);          设置脸部图像。faceName其实就是我们用自带的事件时,双击脸图出现的那个,我们的例子里用的是Actor1,faceIndex则是索引,0表示第一个
$gameMessage.setBackground(bgType);                          设置背景 0窗口 1暗淡 2透明
$gameMessage.setPositionType(posType);                          设置位置 0上 1中 2下
$gameMessage.setSpeakerName(speakerName);                  设置说话人的姓名,只要把speakerName改成相应的名字就可以了
$gameMessage.add(text);                                                设置说话内容,不在赘述
this.setWaitMode('message');                                        固定格式,正常情况下NPC跟角色对话时脸会朝着对话角色直到文字窗口消失,如果不加这段代码的话,NPC朝向角色之后会立马恢复成默认朝向。

这里附赠一个原文档的解释,给英语能力不错的人看看


好,到这里我们脚本指令也完成了,那么下一步就要开始重中之重,着手插件的编写了。想想还有点小激动呢

编写插件的第一步,我的建议是借鉴,这里我们就直接拿官方自带的TextPicture.js来参考,该文件目录位于你的工程位置jsplugins下,我们打开文本编辑器开始学习吧。
经过我们的观察发现,似乎每个插件的格式都是
JAVASCRIPT 代码复制
  1. (() => {
  2. PluginManager.registerCommand(pluginName, "set", args => {
  3.         内容
  4.     });
  5.  
  6. function xxxx(){
  7. 内容
  8. }
  9. })();


其实中间还省略了一段代码,不过那些代码的作用似乎是对原有方法的重写,效果是改变原有指令的逻辑,这里我们是新手向的所以先不做考虑。
那么第一个问题来了PluginManager.registerCommand是干什么的呢,通过查阅文档我们可以找到相关的解释


PluginManager.registerCommand(pluginName, commandName, function);这个方法是用来声明指令的,也就是说,如果你写了一个插件,想让别人来调用插件的指令就必须填写这个方法,具体表现形式如下图



三个参数文档上也有说明。
pluginName即插件名称,比如你创建的插件名称是showmessage.js,那么pluginName的值就是showmessage。
commandName则是指令名称,你可以自定义,今后调用的时候用的就是这个名称。
function则是具体执行的方法,也是我们接下来的重头戏。

因为我们上面已经写过脚本了,所以直接进行一个copy。方法的名字随便自定义一下,代码如下
JAVASCRIPT 代码复制
  1. (() => {
  2.          PluginManager.registerCommand('showmessage', 'showtext', args => {
  3.         aaa();
  4.     });
  5.  
  6.         function aaa(){
  7.  
  8.                 $gameMessage.setFaceImage('Actor1',0);
  9.                 $gameMessage.setBackground(0);
  10.                 $gameMessage.setPositionType(2);
  11.                 $gameMessage.add("hello world");
  12.                 $gameMessage.setSpeakerName("我是说话的人");
  13.                 this.setWaitMode('message');
  14. }
  15. })();


好,那么我们直接进入游戏,载入插件再使用,看看效果如何。
哎呀,想不到一上来就出问题了,我们在调用插件指令的时候发现根本就没有我们事先编写好的指令,这是怎么回事呢。
经过研究后发现,其实每个插件最上面的注释也十分的重要。想要调用指令 必须用到@command注释。注释这部分可以去之前发的文档上看,这里不再赘述。
具体格式如下
@command 调用的指令名 必须与PluginManager.registerCommand(pluginName, commandName, function)方法中的commandName同名
@text 对指令名的文本说明
现在我们重新优化一下,源代码如下
JAVASCRIPT 代码复制
  1. /*:
  2.  * @plugindesc 测试
  3.  * @author: Zackyooo
  4.  *
  5.  * @command show
  6.  * @text    显示文字框
  7.  */
  8.  
  9. (() => {
  10.          PluginManager.registerCommand('showmessage', 'show', args => {
  11.         aaa();
  12.     });
  13.  
  14.         function aaa(){
  15.  
  16.                 $gameMessage.setFaceImage('Actor1',0);
  17.                 $gameMessage.setBackground(0);
  18.                 $gameMessage.setPositionType(2);
  19.                 $gameMessage.add("hello world");
  20.                 $gameMessage.setSpeakerName("我是说话的人");
  21.                 this.setWaitMode('message');
  22. }
  23. })();


让我们再运行一次,看看结果如何。



很不幸,又报错了,看来路途坎坷啊。根据报错的说明 似乎是最后一条代码this.setWaitMode('message');出了问题。
经过我的研究,问题是出在this上面。(以下是我个人理解,不保证正确,欢迎指正),之前我们是在脚本内直接运行的,当时的this应该是指代了当前的interpreter,所以我们可以调用setWaitMode()。而当我们写在插件里面之后,我们是找不到这个interpreter的,所以需要我们通过调用方法来找到这个interpreter,具体调用哪个方法也是通过文档来查找,最后我们找到一个 $gameMap._interpreter。

所以我们再将源代码进行修改。然后进行测试。

JAVASCRIPT 代码复制
  1. /*:
  2.  * @plugindesc 测试
  3.  * @author: Zackyooo
  4.  *
  5.  * @command show
  6.  * @text    显示文字框
  7. */
  8.  
  9. (() => {
  10.          PluginManager.registerCommand('showmessage', 'show', args => {
  11.         aaa();
  12.     });
  13.  
  14.         function aaa(){
  15.                 $gameMessage.setFaceImage('Actor1',0);
  16.                 $gameMessage.setBackground(0);
  17.                 $gameMessage.setPositionType(2);
  18.                 $gameMessage.add("hello world");
  19.                 $gameMessage.setSpeakerName("我是说话的人");
  20.                 $gameMap._interpreter.setWaitMode('message');
  21. }
  22. })();




终于,我们的努力没有白费,我们成功用插件的方式实现了mz自带的显示文字功能(笑)。

相信跟我一起动手做到这里的小白肯定和我一样兴奋,再想想能不能有什么改进的地方,让这个插件变得更强大呢。我们目前是把说的话写死的,固定是hello world.有没有办法让使用者自定义呢,我们现在围绕这个想法继续展开,对插件代码进行改进。
我们可以发现在插件的注释中,有这样一种注释@arg 根据文档上的说明,它似乎就是用来定义参数来使用的。然后可以和registerCommand()中的args=>{}进行配合。由于时间关系,我这里直接贴一张图来进行说明。



每一个你用@arg定义的参数 都能用args.来使用,现在我们就照着这个方法来写一个用户可以自定义文本内容的脚本吧。

源代码如下
JAVASCRIPT 代码复制
  1. /*:
  2.  * @plugindesc 测试
  3.  * @author: Zackyooo
  4.  *
  5.  * @command show
  6.  * @text    显示文字框
  7.  *
  8.  * @arg text
  9.  * @type String
  10.  * @default 显示要说的话
  11.  * @text 参数
  12.  * @desc 在这里设置要说的话
  13.  */
  14.  
  15. (() => {
  16.          PluginManager.registerCommand('showmessage', 'show', args => {
  17.         aaa(args.text);
  18.     });
  19.  
  20.         function aaa(mes){
  21.  
  22.                 $gameMessage.setFaceImage('Actor1',0);
  23.                 $gameMessage.setBackground(0);
  24.                 $gameMessage.setPositionType(2);
  25.                 $gameMessage.add(mes);
  26.                 $gameMessage.setSpeakerName("我是说话的人");
  27.                 $gameMap._interpreter.setWaitMode('message');
  28. }
  29. })();


然后我们进行测试,可以看到,在插件指令里,我们已经可以自定义参数内容了




到此,我们整个插件的制作过程就全部结束了。怎么样,是不是很有成就感。虽然我们现在做的这个插件MZ里本身就自带。但是我们完全可以按照上面的思路无限拓展下去,让许多不可能变成可能。我们要想的应该是这东西还能做什么,而不是这东西只能做什么。
最后,祝每一位有着游戏开发梦想的制作者都能有所成就!
作者: wxh811211    时间: 2022-9-7 15:07
支持支持!
官方开发组的事件脚本文档呢?
作者: darkmoon2022    时间: 2022-9-9 17:40
挺好的 引导式
作者: 悟行    时间: 2022-12-2 06:11
本帖最后由 悟行 于 2022-12-2 06:14 编辑

楼主,请问下“官方开发组的事件脚本文档”可以重新附件上传吗?找不到,但新人感兴趣也想下载下来学习下,谢谢~

找到了,附个外网的链接:https://docs.google.com/spreadsheets/d/1-Oa0cRGpjC8L5JO8vdMwOaYMKO75dtfKDOetnvh7OHs/edit#gid=1186334695




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