RPGMakerMV的插件学习
来源:互联网 发布:plc仿真软件 编辑:程序博客网 时间:2024/06/07 15:06
本着独立游戏开发者的心态,入了正版RM来想自己做游戏,而且这版的语言也正好是js
就着这个机会一边研究插件一边深入学习js
有能力的同学可以试着去看看Youtube上面Soulpour777的几个视频
对于想学js和想做插件的同学都有挺大的收获
这里就把我对做这插件的学习记录放进来,可能有些乱
首先经过视频和其他大神的插件,了解到这么一个问题,就是很多时候要实现自己的插件,基本上都是去重写官方的原型链中的方法(我不太清楚这样称呼是否明确,请大神给指出错误)
就是你随便打开一个官方的js文件,就会看到里面诸如 xxx.prototype.yyy 这样的东西
这个时候在自己新建的插件里面把这整个方法复制下来, 并且在RPGMaker的插件管理加上自己的插件,启动的时候就会执行重写的那个方法
做个简单的事例(同学们请自己动手喔),我们来实现一个在启动游戏的时候(就是显示新游戏NewGame,继续Continue和选项Options那个页面),加入一个新的选择项目 测试项
下面开始操作:
1,首先在游戏项目下的js/plugins文件夹里创建一个自己的插件文件(我这里命名的是testPlugin.js) ,
2,然后得找到启动游戏这个东西是在哪儿画出来的,rpg_window.js 这个文件就是控制来画出所有想要的窗口的官方文件,在文件的5747这行里,有个
Window_TitleCommand.prototype.makeCommandList 方法 这个方法里面就是画出初始化游戏的窗口,把这个方法整个复制到自己的js文件里
从这里就能看到,官方是把这里的3个选项依次加进去,addCommand这个方法有4个参数传进去
Window_Command.prototype.addCommand = function(name, symbol, enabled, ext)
第一个参数 类型(string) 代表的是显示的名称
第二个参数 类型(string)代表的是标示(在事件处理的时候会通过标示来确定执行什么事件)
第三个参数 类型(boolean)代表这个选项是否可用,这里的继续游戏continue按钮是灰色,因为他判断了是否游戏里面有存档this.isContinueEnabled(),如果有存档就返回的true,否则false,默认是true
第四个参数 类型(任意)是拓展 用于其他特殊的标示,类似于第二个参数
3,现在我们把一个测试项放进启动游戏的选项里面,只需要在我们的js文件里面,跟着方法后面写上this.addCommand('测试项','testOption');, ,这样
4,将插件加入进来,运行游戏
当当当!就出现了!可是你点击是没有任何效果的,因为这里还没给设置绑定的事件,下次我会继续讲解如何绑定事件.
有几天没来更新了,在做其它的事儿
这会有空了,马上来把我的tip插件来完成了
上次完成一个测试版的之后,发现了一个很大问题,第一,显示出的tip框是直接就出现了,第二,关闭tip的时候没法回车去关闭,而且还强制改写了Scene_Map的update来实现的关闭,相当难看,第三,打开tip的事件角色只转身一下就又转回去了。
说白了,是相当的失败,于是又花了两天时间仔细研究了一下Window_Message的实现,有一些小的收获,这里先大致讲解一下实现的思路
首先我目标中的tip,是在Scene_Map中弹出来,跟对话的消息是一样的,如果新建一个Scene来显示的话,后面是的画面是不会动的,所以这里照着跟Window_Message一样,仅新建一个Window来在Scene_Map中显示
这里提下关于打开tip(Message也是一样)的关键所在,update,刷新帧,Window_Base自带有的一个方法,所以每个继承至Window_Base的都会有这个方法,当创建Scene之后,然后往Scene里添加Window,这些Window都会一直调用这个方法,通过这个方法来检测某些变量或者函数返回值来做出动作
拿Window_Message来举例(Window_Message里面包涵了除了显示消息以外的好几个东西,这里就简单拿显示消息来做例子),Window_Message的update实现是在非打开中和非关闭中的时候,去判断是否要显示消息框,其中当消息(就是我们调用的时候传入的那些字符信息)存在的时候打开了消息框,同时字符会在里面打印的同时并把它们都消费掉,当字符未被消费完,同时达到窗口容纳字符的最大值的时候,先暂停,然后当触发按键的时候打开下一页。看到那几个简单的字眼估计就明白了,比如newLine啊newPage啊什么的。
我们做的这个tip没这么复杂,至少我不想去每个字符慢悠悠的打出来,所以消费字符这一步我这里直接是全部拿出去了
然后再提出几个关键点
第一,就是当打开消息框的时候,按esc,不会打开菜单,而是关闭掉消息框,同样我们的tip也需要这一个操作,但是这个动作我之前是用了一个比较笨的方法,就是菜单监听esc的事件里先判断是否打开tip,如果是,则先关闭tip,其实官方的方式是,设置菜单的可用性,于是这次我也沿用官方的做法,打开tip的时候,先设置菜单不可用,然后后面的esc就不会触发打开菜单
第二,打开的tip怎么出现的,之前也是用的错误的办法,直接设置tip窗口的visible,效果嘛,就一闪,直接打开了```感觉很突兀,而标题页和消息框的那些菜单都是展开的形式打开的,方法我也想过,无非刷新帧的时候去做个动画而已嘛,实际不用这么麻烦,直接调用本体的open函数就行了,他会每一帧增加一个opacity的值,每次增加32,8次就能达到大于255的极值了,在这个加值的过程,window的isOpening属性会是true,所以就不用担心他在原本的update函数里面捣乱(update函数里面实现的时候是要去判断非打开中和非关闭中的状态),用样close也是类似的动作,所以这一动作就作出了让我们看到的展开的形式(ps:其实这里我还是有点疑问,就是opacity该叫做透明度的,怎么动画效果会是展开呢。。。),这里注意一点,初始化tip窗口的时候,记得把this.openness = 0;,这是open函数操作的关键之一。
第三,事件触发的目标是人物的话,他不会朝向主角,这里是由于有一个等待模式的介入,大家在rpg_object里面找到command101看函数最后就明白了,他设置了一个消息的等待模式,除了消息,其它好几个需要等待的,都是这样处理的,当等待模式启动之后,触发事件的目标就会朝向主角,并且如果带动作效果的,他的动作也不会停,因为等待模式也是一种update刷新着呢
上代码
关于插件的调用和设置就不多说了,下面看成果图
看到你的回复之后,搞了我好几个小时,毕竟是第一个向我提问的人啊,我这不就全力以赴的帮你研究这个了么,总算弄出来了
过程中也发现了rpgmaker的一些弊端,连续使用SceneManager.push是会出问题的```,请大家记住这个问题,如果连续执行push的话,他有可能没刷新过来,导致前面压入栈堆的scene全部都是第一次的那个scene。
所以本来想好的思路完全不行,这里首先用我自己的语言介绍一下rpgmaker内部的一些概念,首先rpg_scene.js和rpg_window.js这两个脚本,我之前一直都是傻傻分不清楚,现在搞了自己的提示窗口(优化之后就放上来跟大家分享一下)和这个使用道具弹出消息,已经明白了7,80%了。
scene是用作每个操作的单屏,SceneManager.goto是代表直接跳转到这个屏,不压入栈堆,SceneManager.push是代表将本屏压入栈堆,(栈堆这里大家可以简单理解为保存我们用过的屏的存储地方)
举个栗子,游戏主页面(Scene_Map)中,按esc按钮进入菜单页(Scene_Menu),再选择道具页(Scene_Item),他这一个流程全部都是用的push,压入到栈堆里面的,当我们在道具页(Scene_Item)取消的时候,再调用SceneManager.pop来剔除当前屏,回到栈堆中的上一屏。
然后我还发现,当Scene_Map每次启动的时候,他都会清空栈堆,这也算是防止栈堆过大的一种策略
所以这次要完成这样的效果,同时考虑到连续push会出问题这一因素,我们得用一个标示来禁止Scene_Map启动的时候清空栈堆。
然后在文本消息结束的时候,调用pop回到前面的页面
大致流程如下
游戏主页面(Scene_Map) —— 菜单页(Scene_Menu)—— 道具页(Scene_Item)—— 使用道具弹出消息(Scene_Map)并弹出消息
由于我们设置了标示防止回到Scene_Map的时候清空栈堆,所以以上的流程会在栈堆里,当我们调用SceneManager.pop之后,就会回到道具页(Scene_Item)
这里有个问题就是,如果我们选择道具页的贵重品栏中的道具,回来之后他会清空之前选择的栏位,回到第一栏,所以这里我的办法是再设置一个变量来保存前一次操作所选择的栏位,然后回到这个页面的时候,直接点亮那个栏位,并且把我们之前用来控制回到Scene_Map不清空栈堆的标示改为失效
接下来上代码
接下来得创建道具
这里稍微提一下,这里的scope选none,意思就是随便用,如果scope是1 ally及后面的话,会弹出submenu来选择使用对象,所以我这里就直接选的none
最后插件管理里面加起来,跑起来
这次来了解一下 精灵(Sprite)元素
对于做游戏的大神都知道精灵(Sprite)对于游戏的重要性(ps:我不是大神,我是初心者。。。)
这里我仅用自己的思路大致来描述一下,有偏差的地方请同学们指正一下。
拿这个rpgmaker来说,里面大大小小的东西都可以算作是精灵,首页显示的背景算是,地图的每个单元算是,更不用说我们操作的角色了,你游戏中几乎所有看到的东西动起来,仅仅是精灵单元改变自己的图片而已,由于游戏的fps(帧)刷新得比较快,所以我们看到的就是一个连贯动作的精灵(就像我小时候在课本每页的右下角画小人,然后每一页画一个动作,然后把书翻起来的话,就会看到一个连贯的动作,就是这个意思)。
在rpgmaker中大多数对象都具有update的方法,这就像是我们在翻书的动作,然后里面的图片素材就是我们画的小人。
所以这次我们来做个自己想要的标题页,可以动起来的,主要操作的东西,就是精灵(Sprite)。
在rpg_scene.js的233行找到创建标题页的代码
其中createBackground方法就给了我们很好的示例,他在里面创建了2个精灵(说白了你甚至可以把精灵直接理解为一个图片都行- -),
这里就是我们在System里面选择的图片
$dataSystem.title1Name 背景图片名称 左一列表所选择的
$dataSystem.title2Name 前景图片名称 左二列表所选择的
然后通过ImageManager中的loadTitle1方法,传入名称去获取到图片
稍微描述一下这个ImageManager,他里面的每个loadxxxx的方法都直接对应到的是项目文件下img文件里的每个文件夹
而且他每个load方法的实现也是很容易看懂的
创建了精灵之后,还需要把这个精灵加入到我们的屏幕(Scene)中去
就像这句的写法就行了, this.addChild(this._backSprite1);
具体精灵有哪些参数和方法,大家可以去官方文档查看,这里不做介绍了
现在开始做我们的标题页,这里为想做一个背景在移动,中间再放个人物,然后人物背后一遍遍的扩散自己本身,效果如下
首先我们把背景换成 SeaofClouds 这个图片,这里不是要你直接在System里面去改,因为那样的话图片是不会动的,而我们需要一个水平移动的背景
老样子,复制源码过来改改改
然后实现我们自己创建背景的方法
这里的效果跟官方设置背景的效果是一模一样的,如果仅是这样做的话,就等于用我们的方式再画了一个精灵贴上去而已,也就是然并卵,我们要让这个背景水平动起来
这里是让标题页的每一帧刷新的时候,让我们的背景精灵 x 坐标 +1 ,先运行看看效果吧
是不是看到问题出来了,这我们的背景精灵向左移动的同时,把他覆盖的下面的官方设置的背景元素露出来了。也许你有些编程的思路的话,你会考虑放两张图片上去,两张图片水平放置,一张图片移动的时候另一张也跟着移动出来吧啦吧啦吧啦吧啦...... 太麻烦了,rpgmaker提供了另一种精灵对象就能轻松完成这个任务,就是平铺精灵(TilingSprite)。我们先把创建的普通精灵改成平铺精灵
接下来让他动起来,但是平铺精灵跟普通精灵不同,要让他水平动的话,是要改变它的origin.x(而非普通精灵的 x) ,所以继续修改我们的update方法
如此,就能看到效果,背景平铺的动起来了,滚动的快慢与我们设置每一帧执行update移动的大小有关
比如你这样设置 this._myBackSprite.origin.x += 100 ;
这样屏幕动得飞快(当然你还可以更快 -- ),这里希望大家把脑洞打开,知道超级机器人大战吧?里面的必杀场景是不是特流弊的场景飞快滚动?是的,我们如果去写个插件,当使用某个必杀的时候,这样把战斗背景一弄,就能做出流弊的必杀场景了。
继续来完成这次的目标,放个人物立绘上去,我这里选择的是dlc Cover Art Characters 里面的Package2_3这个人物,把他放在了我们项目文件的picture文件里。同样,我们在创建我们标题页的方法里面新增一个普通精灵放上去。
这样背景屏幕水平滚动的时候,中间还会有一个人物立绘在屏幕正中间,并且底部与屏幕底部贴合。
接下来做个看上去奇怪的效果,让人物立绘背后有个一模一样的人物扩散开来,一直循环,同样继续修改create_myTitleSprite方法
到此,实际的效果只是立绘精灵和幻影精灵重叠了而已,没有任何动作,我们修改update方法来让幻影精灵动起来,实现思路是,我让幻影精灵的透明度(Opacity)慢慢的减弱,并且让幻影精灵的缩放(Scale)慢慢的变大,就能表现出一种向外拓展的效果了,同时幻影精灵完全变成透明的时候,我们要重置他的缩放(Scale)和透明度(Opacity)。
最后把插件加入到游戏里面去
到此,我们这次的目的就能完成了,最后的效果就是这样(脑补一下,动起来的喔)
只要大家脑洞大开,这样继续拓展,我觉得做些啥流弊效果都没问题的吧
睡之前来一发今天的研究成果,做一个改变文字颜色的小插件
首先来说下设计流程,对于官方的源码来看,文字显示出来的样子其实是一个字符一个字符处理出来的,处理过程中他做了一个转译和判断
这里主要说一些要改变文字颜色的关键部分,其余的请同学们自己多研究研究
在处理Text文本的时候,官方会通过这个方法把里面每个字符一个个的遍历出来(rpg_windows.js,307行)
其中 \x1b 这个东西的转译就是 ‘ \ ’ 反斜杠 ,这里官方把出现反斜杠后面的东西拿出来专门做处理,就是这个方法
this.processEscapeCharacter(this.obtainEscapeCode(textState), textState);
然后在rpg_windows.js,364行里,就是对后面带有以下字符的包含的文字特殊处理 , 其中包括C , I , { , }
你在新建一个文本消息,鼠标移到文本中不动的话,他会有提示怎样怎样会改变文字颜色啊,大小啊等,比如 ‘\{’ ‘ \}’ ‘\C’等,
I表示指定一个图标 用法: \I[图标id]
如图 左下角的1表示图标的id 就是那个骷髅的图标
\{ 表示后面的字符大小加大 比如要把 ‘你好吗?’ 中间的好加大 就在显示文本中这样写 ‘你\{好\}吗?’
\} 表示后面的字符大小减小 比如要把 ‘你好吗?’ 中间的好减小 就在显示文本中这样写 ‘你\}好\{吗?’
C表示改变后面文本的颜色 用法: \C[数字] 要变色的文字 \C
最后的\C 表示后面的文字不变色
那么既然有现成的文字变色,为啥还要自己写插件呢?原因有二
一,我看不懂他颜色值的算法- -(求大神教教)
二,我想随心所欲的用任意颜色,比方我随便用取色器取个颜色就放上去了
好,这就开工
知道了他是如何处理,我们就知道如何去改我们想要的东西了
就在他原本处理颜色这上面做手脚
case 'C':
this.changeTextColor(this.textColor(this.obtainEscapeParam(textState)));
break;
1,首先大家以往看到添加插件的时候,插件的参数啊,作者啊,描述啊,其实就是给加上注释就行了,咱们新建一个插件,叫myTextColor.js,然后把注释写上,使用的时候就能在界面上看到我们流弊的插件信息了
一一对照到注释来看添加插件界面就不难理解注释的意义了吧
2,根据之前的讲解,我们首先要注册我们的插件,同时还得把参数传进来的值用变量保存起来
这里的var colorNames = String(parameters['colorNames'] || 'white,red,green,blue'); 稍微解释一下 String后面带的参数意义是,如果在界面操作的时候,你不填colorNames的value是多少,我这里就默认给出这个值,colorValue雷同.
3,把传进来的值用个对象以健值对的形势保存起来,以便后面使用
这里的_colorObjs最后的样子就是
{
'white' : '#ffffff' ,
'red' : '#ff545d' ,
'green' : '#7aff3c' ,
'blue' : '#6da9ff'
}
4,为了显得我们插件流弊一点,得学学人家可以用命令动态添加颜色吧,再贴心一点,咱们把用法也给人说一下,免得别人用我们的插件一打开就萌比了
注释中的 myTextColor addColor orange #ff8153 就代表在pluginCommand里面这样用就能添加一个颜色
或者用js的方法调用的话Game_Interpreter.prototype.pluginCommand('myTextColor',['addColor','orange','#ff8153']);
5,最重要的地方,咱得改写以前的处理方式,在以前 \C 那里别人官方不是 \C[数字] 这样用么?咱给他整个流弊的 \C[颜色名称] 这样来用,其中这个颜色名称会从我们之前保存好的_colorObjs里面找到对应的颜色值,比如 \C['red'] ,这样就把后面的字的颜色改为了 '#ff545d'。
在rpg_windows.js中的354行,官方是这样取出他 \C[数字]中的数字的
咱们就如法炮制 ,给整个这个,差别就是官方的取的是个数字,咱取的是个字符串
6,所有准备工作都做好了,直接上菜吧,还是我的老习惯,给官方的改改改
大功告成,不过整个插件的验证不太可靠,就是说要是乱给写参数进来的话,报错啥的就不好说了,比如你把颜色值写个djsahdjsa什么的````
先贴个全部代码图
再来个使用示例图,这里咱把官方的那几个字体变大小啊,图标啊一并用上来玩
效果图
最后强调一下,为啥要在最后那句话前面写上 \C ,因为前面的 \C[颜色名] 会修改后面的所有文字 ,所以这里带上一个 \C 意思就是把颜色还原成默认的。
接下来简单说明一下事件这块的东西
在我们给菜单栏添加了一个选项之后,看是能看到了,但是点击之后是没有任何效果的,那是因为没有有效的事件绑定到选项的点击,所以是没有反应的
我认为点击之后弹出个消息啥的太没新意了,所以咱们这次做个在启动游戏的初始界面加入一个图鉴的选项(就是官方自带的那个ItemBook图鉴插件),点击图鉴就打开图鉴,想要做这样的东西
是因为之前测试ItemBook这个插件的时候,让我没处调用,给道具加入事件或者在地图上加入一个事件是可以由触发这个事件调用pluginCommand来打开 ,如
设置图右下这个pluginCommand 来开启,但是我想把这个打开加入到选项里啊亲,这种收集的东西放到道具里或者某个地点来触发总觉得不爽啊亲```
言归正传
1,首先还是之前的一样,把图鉴这个选项加进去 ,跟之前的差别就是把第一个参数(显示的名称)和第二个参数(标示)改了一下
2,找到绑定事件的地方,在rpg_scenes.js文件中的310行左右, ,这里就是绑定初始化窗口的事件的地方,把这个函数全部复制到我们的js文件里,然后再给
绑定一个我们自己的事件,
this._commandWindow.setHandler('ItemBook', this.commandOpenItemBook.bind(this));
这句话就是把这个事件绑定到图鉴这个选项上,他就是通过我们之前设置标示(ItemBook)来找到事件该绑定到哪儿的,所以这个第一个参数 一定要跟前面添加的时候设置的标示一致
第二个参数设置是一个事件的监听(我也是凭感觉这样叫,有大神请指教。。。),commandOpenItemBook这个函数是没有的,是我们自己定义的一个函数,所以在下面要写一个这个函数
,(ps:你可以简单的把this就理解成Scene_Title.prototype,这就是这个对象的原型,具体js所谓的原型链是啥,我也解释不太清楚,为了不误导大家,请去
问下度娘)
到这里选项也加上了,事件也绑定,然后就差我们点击图鉴做的事了
3,在我们写的commandOpenItemBook函数中做跟设置事件那个pluginCommand一样的事儿
于是在rpg_objects.js文件的最后找到了Game_Interpreter.prototype.pluginCommand(command,args);这个方法,你仔细往看这一块的官方注释你会发现,编辑界面中所有的事件编辑都是这
里写的 ,看函数名上面的注释就知道了
这里稍微解释一下用js调用这个方法和在界面上调用这个方法有啥区别
3.1在界面上 ,第一个‘ ItemBook’这是调用注册的插件名称(我是这么理解),就像ItemBook.js源码里 ,当你把插件放进
来,并且设置on,启动游戏的时候,他就会把这个插件注册进来(当我们自己写的插件需要带命令来操作的时候,就得先把我们的插件注册进来,由于之前写的东西不大需要带命令操作,所以我
们就没有注册,而是直接开写),第二个‘open’代表命令的参数,大致的规则是 命令[空格]参数1[空格]...参数n
3.2在js里面调用命令 Game_Interpreter.prototype.pluginCommand('ItemBook',['open']); 跟界面上操作也是差不多的,第一个参数是注册的插件名称,第二个参数得注意一下,他是一个数组
大致规则是 Game_Interpreter.prototype.pluginCommand('命令',['参数1'.....'参数n']); , 所以在这里我们的操作其实跟界面上设置pluginCommand的操作是一样的
4,准备就绪,记得把ItemBook插件加入进来 ,然后运行查看效果
最后完成的代码是这个样纸, ,
但是经过之前大神的点拨,太老实重写原本方法的话,说不定会跟其他的插件冲突,于是把代码优化一下, ,为了方便大家看清是改动了哪里,我把多余的代码
只是注释掉了,然后新增了两个对象_myWindow_TitleCommand 和 _myScene_Title ,把原方法保存下来,执行的时候先让他们调用一下原方法执行原本执行的东西,然后在后面执行我们拓
展的东西。
- RPGMakerMV的插件学习
- 基于RPGMakerMV的JavaScript基础-1
- 基于RPGMakerMV的JavaScript基础-2
- 基于RPGMakerMV的JavaScript基础-3
- 基于RPGMakerMV的JavaScript基础-4
- 基于RPGMakerMV的JavaScript基础-5
- 基于RPGMakerMV的JavaScript基础-6
- RpgMakerMV源码解析(1)-输入管理
- Qt插件机制的学习
- Qt插件机制的学习
- Qt插件机制的学习
- jquery插件的应用学习
- Chrome插件的学习入门
- unity3d iTween插件的学习
- ckeditor插件的基础学习
- 手势插件Easytouch的学习
- K3 CLOUD 插件的学习
- lombok插件的使用学习
- shell基本语法
- Cordic算法的原理
- cassandra节点异常:java.lang.OutOfMemoryError: Direct buffer memory
- 51nod 1804 小C的多边形(贪心)
- 词向量源码解析:(4.5)hyperwords源码解析之representations
- RPGMakerMV的插件学习
- STM32再学习——启动流程分析
- 设计模式之单例模式
- Spring boot系列:配置文件(二)
- Maven 之 加载本地的jar包
- 控制循环结构(break、continue)、return结束方法
- leetcode 133. Clone Graph
- 配置处理结果
- 评职称自费出书多少钱