floorImg animate

This commit is contained in:
oc 2019-02-04 17:14:57 +08:00
parent a4a7c26b37
commit 943b70faa1
9 changed files with 121 additions and 68 deletions

View File

@ -801,7 +801,7 @@ setBgFgBlock_s
/* setBgFgBlock_s /* setBgFgBlock_s
tooltip : setBgFgBlock设置某个图层块,忽略坐标楼层则为当前点 tooltip : setBgFgBlock设置某个图层块,忽略坐标楼层则为当前点
helpUrl : https://h5mota.com/games/template/docs/#/event?id=setblock%EF%BC%9A%E8%AE%BE%E7%BD%AE%E6%9F%90%E4%B8%AA%E5%9B%BE%E5%9D%97 helpUrl : https://h5mota.com/games/template/docs/#/event?id=setblock%EF%BC%9A%E8%AE%BE%E7%BD%AE%E6%9F%90%E4%B8%AA%E5%9B%BE%E5%9D%97
colour : this.eventColor colour : this.dataColor
default : ["bg",0,"","",""] default : ["bg",0,"","",""]
var floorstr = ''; var floorstr = '';
if (PosString_0 && PosString_1) { if (PosString_0 && PosString_1) {

View File

@ -93,6 +93,7 @@ editor_blockly = function () {
MotaActionBlocks['useItem_s'].xmlText(), MotaActionBlocks['useItem_s'].xmlText(),
MotaActionBlocks['openShop_s'].xmlText(), MotaActionBlocks['openShop_s'].xmlText(),
MotaActionBlocks['setBlock_s'].xmlText(), MotaActionBlocks['setBlock_s'].xmlText(),
MotaActionBlocks['setBgFgBlock_s'].xmlText(),
MotaActionBlocks['setHeroIcon_s'].xmlText(), MotaActionBlocks['setHeroIcon_s'].xmlText(),
MotaActionBlocks['follow_s'].xmlText(), MotaActionBlocks['follow_s'].xmlText(),
MotaActionBlocks['unfollow_s'].xmlText(), MotaActionBlocks['unfollow_s'].xmlText(),
@ -115,7 +116,6 @@ editor_blockly = function () {
MotaActionBlocks['hideFloorImg_s'].xmlText(), MotaActionBlocks['hideFloorImg_s'].xmlText(),
MotaActionBlocks['showBgFgMap_s'].xmlText(), MotaActionBlocks['showBgFgMap_s'].xmlText(),
MotaActionBlocks['hideBgFgMap_s'].xmlText(), MotaActionBlocks['hideBgFgMap_s'].xmlText(),
MotaActionBlocks['setBgFgBlock_s'].xmlText(),
MotaActionBlocks['trigger_s'].xmlText(), MotaActionBlocks['trigger_s'].xmlText(),
MotaActionBlocks['insert_1_s'].xmlText(), MotaActionBlocks['insert_1_s'].xmlText(),
MotaActionBlocks['insert_2_s'].xmlText(), MotaActionBlocks['insert_2_s'].xmlText(),

View File

@ -84,13 +84,13 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana');
由于HTML5功能素材有限导致了对很多比较复杂的素材比如房子内等无法有着较好的绘图方式。 由于HTML5功能素材有限导致了对很多比较复杂的素材比如房子内等无法有着较好的绘图方式。
为了解决这个问题,我们允许用户自己放置一张或多张图片作为某一层的背景素材。 为了解决这个问题,我们允许用户自己放置一张或多张图片作为某一层的背景/前景素材。
要启用这个功能,我们首先需要在`data.js`中将可能的图片进行加载。 要启用这个功能,我们首先需要在`data.js`中将可能的图片进行加载。
``` js ``` js
"images": [ // 在此存放所有可能使用的图片 "images": [ // 在此存放所有可能使用的图片
// 图片可以被作为背景图(的一部分),也可以直接用自定义事件进行显示。 // 图片可以被作为背景/前景图,也可以直接用自定义事件进行显示。
// 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 // 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
// 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 // 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量
"bg.jpg", "house.png", "bed.png"// 依次向后添加 "bg.jpg", "house.png", "bed.png"// 依次向后添加
@ -99,18 +99,21 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana');
!> 请使用网上的一些[在线图片压缩工具](http://compresspng.com/zh/)对图片进行压缩,以节省流量。 !> 请使用网上的一些[在线图片压缩工具](http://compresspng.com/zh/)对图片进行压缩,以节省流量。
之后,我们可以在每层剧本的`"images"`里来定义该层的默认背景图片素材。 之后,我们可以在每层剧本的`"images"`里来定义该层的默认背景/前景层的图片素材。
从V2.5.4开始,贴图也允许进行帧动画,只要设置第五项的数值。
``` js ``` js
"images": [[3,5,"bg.jpg",0]], // 背景图;你可以选择一张或多张图片来作为背景/前景素材。 "images": [[96,120,"bg.jpg",0]], // 背景图;你可以选择一张或多张图片来作为背景/前景素材。
"images": [], // 无任何背景图 "images": [], // 无任何背景图
"images": [[1,1,"house.png",0], [6,7,"bed.png",1]] // 在(1,1)放一个house.png在背景层且(6,7)放bed.png在前景层 "images": [[32,32,"house.png",0], [160,170,"bed.png",1]] // 在(32,32)放一个house.png在背景层且(160,170)放bed.png在前景层
"images": [[3,5,"tree.png",2]] // 如果写2则会自动调节遮挡效果 "images": [[96,120,"tree.png",2]] // 如果写2则会自动调节遮挡效果
"images": [[64,0,"x.png",1,4]] // 这是一个前景层的4帧动画贴图
``` ```
images为一个数组代表当前层所有作为背景素材的图片信息。 images为一个数组代表当前层所有作为背景素材的图片信息。每一项为一个五元组分别为该背景素材的xy图片名遮挡方式和帧数。
每一项为一个四元组分别为该背景素材的xy图片名和遮挡方式。其中x和y分别为横纵坐标在0-12之间图片名则必须在上面的images中定义过。 其中x和y分别为左上角的像素坐标图片名则必须在全塔属性的images中定义过。
第四项为遮挡方式,定义如下: 第四项为遮挡方式,定义如下:
@ -118,17 +121,31 @@ images为一个数组代表当前层所有作为背景素材的图片信息
- 1该图片将全部画在前景层可以遮挡勇士。举例云彩等效果。 - 1该图片将全部画在前景层可以遮挡勇士。举例云彩等效果。
- 2该图片将上部分画在前景层下部分画在背景层。从而可以达到一个“自动调节遮挡的效果”。举例树、房子等等。 - 2该图片将上部分画在前景层下部分画在背景层。从而可以达到一个“自动调节遮挡的效果”。举例树、房子等等。
!> 如果写2的话请确保图片高度是32的倍数 !> 如果写2的话最好让xy和图片高度都是32的倍数
第五项为图片的帧数,可选。如果进行了设置,则会将该贴图视为帧动画,并切分成对应的帧数。
例如假设图片是100x100的且帧数设为4则视为四帧帧动画每次绘制的图片大小实际上是25x100。
关于楼层贴图和前景、背景层的层叠覆盖关系,默认是:**地板 - 背景贴图 - 背景图块 - 事件 - 勇士 - 前景贴图 - 前景图块**。
可以通过修改`libs/maps.js`的`drawMap`函数中下面三行的顺序来改变其覆盖关系。
``` js
// ----- 可以调整这三行的顺序来修改覆盖关系;同层画布上,后绘制的覆盖先绘制的
// ----- ui.js的drawThumbnail函数也需要对应进行修改。
// 绘制楼层贴图
core.maps.drawFloorImages(floorId, images);
// 绘制背景层图块
core.maps.drawBgFgMap(floorId, core.canvas.bg, "bg", true);
// 绘制前景层图块
core.maps.drawBgFgMap(floorId, core.canvas.fg, "fg", true);
```
楼层贴图可以被事件隐藏和显示,详见[隐藏贴图](event#hideFloorImg隐藏贴图)的写法。 楼层贴图可以被事件隐藏和显示,详见[隐藏贴图](event#hideFloorImg隐藏贴图)的写法。
**如果你需要让某些点不可通行(比如你建了个房子,墙壁和家具等位置不让通行),则需在`events`中指定`{"noPass": false}`,参见[自定义事件](event#自定义事件)的写法。** **如果要让贴图的某些点不可通行则可以使用noPass或者空气墙。**
``` js
"events": {
"x,y": {"noPass": true} // (x,y)点不可通行
}
```
### 使用便捷PS工具生成素材 ### 使用便捷PS工具生成素材

View File

@ -70,6 +70,9 @@ control.prototype.setRequestAnimationFrame = function () {
core.drawBlock(block, core.status.globalAnimateStatus % (block.event.animate||1)); core.drawBlock(block, core.status.globalAnimateStatus % (block.event.animate||1));
}); });
// Global floor images
core.maps.drawFloorImages(core.status.floorId, core.status.floorAnimateObjs||[], core.status.globalAnimateStatus);
// Global Autotile Animate // Global Autotile Animate
core.status.autotileAnimateObjs.blocks.forEach(function (block) { core.status.autotileAnimateObjs.blocks.forEach(function (block) {
// ------ 界面外的动画不绘制 // ------ 界面外的动画不绘制

View File

@ -197,6 +197,7 @@ function core() {
// 动画 // 动画
'globalAnimateObjs': [], 'globalAnimateObjs': [],
'floorAnimateObjs': [],
'boxAnimateObjs': [], 'boxAnimateObjs': [],
'autotileAnimateObjs': {"blocks": [], "map": null, "bgmap": null, "fgmap": null}, 'autotileAnimateObjs': {"blocks": [], "map": null, "bgmap": null, "fgmap": null},
"globalAnimateStatus": 0, "globalAnimateStatus": 0,

View File

@ -481,6 +481,61 @@ maps.prototype.generateGroundPattern = function (floorId) {
// core.material.groundPattern = '#000000'; // core.material.groundPattern = '#000000';
} }
maps.prototype.drawFloorImages = function (floorId, images, animate) {
var redraw = core.isset(animate);
if (!redraw) {
core.status.floorAnimateObjs = core.clone(images);
}
animate = animate || 0;
images.forEach(function (t) {
if (typeof t == 'string') t = [0,0,t];
var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2], frame = core.clamp(parseInt(t[4]), 1, 8);
if (redraw && frame == 1) return; // 不重绘
if (core.isset(dx) && core.isset(dy) &&
!core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) &&
core.isset(core.material.images.images[p])) {
var image = core.material.images.images[p];
var width = parseInt(image.width / frame), height = image.height;
var offsetX = animate%frame*width;
if (!t[3]) {
if (/.*\.gif/i.test(p) && main.mode=='play') {
if (redraw) return; // 忽略gif
core.dom.gif.innerHTML = "";
var gif = new Image();
gif.src = image.src;
gif.style.position = 'absolute';
gif.style.left = (dx*core.domStyle.scale)+"px";
gif.style.top = (dy*core.domStyle.scale)+"px";
gif.style.width = image.width*core.domStyle.scale+"px";
gif.style.height = image.height*core.domStyle.scale+"px";
core.dom.gif.appendChild(gif);
}
else {
if (redraw) core.clearMap('bg', dx, dy, width, height);
core.drawImage('bg', image, offsetX, 0, width, height, dx, dy, width, height);
}
}
else if (t[3]==1) {
if (redraw) core.clearMap('fg', dx, dy, width, height);
core.drawImage('fg', image, offsetX, 0, width, height, dx, dy, width, height);
}
else if (t[3]==2) {
if (redraw) {
core.clearMap('bg', dx, dy + height - 32, width, 32);
core.clearMap('fg', dx, dy, width, height-32);
}
core.drawImage('bg', image, offsetX, height-32, width, 32, dx, dy + height - 32, width, 32);
core.drawImage('fg', image, offsetX, 0, width, height-32, dx, dy, width, height-32);
}
}
});
}
////// 绘制某张地图 ////// ////// 绘制某张地图 //////
maps.prototype.drawMap = function (floorId, callback) { maps.prototype.drawMap = function (floorId, callback) {
floorId = floorId || core.status.floorId; floorId = floorId || core.status.floorId;
@ -511,41 +566,15 @@ maps.prototype.drawMap = function (floorId, callback) {
images = [[0, 0, images]]; images = [[0, 0, images]];
} }
} }
images.forEach(function (t) {
if (typeof t == 'string') t = [0,0,t];
var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2];
if (core.isset(dx) && core.isset(dy) &&
!core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) &&
core.isset(core.material.images.images[p])) {
var image = core.material.images.images[p];
if (!t[3]) {
if (/.*\.gif/i.test(p) && main.mode=='play') {
core.dom.gif.innerHTML = "";
var gif = new Image();
gif.src = image.src;
gif.style.position = 'absolute';
gif.style.left = (32*dx*core.domStyle.scale)+"px";
gif.style.top = (32*dy*core.domStyle.scale)+"px";
gif.style.width = image.width*core.domStyle.scale+"px";
gif.style.height = image.height*core.domStyle.scale+"px";
core.dom.gif.appendChild(gif);
}
else {
core.drawImage('bg', image, 32*dx, 32*dy, image.width, image.height);
}
}
else if (t[3]==1)
core.drawImage('fg', image, 32*dx, 32*dy, image.width, image.height);
else if (t[3]==2) {
core.drawImage('fg', image, 0, 0, image.width, image.height-32,
32*dx, 32*dy, image.width, image.height-32);
core.drawImage('bg', image, 0, image.height-32, image.width, 32,
32*dx, 32*dy + image.height - 32, image.width, 32);
}
}
});
// ----- 可以调整这三行的顺序来修改覆盖关系;同层画布上,后绘制的覆盖先绘制的
// ----- ui.js的drawThumbnail函数也需要对应进行修改。
// 绘制楼层贴图
core.maps.drawFloorImages(floorId, images);
// 绘制背景层图块
core.maps.drawBgFgMap(floorId, core.canvas.bg, "bg", true); core.maps.drawBgFgMap(floorId, core.canvas.bg, "bg", true);
// 绘制前景层图块
core.maps.drawBgFgMap(floorId, core.canvas.fg, "fg", true); core.maps.drawBgFgMap(floorId, core.canvas.fg, "fg", true);
} }
@ -1352,6 +1381,7 @@ maps.prototype.removeGlobalAnimate = function (x, y, all, name) {
core.status.globalAnimateStatus = 0; core.status.globalAnimateStatus = 0;
core.status.globalAnimateObjs = []; core.status.globalAnimateObjs = [];
core.status.autotileAnimateObjs = {"blocks": [], "map": null, "bgmap": null, "fgmap": null}; core.status.autotileAnimateObjs = {"blocks": [], "map": null, "bgmap": null, "fgmap": null};
core.status.floorAnimateObjs = [];
return; return;
} }

View File

@ -2423,6 +2423,7 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
tempCanvas.canvas.height = tempHeight; tempCanvas.canvas.height = tempHeight;
tempCanvas.clearRect(0, 0, tempWidth, tempHeight); tempCanvas.clearRect(0, 0, tempWidth, tempHeight);
// -------- 1. 绘制地板
var groundId = (core.status.maps||core.floors)[floorId].defaultGround || "ground"; var groundId = (core.status.maps||core.floors)[floorId].defaultGround || "ground";
var blockIcon = core.material.icons.terrains[groundId]; var blockIcon = core.material.icons.terrains[groundId];
for (var i = 0; i < mw; i++) { for (var i = 0; i < mw; i++) {
@ -2431,7 +2432,6 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
} }
} }
// background image
var images = []; var images = [];
if (core.isset((core.status.maps||core.floors)[floorId].images)) { if (core.isset((core.status.maps||core.floors)[floorId].images)) {
images = (core.status.maps||core.floors)[floorId].images; images = (core.status.maps||core.floors)[floorId].images;
@ -2439,25 +2439,27 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
images = [[0, 0, images]]; images = [[0, 0, images]];
} }
} }
// -------- 2. 绘制背景贴图
images.forEach(function (t) { images.forEach(function (t) {
if (typeof t == 'string') t = [0,0,t]; if (typeof t == 'string') t = [0,0,t];
var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2]; var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2], frame = core.clamp(parseInt(t[4]), 1, 8);
if (core.isset(dx) && core.isset(dy) && if (core.isset(dx) && core.isset(dy) &&
!core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) && !core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) &&
core.isset(core.material.images.images[p])) { core.isset(core.material.images.images[p])) {
var image = core.material.images.images[p]; var image = core.material.images.images[p];
var width = image.width / frame, height = image.height;
if (!t[3]) if (!t[3])
tempCanvas.drawImage(image, 32 * dx, 32 * dy, image.width, image.height); tempCanvas.drawImage(image, 0, 0, width, height, dx, dy, width, height);
else if (t[3]==2) else if (t[3]==2)
tempCanvas.drawImage(image, 0, image.height-32, image.width, 32, tempCanvas.drawImage(image, 0, height-32, width, 32, dx, dy + height - 32, width, 32);
32 * dx, 32 * dy + image.height - 32, image.width, 32);
} }
}) })
// background map // -------- 3. 绘制背景图块
core.maps.drawBgFgMap(floorId, tempCanvas, "bg"); core.maps.drawBgFgMap(floorId, tempCanvas, "bg");
// draw block // -------- 4. 绘制事件层
var mapArray = core.maps.getMapArray(blocks,mw,mh); var mapArray = core.maps.getMapArray(blocks,mw,mh);
for (var b in blocks) { for (var b in blocks) {
var block = blocks[b]; var block = blocks[b];
@ -2484,7 +2486,7 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
} }
} }
} }
// draw hero // -------- 5. 绘制勇士
if (core.isset(heroLoc)) { if (core.isset(heroLoc)) {
if (!core.isset(core.material.images.images[heroIcon])) if (!core.isset(core.material.images.images[heroIcon]))
heroIcon = "hero.png"; heroIcon = "hero.png";
@ -2493,25 +2495,25 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
tempCanvas.drawImage(core.material.images.images[heroIcon], icon.stop * 32, icon.loc * height, 32, height, 32*heroLoc.x, 32*heroLoc.y+32-height, 32, height); tempCanvas.drawImage(core.material.images.images[heroIcon], icon.stop * 32, icon.loc * height, 32, height, 32*heroLoc.x, 32*heroLoc.y+32-height, 32, height);
} }
// draw fg // -------- 6. 绘制前景贴图
images.forEach(function (t) { images.forEach(function (t) {
var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2]; var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2], frame = core.clamp(parseInt(t[3]), 1, 8);
if (core.isset(dx) && core.isset(dy) && if (core.isset(dx) && core.isset(dy) &&
!core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) && !core.hasFlag("floorimg_"+floorId+"_"+dx+"_"+dy) &&
core.isset(core.material.images.images[p])) { core.isset(core.material.images.images[p])) {
var image = core.material.images.images[p]; var image = core.material.images.images[p];
var width = image.width / frame, height = image.height;
if (t[3]==1) if (t[3]==1)
tempCanvas.drawImage(image, 32*dx, 32*dy, image.width, image.height); tempCanvas.drawImage(image, 0, 0, width, height, dx, dy, width, height);
else if (t[3]==2) else if (t[3]==2)
tempCanvas.drawImage(image, 0, 0, image.width, image.height-32, tempCanvas.drawImage(image, 0, 0, width, height-32, dx, dy, width, height-32);
32*dx, 32*dy, image.width, image.height-32);
} }
}) })
// foreground map // -------- 7. 绘制前景图块
core.maps.drawBgFgMap(floorId, tempCanvas, "fg"); core.maps.drawBgFgMap(floorId, tempCanvas, "fg");
// draw damage // -------- 8. 绘制显伤
if (core.status.event.id=='viewMaps' && (core.status.event.data||{}).damage) if (core.status.event.id=='viewMaps' && (core.status.event.data||{}).damage)
core.control.updateDamage(floorId, tempCanvas); core.control.updateDamage(floorId, tempCanvas);

View File

@ -354,7 +354,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"purify": 3, "purify": 3,
"hatred": 2, "hatred": 2,
"moveSpeed": 100, "moveSpeed": 100,
"animateSpeed": 300, "animateSpeed": 400,
"floorChangeTime": 800 "floorChangeTime": 800
}, },
"flags": { "flags": {

View File

@ -11,7 +11,7 @@ main.floors.sample1=
0, 0,
0, 0,
"bg.jpg", "bg.jpg",
false 0
] ]
], ],
"weather": [ "weather": [