1 窗口基类的图片描画接口
RPG Maker mv框架中的窗口基类(Window_Base)提供了两个用来在窗口上描画图片的接口:
- drawFace
- drawIcon
当我们设计出一个基于窗口基类的窗口类后,就可以使用这两个接口在我们新窗口上描画我们的图片。不过看名字也知道,这俩接口不是什么都能画的,一个是用来话头像的(drawFace),另一个是用来话图标的(drawIcon)。
我们先来看看什么是Face和Icon:
- Face指的是存放与下面固定路径中的图片,图片中头像的大小,排列方式都是RPG Maker mv规定好的:
img\faces
来个Face图片的例子:
- Icon指的是存放在下面固定路径中特定的图片,图片中头像的大小,排列方式都是RPG Maker mv规定好的:
img\system\IconSet.png
Icon图片的内容如下:
如果想要随心所欲的画自己的图片,只能使用更底层的接口,这个后面再说。
1.1 Face描画接口
Window_Base.prototype.drawFace = function(faceName, faceIndex, x, y, width, height) {
width = width || Window_Base._faceWidth;
height = height || Window_Base._faceHeight;
var bitmap = ImageManager.loadFace(faceName);
var pw = Window_Base._faceWidth;
var ph = Window_Base._faceHeight;
var sw = Math.min(width, pw);
var sh = Math.min(height, ph);
var dx = Math.floor(x + Math.max(width - pw, 0) / 2);
var dy = Math.floor(y + Math.max(height - ph, 0) / 2);
var sx = faceIndex % 4 * pw + (pw - sw) / 2;
var sy = Math.floor(faceIndex / 4) * ph + (ph - sh) / 2;
this.contents.blt(bitmap, sx, sy, sw, sh, dx, dy);
};
- faceName Face所在图片的名称(去掉扩展名.png)
- faceIndex Face所在位置,一般一张图片里有8张Face,编号从0~7
- x 描画位置的x坐标,这里的位置是相对于窗口基类contents成员来说的,就是在contents成员上画的位置
- y 描画位置的y坐标,这里的位置是相对于窗口基类contents成员来说的,就是在contents成员上画的位置
- width Face图像的宽
- height Face图像的高
下面来个例子:
//=============================================================================
// Window_Friendliness_List
//
// 友好度展示窗口
//=============================================================================
function Window_Friendliness_List() {
this.initialize.apply(this, arguments);
};
Window_Friendliness_List.prototype = Object.create(Window_Selectable.prototype);
Window_Friendliness_List.prototype.constructor = Window_Friendliness_List;
Window_Friendliness_List.prototype.initialize = function(x, y) {
var width = this.windowWidth();
var height = this.windowHeight();
Window_Selectable.prototype.initialize.call(this, x, y, width, height);
this.NPCList = [
{
"faceName":"Actor2",
"faceIndex":6,
"name":"卡洛琳"
},
{
"faceName":"Actor1",
"faceIndex":2,
"name":"斯洛特"
},
{
"faceName":"People2",
"faceIndex":7,
"name":"希尔"
},
{
"faceName":"伊莉莎(普通)",
"faceIndex":0,
"name":"伊莉莎"
},
{
"faceName":"People4",
"faceIndex":1,
"name":"夏莉"
},
{
"faceName":"Actor1",
"faceIndex":4,
"name":"沙兰特"
}
];
};
Window_Friendliness_List.prototype.drawItem = function(index) {
this.drawItemImage(index);
};
Window_Friendliness_List.prototype.drawItemImage = function(index) {
var rect = this.itemRect(index);
var faceName = this.NPCList[index]["faceName"];
var faceIndex = this.NPCList[index]["faceIndex"];
this.drawFace(faceName, faceIndex, rect.x + 1, rect.y + 1, Window_Base._faceWidth, Window_Base._faceHeight);
};
在上面的例子中,我们首先创建了一个友好度展示用的窗口函数Window_Friendliness_List,继承于Window_Selectable对象的。 Window_Selectable对象继承自Window_Base对象,因此我们的友好度展示窗口对象最终继承于Window_Base对象。
通过new方法创建Window_Friendliness_List窗口对象时,Window_Friendliness_List.prototype.initialize会被调用,通过Window_Friendliness_List.prototype.initialize方法完成友好度展示窗口对象的内部数据构造。可以看到Window_Friendliness_List对象内部维护了一个NPCList,其实是所展示列表中各NPC头像图片的信息。
Window_Selectable对象有个refresh()方法,这个方法会调用Window_Friendliness_List.prototype.drawItem,而Window_Friendliness_List.prototype.drawItem会调用Window_Friendliness_List.prototype.drawItemImage,在Window_Friendliness_List.prototype.drawItemImage中我们通过drawFace()接口完成头像的描画。
Window_Selectable对象的refresh()方法其实是在友好度展示场景对象中触发调用的,例子中没有展示上层场景对象的代码。
1.2 Icon描画接口
Window_Base.prototype.drawIcon = function(iconIndex, x, y) {
var bitmap = ImageManager.loadSystem('IconSet');
var pw = Window_Base._iconWidth;
var ph = Window_Base._iconHeight;
var sx = iconIndex % 16 * pw;
var sy = Math.floor(iconIndex / 16) * ph;
this.contents.blt(bitmap, sx, sy, pw, ph, x, y);
};
- iconIndex Icon在IconSet.png图片中的位置索引,注意空白的部分也是要参与编号的
- x 描画位置的x坐标,这里的位置是相对于窗口基类contents成员来说的,就是在contents成员上画的位置
- y 描画位置的y坐标,这里的位置是相对于窗口基类contents成员来说的,就是在contents成员上画的位置
2 描画自定义图片
我们可以看到通过上面介绍的接口只能画RPG Maker mv框架规定好大小的图片(Face和Icon),当然我们也可以按照Face和Icon的大小要求自己创建图片放到指定的目录下使用,但是当我们需要按照自己的需要画其它大小内容的图片时就不行了。
那么到底有没有其他方法可以描画自定义图片呢?答案当然是有。
我们观察drawFace和drawIcon接口发现,最终描画时都调用了blt方法。这个blt方法属于this.contents,而contents所指向的就是Bitmap对象。到这里我们终于认识到这些图片都是描画在哪里的了。没错,就是在一个几乎占满窗口的大Bitmap对象上画的。
我们来看一下它的实现:
Bitmap.prototype.blt = function(source, sx, sy, sw, sh, dx, dy, dw, dh) {
dw = dw || sw;
dh = dh || sh;
if (sx >= 0 && sy >= 0 && sw > 0 && sh > 0 && dw > 0 && dh > 0 &&
sx + sw <= source.width && sy + sh <= source.height) {
this._context.globalCompositeOperation = 'source-over';
this._context.drawImage(source._canvas, sx, sy, sw, sh, dx, dy, dw, dh);
this._setDirty();
}
};
-
source 一个Bitmap对象,这个对象中包含所要描画图片数据。它一般是通过ImageManager全局对象的一系列load方法得到的:
- loadSystem
- loadFace
- loadIcon
- … … -
sx 要描画的部分在图片中的位置的x坐标
-
sy 要描画的部分在图片中的位置的y坐标
-
sw 要描画的部分的宽
-
sh 要描画的部分的高
-
dx 目标位置的x坐标,相对于contents所指向的Bitmap对象来说
-
dy 目标位置的y坐标,相对于contents所指向的Bitmap对象来说
-
dw 目标的宽
-
dh 目标的高
我们可以通过Bitmap对象的blt方法来描画自定义图片,当然要描画的图片其实可以放在下面几个目录的任意一个中,那么在创建被描画Bitmap对象时就要调用对应位置的load方法:
图片位置 | load方法 |
---|---|
img/animations/ | ImageManager.loadAnimation |
img/battlebacks1/ | ImageManager.loadBattleback1 |
img/battlebacks2/ | ImageManager.loadBattleback2 |
img/enemies/ | ImageManager.loadEnemy |
img/characters/ | ImageManager.loadCharacter |
img/faces/ | ImageManager.loadFace |
img/parallaxes/ | ImageManager.loadParallax |
img/pictures/ | ImageManager.loadPicture |
img/sv_actors/ | ImageManager.loadSvActor |
img/sv_enemies/ | ImageManager.loadSvEnemy |
img/system/ | ImageManager.loadSystem |
img/tilesets/ | ImageManager.loadTileset |
img/titles1/ | ImageManager.loadTitle1 |
img/titles2/ | ImageManager.loadTitle2 |
上面的文件路径其实根据具体的用处定义的,根据名称基本上能猜出来用来放置何种类型的图片的。
我们在放置自定义图片时可以按照框架赋予的含义来选择路径,这样也方便我们自己管理图片资源。