设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 12706|回复: 19
打印 上一主题 下一主题

[原创发布] RPGMakerMV的插件学习

[复制链接]

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2016-3-30
帖子
13
跳转到指定楼层
1
发表于 2016-3-31 17:05:00 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本人程序员,写过几年js,但是真正用到的东西根本算是皮毛中的皮毛。

本着独立游戏开发者的心态,入了正版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,将插件加入进来,运行游戏

当当当!就出现了!可是你点击是没有任何效果的,因为这里还没给设置绑定的事件,下次我会继续讲解如何绑定事件.

点评

很棒的教程!不过最好不要直接修改原方法,这样做容易和其他插件不兼容,建议后面的教程都先重定义方法,再修改新定义的方法,以免杯具  发表于 2016-3-31 17:19

评分

参与人数 7星屑 +221 梦石 +2 收起 理由
xjzsq + 30 精品文章,值得精读!加油!
柳岳枫 + 60
CFRoo + 20 精品文章
冷峻逸 + 46 补个111
gonglinyuan + 45 精品文章
dongdongdjh + 20 插眼,养肥了再看。
余烬之中 + 2 加油

查看全部评分

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2016-3-30
帖子
13
2
 楼主| 发表于 2016-3-31 19:10:14 | 只看该作者
感谢感谢,这下我好像有点明白了为啥更多时候写插件会是call一下原来的函数(ΦωΦ)
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2016-3-30
帖子
13
3
 楼主| 发表于 2016-3-31 19:17:35 | 只看该作者
怎么设置成帖子过期啦?要怎么弄回原创呢- -
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2016-3-30
帖子
13
4
 楼主| 发表于 2016-3-31 20:13:33 | 只看该作者
感谢版主大神给弄回了原创!好流弊!666666
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2016-3-30
帖子
13
5
 楼主| 发表于 2016-3-31 21:11:31 | 只看该作者
本帖最后由 bulangnisi 于 2016-3-31 21:21 编辑

接下来简单说明一下事件这块的东西

在我们给菜单栏添加了一个选项之后,看是能看到了,但是点击之后是没有任何效果的,那是因为没有有效的事件绑定到选项的点击,所以是没有反应的

我认为点击之后弹出个消息啥的太没新意了,所以咱们这次做个在启动游戏的初始界面加入一个图鉴的选项(就是官方自带的那个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 ,把原方法保存下来,执行的时候先让他们调用一下原方法执行原本执行的东西,然后在后面执行我们拓

展的东西。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2016-3-30
帖子
13
6
 楼主| 发表于 2016-3-31 23:17:14 | 只看该作者
睡之前来一发今天的研究成果,做一个改变文字颜色的小插件

首先来说下设计流程,对于官方的源码来看,文字显示出来的样子其实是一个字符一个字符处理出来的,处理过程中他做了一个转译和判断

这里主要说一些要改变文字颜色的关键部分,其余的请同学们自己多研究研究

在处理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 意思就是把颜色还原成默认的。



回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2016-3-30
帖子
13
7
 楼主| 发表于 2016-4-3 16:48:33 | 只看该作者
本帖最后由 bulangnisi 于 2016-4-3 16:51 编辑

这次来了解一下 精灵(Sprite)元素

对于做游戏的大神都知道精灵(Sprite)对于游戏的重要性(ps:我不是大神,我是初心者。。。)

这里我仅用自己的思路大致来描述一下,有偏差的地方请同学们指正一下。

拿这个rpgmaker来说,里面大大小小的东西都可以算作是精灵,首页显示的背景算是,地图的每个单元算是,更不用说我们操作的角色了,你游戏中几乎所有看到的东西动起来,仅仅是精灵单元改变自己的图片而已,由于游戏的fps(帧)刷新得比较快,所以我们看到的就是一个连贯动作的精灵(就像我小时候在课本每页的右下角画小人,然后每一页画一个动作,然后把书翻起来的话,就会看到一个连贯的动作,就是这个意思)。

在rpgmaker中大多数对象都具有update的方法,这就像是我们在翻书的动作,然后里面的图片素材就是我们画的小人。

所以这次我们来做个自己想要的标题页,可以动起来的,主要操作的东西,就是精灵(Sprite)。

在rpg_scene.js的233行找到创建标题页的代码



其中createBackground方法就给了我们很好的示例,他在里面创建了2个精灵(说白了你甚至可以把精灵直接理解为一个图片都行- -),

JAVASCRIPT 代码复制
  1. Scene_Title.prototype.createBackground = function() {
  2.     this._backSprite1 = new Sprite(ImageManager.loadTitle1($dataSystem.title1Name));
  3.     this._backSprite2 = new Sprite(ImageManager.loadTitle2($dataSystem.title2Name));
  4.     this.addChild(this._backSprite1);
  5.     this.addChild(this._backSprite2);
  6. };


这里就是我们在System里面选择的图片



$dataSystem.title1Name 背景图片名称 左一列表所选择的
$dataSystem.title2Name 前景图片名称 左二列表所选择的

然后通过ImageManager中的loadTitle1方法,传入名称去获取到图片

稍微描述一下这个ImageManager,他里面的每个loadxxxx的方法都直接对应到的是项目文件下img文件里的每个文件夹



而且他每个load方法的实现也是很容易看懂的



创建了精灵之后,还需要把这个精灵加入到我们的屏幕(Scene)中去

就像这句的写法就行了, this.addChild(this._backSprite1);

具体精灵有哪些参数和方法,大家可以去官方文档查看,这里不做介绍了

现在开始做我们的标题页,这里为想做一个背景在移动,中间再放个人物,然后人物背后一遍遍的扩散自己本身,效果如下



首先我们把背景换成 SeaofClouds 这个图片,这里不是要你直接在System里面去改,因为那样的话图片是不会动的,而我们需要一个水平移动的背景

老样子,复制源码过来改改改

JAVASCRIPT 代码复制
  1. var _myScene_Title_create = Scene_Title.prototype.create;
  2.  
  3. Scene_Title.prototype.create = function() {
  4.  
  5.   _myScene_Title_create.call(this);//原本官方执行的方法不去动它的,他该怎么创建就怎么创建
  6.  
  7.   //创建我们自己的背景;
  8.   this.create_myTitleSprite();
  9. };


然后实现我们自己创建背景的方法

JAVASCRIPT 代码复制
  1. Scene_Title.prototype.create_myTitleSprite = function(){
  2.  
  3.   this._myBackSprite = new Sprite(ImageManager.loadParallax('SeaofClouds'));
  4.  
  5.   this.addChild(this._myBackSprite);
  6.  
  7. };


这里的效果跟官方设置背景的效果是一模一样的,如果仅是这样做的话,就等于用我们的方式再画了一个精灵贴上去而已,也就是然并卵,我们要让这个背景水平动起来

JAVASCRIPT 代码复制
  1. var _myScene_Title_update = Scene_Title.prototype.update;
  2.  
  3.   Scene_Title.prototype.update = function() {
  4.  
  5.     _myScene_Title_update.call(this);
  6.  
  7.     this._myBackSprite.x += 1 ;
  8.  
  9.   }


这里是让标题页的每一帧刷新的时候,让我们的背景精灵 x 坐标 +1 ,先运行看看效果吧

是不是看到问题出来了,这我们的背景精灵向左移动的同时,把他覆盖的下面的官方设置的背景元素露出来了。也许你有些编程的思路的话,你会考虑放两张图片上去,两张图片水平放置,一张图片移动的时候另一张也跟着移动出来吧啦吧啦吧啦吧啦...... 太麻烦了,rpgmaker提供了另一种精灵对象就能轻松完成这个任务,就是平铺精灵(TilingSprite)。我们先把创建的普通精灵改成平铺精灵

JAVASCRIPT 代码复制
  1. Scene_Title.prototype.create_myTitleSprite = function(){
  2.  
  3.   //this._myBackSprite = new Sprite(ImageManager.loadParallax('SeaofClouds'));//普通精灵
  4.  
  5.   this._myBackSprite = new TilingSprite(ImageManager.loadParallax('SeaofClouds'));//平铺精灵
  6.  
  7.   //平铺精灵需要设置他默认的位置,否则是看不到的
  8.   //通过平铺精灵的move函数设置他的位置
  9.   //参数1  TilingSprite(平铺精灵) 的 X 坐标
  10.   //参数2  TilingSprite(平铺精灵) 的 Y 坐标
  11.   //参数3  TilingSprite(平铺精灵) 的宽度
  12.   //参数4  TilingSprite(平铺精灵) 的高度
  13.   //这里的Graphics的width和height是游戏窗口显示的宽度和高度,我们这样设置就会让这个平铺精灵全部占满屏幕
  14.   this._myBackSprite.move(0,0,Graphics.width,Graphics.height);
  15.  
  16.   //将我们的精灵添加到标题页
  17.   this.addChild(this._myBackSprite);
  18.  
  19. };


接下来让他动起来,但是平铺精灵跟普通精灵不同,要让他水平动的话,是要改变它的origin.x(而非普通精灵的 x) ,所以继续修改我们的update方法

JAVASCRIPT 代码复制
  1. var _myScene_Title_update = Scene_Title.prototype.update;
  2.  
  3.   Scene_Title.prototype.update = function() {
  4.  
  5.     _myScene_Title_update.call(this);
  6.  
  7.     //this._myBackSprite.x += 1 ;
  8.  
  9.     this._myBackSprite.origin.x += 1 ;
  10.  
  11.   }


如此,就能看到效果,背景平铺的动起来了,滚动的快慢与我们设置每一帧执行update移动的大小有关

比如你这样设置  this._myBackSprite.origin.x += 100 ;  

这样屏幕动得飞快(当然你还可以更快 -- ),这里希望大家把脑洞打开,知道超级机器人大战吧?里面的必杀场景是不是特流弊的场景飞快滚动?是的,我们如果去写个插件,当使用某个必杀的时候,这样把战斗背景一弄,就能做出流弊的必杀场景了。

继续来完成这次的目标,放个人物立绘上去,我这里选择的是dlc Cover Art Characters 里面的Package2_3这个人物,把他放在了我们项目文件的picture文件里。同样,我们在创建我们标题页的方法里面新增一个普通精灵放上去。

JAVASCRIPT 代码复制
  1. Scene_Title.prototype.create_myTitleSprite = function(){
  2.  
  3.   //this._myBackSprite = new Sprite(ImageManager.loadParallax('SeaofClouds'));//普通精灵
  4.  
  5.   this._myBackSprite = new TilingSprite(ImageManager.loadParallax('SeaofClouds'));//平铺精灵
  6.  
  7.   //平铺精灵需要设置他默认的位置,否则是看不到的
  8.   //通过平铺精灵的move函数设置他的位置
  9.   //参数1  TilingSprite(平铺精灵) 的 X 坐标
  10.   //参数2  TilingSprite(平铺精灵) 的 Y 坐标
  11.   //参数3  TilingSprite(平铺精灵) 的宽度
  12.   //参数4  TilingSprite(平铺精灵) 的高度
  13.   //这里的Graphics的width和height是游戏窗口显示的宽度和高度,我们这样设置就会让这个平铺精灵全部占满屏幕
  14.   this._myBackSprite.move(0,0,Graphics.width,Graphics.height);
  15.  
  16.   this._myForeSprite = new Sprite(ImageManager.loadPicture('Package2_3'));//因为这里我仅是放一个人物立绘上去,所以就使用平铺精灵就好了
  17.  
  18.   //设置人物立绘的位置
  19.   this._myForeSprite.anchor.x = 0.5;               //设置立绘精灵的横向锚点,初始值是0,最大值为1,从左到右,最左是0,最右是1,这里设置的0.5就表示正中间
  20.   this._myForeSprite.anchor.y = 1;                  //设置立绘精灵的纵向锚点,初始值是0,最大值为1,从上到下,最上是0,最下是1,这里设置的1就表示最底部
  21.   this._myForeSprite.x = Graphics.width / 2;  //设置立绘精灵的水平坐标为整个屏幕宽度的一半,与我们之前设置的横向锚点配合,立绘精灵就会在屏幕的水平正中间
  22.   this._myForeSprite.y = Graphics.height;      //设置立绘精灵的纵向坐标为整个屏幕的高度,与我们之前设置的纵向锚点配合,立绘精灵的最底部就会跟屏幕的最底部重合
  23.  
  24.   //将我们的精灵添加到标题页
  25.   this.addChild(this._myBackSprite);
  26.   this.addChild(this._myForeSprite);
  27.  
  28. };


这样背景屏幕水平滚动的时候,中间还会有一个人物立绘在屏幕正中间,并且底部与屏幕底部贴合。

接下来做个看上去奇怪的效果,让人物立绘背后有个一模一样的人物扩散开来,一直循环,同样继续修改create_myTitleSprite方法

JAVASCRIPT 代码复制
  1. Scene_Title.prototype.create_myTitleSprite = function(){
  2.  
  3.   //this._myBackSprite = new Sprite(ImageManager.loadParallax('SeaofClouds'));//普通精灵
  4.  
  5.   this._myBackSprite = new TilingSprite(ImageManager.loadParallax('SeaofClouds'));//平铺精灵
  6.  
  7.   //平铺精灵需要设置他默认的位置,否则是看不到的
  8.   //通过平铺精灵的move函数设置他的位置
  9.   //参数1  TilingSprite(平铺精灵) 的 X 坐标
  10.   //参数2  TilingSprite(平铺精灵) 的 Y 坐标
  11.   //参数3  TilingSprite(平铺精灵) 的宽度
  12.   //参数4  TilingSprite(平铺精灵) 的高度
  13.   //这里的Graphics的width和height是游戏窗口显示的宽度和高度,我们这样设置就会让这个平铺精灵全部占满屏幕
  14.   this._myBackSprite.move(0,0,Graphics.width,Graphics.height);
  15.  
  16.   this._myForeSprite = new Sprite(ImageManager.loadPicture('Package2_3'));//因为这里我仅是放一个人物立绘上去,所以就使用平铺精灵就好了
  17.  
  18.   //设置人物立绘
  19.   this._myForeSprite.anchor.x = 0.5;               //设置立绘精灵的横向锚点,初始值是0,最大值为1,从左到右,最左是0,最右是1,这里设置的0.5就表示正中间
  20.   this._myForeSprite.anchor.y = 1;                  //设置立绘精灵的纵向锚点,初始值是0,最大值为1,从上到下,最上是0,最下是1,这里设置的1就表示最底部
  21.   this._myForeSprite.x = Graphics.width / 2;  //设置立绘精灵的水平坐标为整个屏幕宽度的一半,与我们之前设置的横向锚点配合,立绘精灵就会在屏幕的水平正中间
  22.   this._myForeSprite.y = Graphics.height;      //设置立绘精灵的纵向坐标为整个屏幕的高度,与我们之前设置的纵向锚点配合,立绘精灵的最底部就会跟屏幕的最底部重合
  23.  
  24.   this._myForeSprite2 = new Sprite(ImageManager.loadPicture('Package2_3'));//背后闪现的幻影
  25.  
  26.   //设置人物立绘的幻影,与人物立绘相同
  27.   this._myForeSprite2.anchor.x = 0.5;               
  28.   this._myForeSprite2.anchor.y = 1;                 
  29.   this._myForeSprite2.x = Graphics.width / 2;
  30.   this._myForeSprite2.y = Graphics.height;
  31.  
  32.   //将我们的精灵添加到标题页
  33.   this.addChild(this._myBackSprite);
  34.   this.addChild(this._myForeSprite2);
  35.   //这里添加的时候,我们首先是添加的幻影的那个精灵,再添加的立绘的精灵,因为我想达到的效果是在人物立绘的背后出现幻影,如果先添加立绘精灵的话,这个幻影就会在立绘精灵的前面闪动,这里各位可以试着调换一下顺序就明白了
  36.   this.addChild(this._myForeSprite);
  37.  
  38.  
  39. };


到此,实际的效果只是立绘精灵和幻影精灵重叠了而已,没有任何动作,我们修改update方法来让幻影精灵动起来,实现思路是,我让幻影精灵的透明度(Opacity)慢慢的减弱,并且让幻影精灵的缩放(Scale)慢慢的变大,就能表现出一种向外拓展的效果了,同时幻影精灵完全变成透明的时候,我们要重置他的缩放(Scale)和透明度(Opacity)。
JAVASCRIPT 代码复制
  1. var _myScene_Title_update = Scene_Title.prototype.update;
  2.  
  3.   Scene_Title.prototype.update = function() {
  4.  
  5.     _myScene_Title_update.call(this);
  6.  
  7.     //this._myBackSprite.x += 1 ;
  8.  
  9.     this._myBackSprite.origin.x += 1 ;
  10.  
  11.     //幻想精灵透明度(Opacity)完全透明的时候,重置他的缩放和透明度
  12.       if(this._myForeSprite2.opacity <= 0){
  13.  
  14.         this._myForeSprite2.opacity = 255;
  15.  
  16.         this._myForeSprite2.scale.x = 1;
  17.  
  18.         this_myForeSprite2.scale.y = 1 ;
  19.  
  20.       }
  21.     //幻想精灵并没有完全透明的时候,我们让他的透明度一直减小,同时通过改变他的缩放来看上去一种扩散的感觉
  22.       else{
  23.  
  24.         this._myForeSprite2.opacity -= 3 ;
  25.  
  26.         this._myForeSprite2scale.x += 0.003;
  27.  
  28.         this._myForeSprite2.scale.y += 0.003;
  29.  
  30.       }


最后把插件加入到游戏里面去

到此,我们这次的目的就能完成了,最后的效果就是这样(脑补一下,动起来的喔)



只要大家脑洞大开,这样继续拓展,我觉得做些啥流弊效果都没问题的吧

点评

精灵跟面向对象里面的类跟对象很像吧?  发表于 2017-1-1 21:30
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2015-12-15
帖子
6
8
发表于 2016-4-4 01:49:22 | 只看该作者
看到前文提到了一点。。可否请问要怎么给道具加事件。。。?比如我希望key item里,对某一项按确定之后跳出图片以及对话框,再按确定或者取消之后返回key item界面里,这样的效果该怎么做呢?谢赐教
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2016-3-30
帖子
13
9
 楼主| 发表于 2016-4-4 22:18:46 | 只看该作者
yochii 发表于 2016-4-4 01:49
看到前文提到了一点。。可否请问要怎么给道具加事件。。。?比如我希望key item里,对某一项按确定之后跳出 ...

呼~~~

看到你的回复之后,搞了我好几个小时,毕竟是第一个向我提问的人啊,我这不就全力以赴的帮你研究这个了么,总算弄出来了

过程中也发现了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不清空栈堆的标示改为失效

接下来上代码

JAVASCRIPT 代码复制
  1. /**
  2.  * 使用过道具之后,弹出消息再回到道具页面
  3.  */
  4. Scene_Map.prototype.start = function() {
  5.   Scene_Base.prototype.start.call(this);
  6.   //如果需要重新打开道具页面,则不清空栈
  7.   if(!$gameSystem._needReplayItemMenu){
  8.     SceneManager.clearStack();
  9.   }
  10.   if (this._transfer) {
  11.     this.fadeInForTransfer();
  12.     this._mapNameWindow.open();
  13.     $gameMap.autoplay();
  14.   } else if (this.needsFadeIn()) {
  15.     this.startFadeIn(this.fadeSpeed(), false);
  16.   }
  17.   this.menuCalling = false;
  18. };
  19.  
  20. //为了不影响其他正常的消息展示,这里同样使用之前的标示来控制。当这个标示有效的时候,SceneManager.pop();让屏幕回到上一屏
  21. var _my_Window_Message_terminateMessage = Window_Message.prototype.terminateMessage;
  22. Window_Message.prototype.terminateMessage = function() {
  23.   _my_Window_Message_terminateMessage.call(this);
  24.  
  25.   if($gameSystem._needReplayItemMenu){
  26.     SceneManager.pop();
  27.   }
  28. };
  29.  
  30. //因为消息是在Scene_Map中的一个window,所以要显示消息的话,得回到Scene_Map中,所以这里把Scene_Map push进了栈堆,同时显示出消息
  31. var _my_Scene_Item_useItem = Scene_Item.prototype.useItem;
  32. Scene_Item.prototype.useItem = function() {
  33.   _my_Scene_Item_useItem.call(this);
  34.  
  35.   SceneManager.push(Scene_Map);
  36.   $gameMessage.add('使用了:'+this.item().name);
  37.   $gameSystem._needReplayItemMenu = true;
  38. };
  39.  
  40. //创建道具栏的分类的时候,调用我们的设置最后选择的分类的方法
  41. var _my_Scene_Item_createCategoryWindow = Scene_Item.prototype.createCategoryWindow;
  42. Scene_Item.prototype.createCategoryWindow = function() {
  43.   _my_Scene_Item_createCategoryWindow.call(this);
  44.  
  45.   this.setSelectLast();
  46. };
  47.  
  48. //当分类栏点击确定的时候,把最后选择的分类栏的下标保存下来
  49. var _my_Scene_Item_onCategoryOK = Scene_Item.prototype.onCategoryOk;
  50. Scene_Item.prototype.onCategoryOk = function() {
  51.   _my_Scene_Item_onCategoryOK.call(this);
  52.  
  53.   $gameSystem._categoryWindowSelectInx = this._categoryWindow._index;
  54.  
  55. };
  56.  
  57. //如果最后选择的分类栏的下标存在,则默认选中
  58. Scene_Item.prototype.setSelectLast = function(){
  59.   if($gameSystem._needReplayItemMenu){
  60.     //关闭是否回到Scene_Map清空栈堆的标示
  61.     $gameSystem._needReplayItemMenu = false;
  62.     this._categoryWindow._index = isNaN($gameSystem._categoryWindowSelectInx) ? 0 : $gameSystem._categoryWindowSelectInx;
  63.     this._categoryWindow.activate();
  64.   }
  65. };


接下来得创建道具


这里稍微提一下,这里的scope选none,意思就是随便用,如果scope是1 ally及后面的话,会弹出submenu来选择使用对象,所以我这里就直接选的none

最后插件管理里面加起来,跑起来



使用了道具,弹出提示,然后关闭之后又回到了道具栏,呼`````
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
19 小时
注册时间
2015-12-15
帖子
6
10
发表于 2016-4-5 03:49:43 | 只看该作者
bulangnisi 发表于 2016-4-4 22:18
呼~~~

看到你的回复之后,搞了我好几个小时,毕竟是第一个向我提问的人啊,我这不就全力以赴的帮你研 ...

天哪……………………简直太感谢了!!!!!!!原来每次scene_map都要清空栈…………总之太感谢了!!!!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-1 19:34

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表