下面就开始实现人物信息随选项变动的功能了!
首先,我们需要知道存储当前选项的变量是什么,在Window_MenuStatus中的处理确定的函数processOk中,获取当前的人物是通过this.index()实现的,而this.index()呢?在Window_MenuStatus中没有搜到这个函数的定义,因此我们去他的父类Window_Selectable中搜索,得到以下结果:
- /**索引 */
- Window_Selectable.prototype.index = function() {
- //返回 _index
- return this._index;
- };
复制代码因此我们也珂以使用this._index获取当前index。
因此将index那里改为this._index,然后运行下看看效果。
运行后却得到了TypeError: Cannot read property 'faceName' of undefined的错误。
难道说this._index出错了?我们珂以看看到底运行到这里this._index返回了什么值。
这就要用到浏览器的控制台输出函数,在出错的这行前面插入:
- console.log(this._index);
复制代码再次运行打开菜单出错后按F12,发现输出的值为-1,为什么是-1?我们现在他等于-1的时候把值改为0,然后在F12里面看看这个-1是什么情况下出现的。
因此将定义actor那行改为:
- var actor = $gameParty.members()[this._index==-1?0:this._index];
复制代码却发现F12在选项移动的过程中并没有输出任何东西,说明drawItemActorStatus这个函数在选项移动过程中并没有被调用,只是绘制选项的过程中被调用了一次,这显然达不到我们的要求。
这里补充一个知识:放在窗口类的update函数内的函数会不断被调用。而Window_MenuStatus中没有定义update函数,说明他的update与父类相同,因此需要自己定义update函数(首先继承了父类的update函数):
- Window_MenuStatus.prototype.update = function(){
- Window_Selectable.prototype.update.call(this);
- this.drawItemActorStatus();
- };
复制代码并且记得在drawItem中删掉drawItemActorStatus函数的引用。
然后运行后发现,虽然人物信息随着选项的移动而改变,但是却发现原来的人物信息还在,只是往窗口上一层一层地“铺”,这样肯定是不行的。
因此我们需要想办法,让原人物信息先从菜单上清除,再描绘当前选项的人物信息。
Tip:清除坐标为x,y,高和宽分别为height和width的矩形中的内容的函数为clearRect,我们珂以通过itemRectForStatus函数来获得矩形的信息,同样把下面这行插入update:
- this.contents.clearRect(rect.x,rect.y,rect.width,rect.height);
复制代码运行下看看结果……
确实是没问题了。但是不知为啥电脑风扇开始狂转,打开任务管理器,发现MV的生成的游戏的进程电池使用情况为“非常高”(写教程的时候电脑开着这个时候的游戏开了一晚上,早晨起来发现电脑风扇快转疯了……),这肯定不正常啊…
打开F12发现,之前写的输出this._index的代码正在疯狂输出-1,说明画面更新实在是太频繁了,而实际上并不需要这么频繁,只需要在选项变化的时候更新画面即可。
怎样判断选项变化呢?
因为this._index存储了当前的选项,所以只要选项和原来不一样,this._index就会和原来不一样,所以珂以先把this._index的值存到一个变量中,如果两者不相等,再执行清除重绘的函数,并更新存储的变量,这样就珂以解决因为频繁刷新而导致电脑卡到爆的情况了。
我们在update函数外面新建一个变量xjzsqIndex,然后在update函数内增加一个if判断,来实现这个效果,并且记得把在控制台输出this._index值的那句删掉!代码如下:
- var xjzsqIndex;
- Window_MenuStatus.prototype.update = function(){
- Window_Selectable.prototype.update.call(this);
- if(xjzsqIndex != this._index)
- {
- var rect = this.itemRectForStatus();
- this.contents.clearRect(rect.x, rect.y, rect.width, rect.height);
- this.drawItemActorStatus();
- xjzsqIndex = this._index;
- }
- };
复制代码电池使用情况立马变成“中”了。
现在就只剩下改变菜单背景了吧。
在加上自带的背景图片之前,我们先把窗口自带的边框“扒”掉,虽然说是扒掉,但是方法确实将窗口背景部分的内容透明度更改为0。
比较合适的修改窗口透明度的时机有两个,一个是在窗口的initialize中修改,因为这是窗口的初始化过程,只执行一次,不会因为多次执行浪费计算资源,另一种是在使用new创建窗口的时候修改,具体在哪里修改还是要看具体情况,哪个方便就在哪里改。
首先是显示金钱的窗口,因为我们在脚本中定义过Scene_Menu的createGoldWindow函数,因此珂以在金钱窗口创造后使用
- this._goldWindow.opacity = 0;
复制代码来将金钱窗口背景的透明度修改为0。
对于菜单选项窗口,我们考虑在initialize函数中修改透明度,但是我们发现initialize中已经有了其他方法,我们珂以通过重写这个方法,也就是:(具体为什么这样写珂以去看我参考资料中的烂尾教程一)
- xjzsqInitialize = Window_MenuCommand.prototype.initialize;
- Window_MenuCommand.prototype.initialize = function(){
- xjzsqInitialize.call(this);
- this.opacity = 0;
- };
复制代码但是我希望代码尽量短一些,所以我决定在refresh中修改透明度,原因是,refresh函数在该函数中并没有定义,而是直接继承的父类的refresh中的内容,我们自己重新定义比较方便,另外refresh函数也只在他的父类的initialize函数中被调用了一次,本质上还是在initialize中修改的。
因此我们珂以用比上面少一行的代码量来修改复杂度:
- Window_MenuCommand.prototype.refresh = function(){
- Window_Command.prototype.refresh.call(this);
- this.opacity = 0;
- };
复制代码同样地,经过搜索,发现Window_MenuStatus情况也大致相同,因此采用与上面同样的方法:
- Window_MenuStatus.prototype.refresh = function(){
- Window_Selectable.prototype.refresh.call(this);
- this.opacity = 0;
- };
复制代码运行游戏测试一下: