RPG Maker MV 仿新仙剑 战斗场景UI 五
战斗状态菜单
这部分比较简单,由于有主菜单的状态菜单打底所以开发上也容易些。
原始RMMV 菜单窗口
在原版的RMMV中显示的数据主要是人物的HP、MP、TP、和两个计量条及人物姓名,不需要显示的东西可以不进行显示。
如图显示是很单调的,主菜单的好歹还有个头像,这个就少了一些东西。
仿新仙剑代码
function Window_BattleStatus() {
this.initialize.apply(this, arguments);
}
Window_BattleStatus.prototype = Object.create(Window_Selectable.prototype);
Window_BattleStatus.prototype.constructor = Window_BattleStatus;
Window_BattleStatus.prototype.initialize = function(x,y) {
Window_Selectable.prototype.initialize.call(this, x, y, 465, 116);
this.characterStateFrame=ImageManager.loadMenu('CharacterStateFrame');
this.refresh();
};
Window_BattleStatus._faceWidth=144;
Window_BattleStatus._faceHeight=112;
//标准内边距
Window_BattleStatus.prototype.standardPadding = function() {
return 0;//18;
};
Window_BattleStatus.prototype.numVisibleRows = function() {
return 1;
};
//设置状态菜单的最大列数
Window_BattleStatus.prototype.maxCols = function() {
return 3;
};
//最大项目数
Window_BattleStatus.prototype.maxItems = function() {
return $gameParty.size();
};
//间距
Window_BattleStatus.prototype.spacing = function() {
return 6;
};
//每项高度
Window_BattleStatus.prototype.itemHeight = function() {
var clientHeight = this.height - this.padding * 2;
return Math.floor(clientHeight / this.numVisibleRows());
};
Window_BattleStatus.prototype.drawItem = function(index) {
this.drawItemImage(index);
this.drawItemStatus(index);
};
//绘制人物背景
Window_BattleStatus.prototype.drawItemBackground = function(index) {
if (index === this._pendingIndex) {
var rect = this.itemRect(index);
//var color = this.pendingColor();
var color = this.deathColor();
this.changePaintOpacity(false);
this.contents.fillRect(rect.x, rect.y, rect.width, rect.height, color);
this.changePaintOpacity(true);
}
};
//绘制人物图像
Window_BattleStatus.prototype.drawItemImage = function(index) {
var actors = $gameParty.members();
var actor=actors[index];
var rect = this.itemRect(index);
this.changePaintOpacity(actor.isBattleMember());
this.drawActorFace(actor, rect.x + 2, rect.y + 1, rect.width, rect.height,index);
this.changePaintOpacity(true);
};
//绘制演员头像
Window_BattleStatus.prototype.drawActorFace = function(actor, x, y, width, height,index) {
this.drawFace(actor.faceName(), actor.faceIndex(), x, y, width, height,index);
};
//绘制头像
Window_BattleStatus.prototype.drawFace = function(faceName, faceIndex, x, y, width, height,index) {
var actors=$gameParty.members();
var wx=0;
switch(actors.length){
case 1:
wx=154*2;
break;
case 2:
wx=154;
break;
default:
break;
}
width = width || Window_BattleStatus._faceWidth;
height = height || Window_BattleStatus._faceHeight;
var bitmap = ImageManager.loadFace(faceName);
var pw = Window_BattleStatus._faceWidth;
var ph = Window_BattleStatus._faceHeight;
var sw = Math.min(width, pw);
var sh = Math.min(height, ph);
var sx = faceIndex % 6 * pw + (pw - sw) / 2;
var sy = Math.floor(faceIndex / 6) * ph + (ph - sh) / 2;
if(!bitmap.isReady()){
setTimeout(()=>{
this.contents.blt(bitmap, sx, sy, sw, sh, x+wx, y);
this.drawItemStatus(index);
},0.25);
}else{
this.contents.blt(bitmap, sx, sy, sw, sh, x+wx, y);
}
};
//绘制人物状态
Window_BattleStatus.prototype.drawItemStatus = function(index) {
var actor = $gameParty.members()[index];
var rect = this.itemRect(index);
this.drawActorSimpleStatus(actor, rect.x, rect.y, rect.width,rect.height);
};
//绘制演员简单状态
Window_BattleStatus.prototype.drawActorSimpleStatus = function(actor, x, y, width,height) {
this.drawActorIcons(actor, x+73, y+36,width,height);// 人物状态图标
this.drawActorHp(actor, x, y, width);
this.drawActorMp(actor, x, y, width);
};
//绘制演员图标,作为参考及绘制四种状态
Window_BattleStatus.prototype.drawActorIcons = function(actor, x, y, width) {
width = width || 144;
var actorStates=actor.states(); //获取人物状态
var stateIcons=[];
for (var i = 0; i < actorStates.length; i++) {
if (actorStates[i].id>13&&actorStates[i].id<18) {
stateIcons.push(actorStates[i].iconIndex);
}
}
for (var i = 0; i < stateIcons.length&&i<2; i++) {
this.drawIcon(stateIcons[i]-12, x + 24 * i+(i*5), y);
}
};
//绘制状态图标
Window_BattleStatus.prototype.drawIcon = function(iconIndex, x, y) {
var actors=$gameParty.members();
var wx=0;
switch(actors.length){
case 1:
wx=154*2;
break;
case 2:
wx=154;
break;
default:
break;
}
x=x+wx;
var bitmap = ImageManager.loadSystem('CharacterStatus');
var pw = 24;
var sx = iconIndex % 5 * pw;
var sy = 0;
if(!bitmap.isReady()){
//console.log(bitmap.isReady())
setTimeout(()=>{this.contents.blt(bitmap, sx, sy, pw, 26, x, y);},0.25);
}else{
this.contents.blt(bitmap, sx, sy, pw, 26, x, y);
}
};
//绘制演员HP
Window_BattleStatus.prototype.drawActorHp = function(actor, x, y, width) {
width = width || 144;
var color1 = this.textColor(10);
var color2 = this.textColor(15);
this.drawCurrentAndMax(actor.hp, actor.mhp, x-2, y+56, width,color1, color2);
};
//绘制演员MP
Window_BattleStatus.prototype.drawActorMp = function(actor, x, y, width) {
width = width || 144;
var color1 = this.textColor(9);
var color2 = this.textColor(15);
this.drawCurrentAndMax(actor.mp, actor.mmp, x-10, y+74, width,color1, color2);
};
//绘制现在和最大值
Window_BattleStatus.prototype.drawCurrentAndMax = function(current, max, x, y,
width, color1, color2) {
var actors=$gameParty.members();
var wx=0;
switch(actors.length){
case 1:
wx=154*2;
break;
case 2:
wx=154;
break;
default:
break;
}
x=x+wx;
this.contents.fontSize=14;//设置字体大小
var labelWidth = this.textWidth('HP');//28
var valueWidth = this.textWidth('0000');//56
var slashWidth = this.textWidth('/');//14
var x1 = x + width - valueWidth;
var x2 = x1 - slashWidth;
var x3 = x2 - valueWidth;
if (x3 >= x + labelWidth) {
this.changeTextColor(color1);
this.contents.outlineColor=color1;
this.contents.outlineWidth = 0;
this.drawText(current, x3, y, valueWidth, 'right');
this.changeTextColor(color2);
this.contents.outlineColor=color2;
this.contents.outlineWidth = 0;
this.drawText('/', x2, y, slashWidth, 'center');
this.changeTextColor(color1);
this.contents.outlineColor=color1;//轮廓颜色
this.contents.outlineWidth = 0;//轮廓宽度
this.drawText(max, x1, y, valueWidth, 'left');
} else {
this.contents.outlineColor=color1;//轮廓颜色
this.contents.outlineWidth = 0;//轮廓宽度
this.changeTextColor(color1);
this.drawText(current, x1, y, valueWidth, 'left');
}
};
//绘制文本
Window_BattleStatus.prototype.drawText = function(text, x, y, maxWidth, align) {
this.contents.drawText(text, x, y, maxWidth, this.lineHeight(), align);
};
//等待索引
Window_BattleStatus.prototype.pendingIndex = function() {
return this._pendingIndex;
};
//刷新光标
Window_BattleStatus.prototype._refreshCursor = function() {
var pad = this._padding;
var x = this._cursorRect.x;
var y = this._cursorRect.y;
var w = this._cursorRect.width;
var h = this._cursorRect.height;
var bitmap = new Bitmap(w, h);
this._windowCursorSprite.bitmap = bitmap;
this._windowCursorSprite.setFrame(0, 0, w, h);
var actors=$gameParty.members();
var wx=0;
switch(actors.length){
case 1:
wx=154*2;
break;
case 2:
wx=154;
break;
default:
break;
}
this._windowCursorSprite.move(wx+x, y);
if (w > 0 && h > 0&&this.characterStateFrame) {
var csf=this.characterStateFrame;
this._windowCursorSprite.bitmap.blt(csf,0,0,164,96,0-3,0+20,164,96);
}
};
//更新光标
Window_BattleStatus.prototype._updateCursor = function() {
this._windowCursorSprite.bitmap.clear();
var blinkCount = this._animationCount % 50;
var characterStateSpriteY=0;
if (this._windowCursorSprite.visible) {
switch(Math.floor(blinkCount/10)){
case 0:
characterStateSpriteY=0;
break;
case 1:
characterStateSpriteY=96;
break;
case 2:
characterStateSpriteY=192;
break;
case 3:
characterStateSpriteY=288;
break;
case 4:
characterStateSpriteY=384;
break;
default:
//characterStateSpriteY=4*96;
break;
}
}
this._windowCursorSprite.bitmap.blt(this.characterStateFrame,0,characterStateSpriteY,164,96,0-3,0+20,164,96);
this._windowCursorSprite.visible = this.isOpen();
};
Window_BattleStatus.prototype.update = function() {
Window_Selectable.prototype.update.call(this);
this._animationCount++;
};
这里只对其中部分代码做出解释,大部分代码在之前都说过的。
initialize 方法中,调用的父类传入的参数width和主菜单的不同,这是为什么,这是因为主菜单时做的是4角色同框的,而这里是3个角色同框的,后期应该会保持一致。
maxCols 方法中的参数也是这个作用。
switch(actors.length){
case 1:wx=154*2;break;
case 2:wx=154;break;
default:break;
}
这部分代码也是这个作用,重新计算需要绘制图像的位置。
_updateCursor 这个更新光标的方法中判断的条件发生了变化,原来是按照是否激活来判断,现在按照是否隐藏来判断,这是因为,默认窗口是取消激活的,而激活后导致的问题就是在使用其他菜单时会操作到这个菜单,因此需要取消激活,但是光标的更新就出现了问题,因此需要更换判断条件。
update 正常来说更新的方法是不用显示的写出来的,因为会自动执行,但里面的代码更新动画的变量是在窗口激活时才进行计数的,因此需要子类显示调用父类后重新进行动画更新计时的增加,不然就不能正常显示。
仿新仙剑战斗状态菜单
如图:
做出来的样子就是这样的,当然了,现在是暂时没有去掉背景的,后期全部完善战斗场景的窗口和功能后再去掉背景。