commit
b04a4d2a78
12
README.md
12
README.md
@ -54,6 +54,18 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏!
|
||||
|
||||
## 更新说明
|
||||
|
||||
### 2018.9.28 V2.4.2
|
||||
|
||||
* [x] 允许导入tilesets直接使用,无需PS和注册
|
||||
* [x] tilesets的素材允许以矩形方式整体绘制
|
||||
* [x] Alt+0~9保存素材,Ctrl+0~9快速选中
|
||||
* [x] 增加了透明块的支持
|
||||
* [x] 装备允许按照百分比增加属性
|
||||
* [x] 多动画的同时播放
|
||||
* [x] 修复了打开存读档页面时闪屏的问题
|
||||
* [x] 修复了cannotMove仍然能轻按和瞬移的问题
|
||||
* [x] 所有已知Bug修复,部分代码重构和细节优化
|
||||
|
||||
### 2018.9.18 V2.4.1
|
||||
|
||||
* [x] 增加背景层和前景层的图块绘制,多层图块可叠加
|
||||
|
||||
@ -802,7 +802,7 @@ return code;
|
||||
*/;
|
||||
|
||||
viberate_s
|
||||
: '画面震动' '时间' Int '异步' Bool Newline
|
||||
: '画面震动' '时间' Int '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* viberate_s
|
||||
@ -817,7 +817,7 @@ return code;
|
||||
*/;
|
||||
|
||||
animate_s
|
||||
: '显示动画' IdString '位置' EvalString? '异步' Bool Newline
|
||||
: '显示动画' IdString '位置' EvalString? '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* animate_s
|
||||
@ -867,7 +867,7 @@ return code;
|
||||
*/;
|
||||
|
||||
animateImage_0_s
|
||||
: '图片淡入' EvalString '起点像素位置' 'x' PosString 'y' PosString '动画时间' Int '异步' Bool Newline
|
||||
: '图片淡入' EvalString '起点像素位置' 'x' PosString 'y' PosString '动画时间' Int '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* animateImage_0_s
|
||||
@ -881,7 +881,7 @@ return code;
|
||||
*/;
|
||||
|
||||
animateImage_1_s
|
||||
: '图片淡出' EvalString '起点像素位置' 'x' PosString 'y' PosString '动画时间' Int '异步' Bool Newline
|
||||
: '图片淡出' EvalString '起点像素位置' 'x' PosString 'y' PosString '动画时间' Int '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* animateImage_1_s
|
||||
@ -921,7 +921,7 @@ return code;
|
||||
|
||||
moveImage_0_s
|
||||
: '图片移动' EvalString '起点像素位置' 'x' PosString 'y' PosString BGNL
|
||||
'终点像素位置' 'x' PosString 'y' PosString '移动时间' Int '异步' Bool Newline
|
||||
'终点像素位置' 'x' PosString 'y' PosString '移动时间' Int '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* moveImage_0_s
|
||||
@ -935,7 +935,7 @@ return code;
|
||||
*/;
|
||||
|
||||
setFg_0_s
|
||||
: '更改画面色调' Number ',' Number ',' Number ',' Number '动画时间' Int? '异步' Bool Newline
|
||||
: '更改画面色调' Number ',' Number ',' Number ',' Number '动画时间' Int? '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* setFg_0_s
|
||||
@ -959,7 +959,7 @@ return code;
|
||||
*/;
|
||||
|
||||
setFg_1_s
|
||||
: '恢复画面色调' '动画时间' Int? '异步' Bool Newline
|
||||
: '恢复画面色调' '动画时间' Int? '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* setFg_1_s
|
||||
@ -1110,7 +1110,7 @@ return code;
|
||||
*/;
|
||||
|
||||
setVolume_s
|
||||
: '设置音量' Int '渐变时间' Int? '异步' Bool Newline
|
||||
: '设置音量' Int '渐变时间' Int? '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* setVolume_s
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
function editor() {
|
||||
this.version = "2.0";
|
||||
this.brushMod = "line";//["line","rectangle"]
|
||||
this.brushMod = "line";//["line","rectangle","tileset"]
|
||||
this.layerMod = "map";//["fgmap","map","bgmap"]
|
||||
this.isMobile = false;
|
||||
}
|
||||
@ -97,6 +97,12 @@ editor.prototype.idsInit = function (maps, icons) {
|
||||
var id = indexBlock.event.id;
|
||||
var indexId = indexBlock.id;
|
||||
var allCls = Object.keys(icons);
|
||||
if(i==17){
|
||||
editor.ids.push({'idnum': 17, 'id': id, 'images': 'terrains'});
|
||||
point++;
|
||||
editor.indexs[i].push(point);
|
||||
continue;
|
||||
}
|
||||
for (var j = 0; j < allCls.length; j++) {
|
||||
if (id in icons[allCls[j]]) {
|
||||
editor.ids.push({'idnum': indexId, 'id': id, 'images': allCls[j], 'y': icons[allCls[j]][id]});
|
||||
@ -114,7 +120,10 @@ editor.prototype.idsInit = function (maps, icons) {
|
||||
var img = core.material.images.tilesets[imgName];
|
||||
var width = Math.floor(img.width/32), height = Math.floor(img.height/32);
|
||||
if(img.width%32 || img.height%32){
|
||||
alert(imgName+'的长或宽不是32的整数倍, 请修改后刷新页面')
|
||||
alert(imgName+'的长或宽不是32的整数倍, 请修改后刷新页面');
|
||||
}
|
||||
if(img.width*img.height > 32*32*1000){
|
||||
alert(imgName+'上的图块数量超过了1000,请修改后刷新页面');
|
||||
}
|
||||
for (var id=startOffset; id<startOffset+width*height;id++) {
|
||||
var x = (id-startOffset)%width, y = parseInt((id-startOffset)/width);
|
||||
@ -329,9 +338,9 @@ editor.prototype.drawInitData = function (icons) {
|
||||
continue;
|
||||
}
|
||||
if (img == 'terrains') {
|
||||
editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + images[img].width) / 32, images[img].height + 32]
|
||||
editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + images[img].width) / 32, images[img].height + 32*2]
|
||||
sumWidth += images[img].width;
|
||||
maxHeight = Math.max(maxHeight, images[img].height + 32);
|
||||
maxHeight = Math.max(maxHeight, images[img].height + 32*2);
|
||||
continue;
|
||||
}
|
||||
editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + images[img].width) / 32, images[img].height];
|
||||
@ -357,7 +366,19 @@ editor.prototype.drawInitData = function (icons) {
|
||||
for (var ii = 0; ii < imgNames.length; ii++) {
|
||||
var img = imgNames[ii];
|
||||
if (img == 'terrains') {
|
||||
dc.drawImage(images[img], nowx, 32);
|
||||
(function(image,dc,nowx){
|
||||
if (image.complete) {
|
||||
dc.drawImage(image, nowx, 32);
|
||||
core.material.images.airwall = image;
|
||||
delete(editor.airwallImg);
|
||||
} else image.onload = function () {
|
||||
dc.drawImage(image, nowx, 32);
|
||||
core.material.images.airwall = image;
|
||||
delete(editor.airwallImg);
|
||||
editor.updateMap();
|
||||
}
|
||||
})(editor.airwallImg,dc,nowx);
|
||||
dc.drawImage(images[img], nowx, 32*2);
|
||||
nowx += images[img].width;
|
||||
continue;
|
||||
}
|
||||
@ -440,6 +461,31 @@ editor.prototype.buildMark = function(){
|
||||
}
|
||||
}
|
||||
|
||||
editor.prototype.setSelectBoxFromInfo=function(thisevent){
|
||||
var pos={x: 0, y: 0, images: "terrains"};
|
||||
var ysize = 32;
|
||||
if(thisevent==0){
|
||||
} else if (thisevent.idnum==17){
|
||||
pos.y=1;
|
||||
} else {
|
||||
pos.x=editor.widthsX[thisevent.images][1];
|
||||
pos.y=thisevent.y;
|
||||
if(thisevent.x)pos.x+=thisevent.x;
|
||||
if(thisevent.images=='terrains')pos.y+=2;
|
||||
ysize = thisevent.images.indexOf('48') === -1 ? 32 : 48;
|
||||
}
|
||||
var dataSelection = document.getElementById('dataSelection');
|
||||
dataSelection.style.left = pos.x * 32 + 'px';
|
||||
dataSelection.style.top = pos.y * ysize + 'px';
|
||||
dataSelection.style.height = ysize - 6 + 'px';
|
||||
setTimeout(function(){selectBox.isSelected = true;});
|
||||
editor.info = JSON.parse(JSON.stringify(thisevent));
|
||||
tip.infos = JSON.parse(JSON.stringify(thisevent));
|
||||
editor.pos=pos;
|
||||
editor_mode.onmode('nextChange');
|
||||
editor_mode.onmode('enemyitem');
|
||||
}
|
||||
|
||||
editor.prototype.listen = function () {
|
||||
|
||||
document.body.onmousedown = function (e) {
|
||||
@ -468,7 +514,7 @@ editor.prototype.listen = function () {
|
||||
});
|
||||
|
||||
var unselect=true;
|
||||
for(var ii=0,thisId;thisId=['edit','tip','brushMod','brushMod2','layerMod','layerMod2','layerMod3','viewportButtons'][ii];ii++){
|
||||
for(var ii=0,thisId;thisId=['edit','tip','brushMod','brushMod2','brushMod3','layerMod','layerMod2','layerMod3','viewportButtons'][ii];ii++){
|
||||
if (clickpath.indexOf(thisId) !== -1){
|
||||
unselect=false;
|
||||
break;
|
||||
@ -625,7 +671,7 @@ editor.prototype.listen = function () {
|
||||
e.stopPropagation();
|
||||
if (stepPostfix && stepPostfix.length) {
|
||||
preMapData = JSON.parse(JSON.stringify({map:editor.map,fgmap:editor.fgmap,bgmap:editor.bgmap}));
|
||||
if(editor.brushMod==='rectangle'){
|
||||
if(editor.brushMod!=='line'){
|
||||
var x0=stepPostfix[0].x;
|
||||
var y0=stepPostfix[0].y;
|
||||
var x1=stepPostfix[stepPostfix.length-1].x;
|
||||
@ -633,8 +679,8 @@ editor.prototype.listen = function () {
|
||||
if(x0>x1){x0^=x1;x1^=x0;x0^=x1;}//swap
|
||||
if(y0>y1){y0^=y1;y1^=y0;y0^=y1;}//swap
|
||||
stepPostfix=[];
|
||||
for(var ii=x0;ii<=x1;ii++){
|
||||
for(var jj=y0;jj<=y1;jj++){
|
||||
for(var jj=y0;jj<=y1;jj++){
|
||||
for(var ii=x0;ii<=x1;ii++){
|
||||
stepPostfix.push({x:ii,y:jj})
|
||||
}
|
||||
}
|
||||
@ -646,8 +692,22 @@ editor.prototype.listen = function () {
|
||||
if (editor.layerMod!='map' && editor.info.images && editor.info.images.indexOf('48')!==-1){
|
||||
printe('前景/背景不支持48的图块');
|
||||
} else {
|
||||
for (var ii = 0; ii < stepPostfix.length; ii++)
|
||||
if(editor.brushMod==='tileset' && core.tilesets.indexOf(editor.info.images)!==-1){
|
||||
var imgWidth=~~(core.material.images.tilesets[editor.info.images].width/32);
|
||||
var x0=stepPostfix[0].x;
|
||||
var y0=stepPostfix[0].y;
|
||||
var idnum=editor.info.idnum;
|
||||
for (var ii = 0; ii < stepPostfix.length; ii++){
|
||||
if(stepPostfix[ii].y!=y0){
|
||||
y0++;
|
||||
idnum+=imgWidth;
|
||||
}
|
||||
editor[editor.layerMod][stepPostfix[ii].y][stepPostfix[ii].x] = editor.ids[editor.indexs[idnum+stepPostfix[ii].x-x0]];
|
||||
}
|
||||
} else {
|
||||
for (var ii = 0; ii < stepPostfix.length; ii++)
|
||||
editor[editor.layerMod][stepPostfix[ii].y][stepPostfix[ii].x] = editor.info;
|
||||
}
|
||||
}
|
||||
// console.log(editor.map);
|
||||
editor.updateMap();
|
||||
@ -710,9 +770,12 @@ editor.prototype.listen = function () {
|
||||
info: {}
|
||||
};
|
||||
var reDo = null;
|
||||
var shortcut = core.getLocalStorage('shortcut',{48: 0, 49: 0, 50: 0, 51: 0, 52: 0, 53: 0, 54: 0, 55: 0, 56: 0, 57: 0});
|
||||
document.body.onkeydown = function (e) {
|
||||
// 禁止快捷键的默认行为
|
||||
if (e.ctrlKey && ( e.keyCode == 90 || e.keyCode == 89 ))
|
||||
if (e.ctrlKey && [89, 90, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1)
|
||||
e.preventDefault();
|
||||
if (e.altKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1)
|
||||
e.preventDefault();
|
||||
//Ctrl+z 撤销上一步undo
|
||||
if (e.keyCode == 90 && e.ctrlKey && preMapData && currDrawData.pos.length && selectBox.isSelected) {
|
||||
@ -757,6 +820,18 @@ editor.prototype.listen = function () {
|
||||
editor.changeFloor(toId);
|
||||
}
|
||||
}
|
||||
//ctrl + 0~9 切换到快捷图块
|
||||
if (e.ctrlKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1){
|
||||
editor.setSelectBoxFromInfo(JSON.parse(JSON.stringify(shortcut[e.keyCode]||0)));
|
||||
}
|
||||
//alt + 0~9 改变快捷图块
|
||||
if (e.altKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1){
|
||||
var infoToSave = JSON.stringify(editor.info||0);
|
||||
if(infoToSave==JSON.stringify({}))return;
|
||||
shortcut[e.keyCode]=JSON.parse(infoToSave);
|
||||
printf('已保存该快捷图块, ctrl + '+(e.keyCode-48)+' 使用.')
|
||||
core.setLocalStorage('shortcut',shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
var dataSelection = document.getElementById('dataSelection');
|
||||
@ -803,9 +878,11 @@ editor.prototype.listen = function () {
|
||||
if (pos.x == 0 && pos.y == 0) {
|
||||
// editor.info={idnum:0, id:'empty','images':'清除块', 'y':0};
|
||||
editor.info = 0;
|
||||
} else if(pos.x == 0 && pos.y == 1){
|
||||
editor.info = editor.ids[editor.indexs[17]];
|
||||
} else {
|
||||
if (hasOwnProp(autotiles, pos.images)) editor.info = {'images': pos.images, 'y': 0};
|
||||
else if (pos.images == 'terrains') editor.info = {'images': pos.images, 'y': pos.y - 1};
|
||||
else if (pos.images == 'terrains') editor.info = {'images': pos.images, 'y': pos.y - 2};
|
||||
else if (core.tilesets.indexOf(pos.images)!=-1) editor.info = {'images': pos.images, 'y': pos.y, 'x': pos.x-editor.widthsX[spriter][1]};
|
||||
else editor.info = {'images': pos.images, 'y': pos.y};
|
||||
|
||||
@ -874,28 +951,7 @@ editor.prototype.listen = function () {
|
||||
editor.hideMidMenu();
|
||||
e.stopPropagation();
|
||||
var thisevent = editor.map[editor.pos.y][editor.pos.x];
|
||||
var pos={x: 0, y: 0, images: "terrains"};
|
||||
var ysize = 32;
|
||||
if(thisevent==0){
|
||||
//选中清除块
|
||||
editor.info = 0;
|
||||
editor.pos=pos;
|
||||
} else {
|
||||
var ids=editor.indexs[thisevent.idnum];
|
||||
ids=ids[0]?ids[0]:ids;
|
||||
editor.info=editor.ids[ids];
|
||||
pos.x=editor.widthsX[thisevent.images][1];
|
||||
pos.y=editor.info.y;
|
||||
if(thisevent.images=='terrains')pos.y++;
|
||||
ysize = thisevent.images.indexOf('48') === -1 ? 32 : 48;
|
||||
}
|
||||
setTimeout(function(){selectBox.isSelected = true;});
|
||||
dataSelection.style.left = pos.x * 32 + 'px';
|
||||
dataSelection.style.top = pos.y * ysize + 'px';
|
||||
dataSelection.style.height = ysize - 6 + 'px';
|
||||
tip.infos = JSON.parse(JSON.stringify(editor.info));
|
||||
editor_mode.onmode('nextChange');
|
||||
editor_mode.onmode('enemyitem');
|
||||
editor.setSelectBoxFromInfo(thisevent);
|
||||
}
|
||||
|
||||
var fields = Object.keys(editor.file.comment._data.floors._data.loc._data);
|
||||
@ -1013,6 +1069,11 @@ editor.prototype.listen = function () {
|
||||
editor.brushMod=brushMod2.value;
|
||||
}
|
||||
|
||||
var brushMod3=document.getElementById('brushMod3');
|
||||
if(brushMod3)brushMod3.onchange=function(){
|
||||
editor.brushMod=brushMod3.value;
|
||||
}
|
||||
|
||||
var layerMod=document.getElementById('layerMod');
|
||||
layerMod.onchange=function(){
|
||||
editor.layerMod=layerMod.value;
|
||||
|
||||
@ -315,7 +315,7 @@ editor_mode = function (editor) {
|
||||
//editor.info=editor.ids[editor.indexs[201]];
|
||||
if (!core.isset(editor.info)) return;
|
||||
|
||||
if (Object.keys(editor.info).length !== 0) editor_mode.info = editor.info;//避免editor.info被清空导致无法获得是物品还是怪物
|
||||
if (Object.keys(editor.info).length !== 0 && editor.info.idnum!=17) editor_mode.info = editor.info;//避免editor.info被清空导致无法获得是物品还是怪物
|
||||
|
||||
if (!core.isset(editor_mode.info.id)) {
|
||||
// document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML = '';
|
||||
|
||||
@ -241,6 +241,7 @@ var tip = new Vue({
|
||||
isAutotile: false,
|
||||
isSelectedBlock: false,
|
||||
isClearBlock: false,
|
||||
isAirwall: false,
|
||||
geneMapSuccess: false,
|
||||
timer: null,
|
||||
msgs: [ //分别编号1,2,3,4,5,6,7,8,9,10;奇数警告,偶数成功
|
||||
@ -264,12 +265,17 @@ var tip = new Vue({
|
||||
infos: {
|
||||
handler: function (val, oldval) {
|
||||
this.isClearBlock = false;
|
||||
this.isAirwall = false;
|
||||
if (typeof(val) != 'undefined') {
|
||||
if (val == 0) {
|
||||
this.isClearBlock = true;
|
||||
return;
|
||||
}
|
||||
if ('id' in val) {
|
||||
if (val.idnum == 17) {
|
||||
this.isAirwall = true;
|
||||
return;
|
||||
}
|
||||
this.hasId = true;
|
||||
} else {
|
||||
this.hasId = false;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# V2.0版本介绍
|
||||
|
||||
?> 目前版本**v2.4.1**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.4.2**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
目前样板已经更新到V2.0版本以上,本章将对V2.0的一些内容进行介绍。
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 附录: API列表
|
||||
|
||||
?> 目前版本**v2.4.1**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.4.2**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
**这里只列出所有可能会被造塔者用到的常用API,更多的有关内容请在代码内进行查询。**
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 元件说明
|
||||
|
||||
?> 目前版本**v2.4.1**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.4.2**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 事件
|
||||
|
||||
?> 目前版本**v2.4.1**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.4.2**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
本章内将对样板所支持的事件进行介绍。
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# HTML5 魔塔样板说明文档
|
||||
|
||||
?> 目前版本**v2.4.1**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.4.2**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
众所周知,魔塔的趋势是向移动端发展,贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中,NekoRPG有着比较大的局限性,游戏感较差,更是完全没法在iOS上运行。而一些APP的魔塔虽然可用,但是必须要下载安装,对于Android和iOS还必须开发不同的版本,非常麻烦。
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 个性化
|
||||
|
||||
?> 目前版本**v2.4.1**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.4.2**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。
|
||||
|
||||
@ -261,6 +261,8 @@ ID必须由数字字母下划线组成,数字在1000以内,且均不能和
|
||||
|
||||
除此之外,额外素材在游戏中的使用和正式素材都是一致的,也能在前景或背景图层绘制。
|
||||
|
||||
额外素材可以使用“tileset贴图”的方式进行绘制,一次绘制一个矩形区域。
|
||||
|
||||
## 自定义道具效果
|
||||
|
||||
本节中将继续介绍如何自己编辑一个道具的效果。
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 快速上手
|
||||
|
||||
?> 目前版本**v2.4.1**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.4.2**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!
|
||||
|
||||
@ -50,6 +50,8 @@
|
||||
|
||||
绘制地图时可以右键弹出菜单,移动图块和事件。
|
||||
|
||||
从V2.4.2开始,可以使用`Alt+0~9`对一个图块素材快速保存,`Ctrl+0~9`来快速选用。
|
||||
|
||||
### 从RMXP导入已有的地图
|
||||
|
||||
如果我们想复刻一个现有的,已经被RMXP所制作的塔,也有很便捷的方式,那就是用到我们的“地图生成器”。
|
||||
|
||||
@ -234,6 +234,7 @@
|
||||
<div id="tip" v-cloak>
|
||||
<div v-if="isSelectedBlock">
|
||||
<p v-if="isClearBlock" class="infoText">当前选择为清除块,可擦除地图上块</p>
|
||||
<p v-if="isAirwall" class="infoText">当前选择为空气墙, 在编辑器中可视, 在游戏中隐藏的墙, 用来配合前景/背景的贴图</p>
|
||||
<div v-else>
|
||||
<p v-if="hasId">图块编号:<span class="infoText">{{ infos['idnum'] }}</span></p>
|
||||
<p v-if="hasId">图块ID:<span class="infoText">{{ infos['id'] }}</span></p>
|
||||
@ -276,6 +277,7 @@
|
||||
<select id="brushMod" style="clear:right">
|
||||
<option value="line">画线</option>
|
||||
<option value="rectangle">画矩形</option>
|
||||
<option value="tileset">tileset贴图</option>
|
||||
</select>
|
||||
<select id="layerMod" style="float:left;margin-right:3px">
|
||||
<option value="bgmap">背景层</option>
|
||||
@ -449,6 +451,8 @@ if (location.protocol.indexOf("http")!=0) {
|
||||
|
||||
var useCompress = main.useCompress;
|
||||
main.useCompress = false;
|
||||
editor.airwallImg = new Image();
|
||||
editor.airwallImg.src = './project/images/airwall.png';
|
||||
main.init('editor', function () {
|
||||
editor.init(function () {
|
||||
editor.useCompress = useCompress;
|
||||
|
||||
@ -221,6 +221,7 @@
|
||||
<div id="tip" v-cloak>
|
||||
<div v-if="isSelectedBlock">
|
||||
<p v-if="isClearBlock" class="infoText">当前选择为清除块,可擦除地图上块</p>
|
||||
<p v-else-if="isAirwall" class="infoText">当前选择为空气墙, 在编辑器中可视, 在游戏中隐藏的墙, 用来配合前景/背景的贴图</p>
|
||||
<div v-else>
|
||||
<p v-if="hasId">图块编号:<span class="infoText">{{ infos['idnum'] }}</span></p>
|
||||
<p v-if="hasId">图块ID:<span class="infoText">{{ infos['id'] }}</span></p>
|
||||
@ -245,9 +246,11 @@
|
||||
<option value="functions">脚本编辑</option>
|
||||
<option value="appendpic">追加素材</option>
|
||||
</select>
|
||||
<span style="font-size: 12px; margin-left: 5px">
|
||||
<br/>
|
||||
<span style="font-size: 12px;">
|
||||
<input type="radio" id="brushMod" name="brushMod" value="line" checked="checked" />画线
|
||||
<input type="radio" id="brushMod2" name="brushMod" value="rectangle" />画矩形
|
||||
<input type="radio" id="brushMod3" name="brushMod" value="tileset" />tileset贴图
|
||||
</span>
|
||||
<br/>
|
||||
<span style="font-size: 12px">
|
||||
@ -432,6 +435,8 @@ if (location.protocol.indexOf("http")!=0) {
|
||||
<script>
|
||||
var useCompress = main.useCompress;
|
||||
main.useCompress = false;
|
||||
editor.airwallImg = new Image();
|
||||
editor.airwallImg.src = './project/images/airwall.png';
|
||||
main.init('editor', function () {
|
||||
editor.init(function () {
|
||||
editor.useCompress = useCompress;
|
||||
|
||||
@ -56,6 +56,7 @@ control.prototype.setRequestAnimationFrame = function () {
|
||||
|
||||
core.animateFrame.globalTime = core.animateFrame.globalTime||timestamp;
|
||||
core.animateFrame.boxTime = core.animateFrame.boxTime||timestamp;
|
||||
core.animateFrame.animateTime = core.animateFrame.animateTime||timestamp;
|
||||
core.animateFrame.moveTime = core.animateFrame.moveTime||timestamp;
|
||||
core.animateFrame.weather.time = core.animateFrame.weather.time||timestamp;
|
||||
|
||||
@ -88,6 +89,18 @@ control.prototype.setRequestAnimationFrame = function () {
|
||||
core.animateFrame.boxTime = timestamp;
|
||||
}
|
||||
|
||||
// Animate
|
||||
if (timestamp-core.animateFrame.animateTime>50 && core.isset(core.status.animateObjs) && core.status.animateObjs.length>0) {
|
||||
core.clearMap('animate');
|
||||
core.status.animateObjs = core.status.animateObjs.filter(function (obj) {
|
||||
return obj.index < obj.animate.frames.length;
|
||||
})
|
||||
core.status.animateObjs.forEach(function (obj) {
|
||||
core.maps.drawAnimateFrame(obj.animate, obj.centerX, obj.centerY, obj.index++);
|
||||
})
|
||||
core.animateFrame.animateTime = timestamp;
|
||||
}
|
||||
|
||||
// Hero move
|
||||
if (timestamp-core.animateFrame.moveTime>16 && core.isset(core.status.heroMoving) && core.status.heroMoving>0) {
|
||||
var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'), direction = core.getHeroLoc('direction');
|
||||
|
||||
@ -31,6 +31,7 @@ function core() {
|
||||
'globalAnimate': false,
|
||||
'globalTime': null,
|
||||
'boxTime': null,
|
||||
'animateTime': null,
|
||||
'moveTime': null,
|
||||
'speed': null,
|
||||
'weather': {
|
||||
@ -157,6 +158,7 @@ function core() {
|
||||
// 动画
|
||||
'globalAnimateObjs': [],
|
||||
'boxAnimateObjs': [],
|
||||
'animateObjs': [],
|
||||
};
|
||||
this.status = {};
|
||||
}
|
||||
|
||||
112
libs/maps.js
112
libs/maps.js
@ -59,7 +59,10 @@ maps.prototype.initBlock = function (x, y, id) {
|
||||
var tmp = {'x': x, 'y': y, 'id': id};
|
||||
if (disable!=null) tmp.disable = disable;
|
||||
|
||||
if (id in this.blocksInfo) tmp.event = JSON.parse(JSON.stringify(this.blocksInfo[id]));
|
||||
if (id==17) {
|
||||
tmp.event = {"cls": "terrains", "id": "airwall", "noPass": true};
|
||||
}
|
||||
else if (id in this.blocksInfo) tmp.event = JSON.parse(JSON.stringify(this.blocksInfo[id]));
|
||||
else {
|
||||
var tilesetOffset = core.icons.getTilesetOffset(id);
|
||||
if (tilesetOffset != null) {
|
||||
@ -338,18 +341,27 @@ maps.prototype.canMoveDirectly = function (destX,destY) {
|
||||
}
|
||||
|
||||
maps.prototype.drawBlock = function (block, animate, dx, dy) {
|
||||
// none:空地
|
||||
if (block.event.id=='none') return;
|
||||
|
||||
var cls = block.event.cls, height = block.event.height || 32;
|
||||
|
||||
var image, x, y;
|
||||
|
||||
if (cls == 'tileset') {
|
||||
var offset = core.icons.getTilesetOffset(block.event.id);
|
||||
if (offset == null) return;
|
||||
image = core.material.images.tilesets[offset.image];
|
||||
x = offset.x;
|
||||
y = offset.y;
|
||||
height = 32;
|
||||
}
|
||||
else if (cls == 'autotile') return;
|
||||
// 空气墙的单独处理
|
||||
else if (block.id==17) {
|
||||
if (!core.isset(core.material.images.airwall)) return;
|
||||
image = core.material.images.airwall;
|
||||
x = y = 0;
|
||||
}
|
||||
else {
|
||||
image = core.material.images[cls];
|
||||
x = (animate||0)%(block.event.animate||1);
|
||||
@ -402,7 +414,12 @@ maps.prototype.drawBgFgMap = function (floorId, canvas, name) {
|
||||
else if (cls == 'tileset') {
|
||||
var offset = core.icons.getTilesetOffset(id);
|
||||
if (offset!=null) {
|
||||
canvas.drawImage(core.material.images.tilesets[offset.image], 32*offset.x, 32*offset.y, 32, 32, 32*block.x, 32*block.y, 32, 32);
|
||||
canvas.drawImage(core.material.images.tilesets[offset.image], 32*offset.x, 32*offset.y, 32, 32, 32*x, 32*y, 32, 32);
|
||||
}
|
||||
}
|
||||
else if (arr[y][x]==17) {
|
||||
if (core.isset(core.material.images.airwall)) {
|
||||
canvas.drawImage(core.material.images.airwall, 32*x, 32*y);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -492,7 +509,7 @@ maps.prototype.drawMap = function (mapName, callback) {
|
||||
if (block.event.cls == 'autotile') {
|
||||
core.drawAutotile(core.canvas.event, mapArray, block, 32, 0, 0);
|
||||
}
|
||||
else if (block.event.id!='none') {
|
||||
else {
|
||||
core.drawBlock(block);
|
||||
core.addGlobalAnimate(block);
|
||||
}
|
||||
@ -717,6 +734,11 @@ maps.prototype.moveBlock = function(x,y,steps,time,keep,callback) {
|
||||
if (core.isset(callback)) callback();
|
||||
return;
|
||||
}
|
||||
// 空气墙;忽略事件
|
||||
else if (block.id==17) {
|
||||
if (core.isset(callback)) callback();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
image = core.material.images[block.event.cls];
|
||||
bx = 0;
|
||||
@ -841,6 +863,11 @@ maps.prototype.jumpBlock = function(sx,sy,ex,ey,time,keep,callback) {
|
||||
if (core.isset(callback)) callback();
|
||||
return;
|
||||
}
|
||||
// 空气墙;忽略事件
|
||||
else if (block.id==17) {
|
||||
if (core.isset(callback)) callback();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
image = core.material.images[block.event.cls];
|
||||
bx = 0;
|
||||
@ -948,6 +975,8 @@ maps.prototype.animateBlock = function (loc,type,time,callback) {
|
||||
else if (block.event.cls == 'autotile') {
|
||||
return;
|
||||
}
|
||||
// 空气墙,忽略事件
|
||||
else if (block.id==17) return;
|
||||
else {
|
||||
image = core.material.images[block.event.cls];
|
||||
bx = 0;
|
||||
@ -1180,6 +1209,35 @@ maps.prototype.drawBoxAnimate = function () {
|
||||
}
|
||||
}
|
||||
|
||||
////// 绘制动画的某一帧 //////
|
||||
maps.prototype.drawAnimateFrame = function (animate, centerX, centerY, index) {
|
||||
var frame = animate.frames[index];
|
||||
var ratio = animate.ratio;
|
||||
frame.forEach(function (t) {
|
||||
var image = animate.images[t.index];
|
||||
if (!core.isset(image)) return;
|
||||
var realWidth = image.width * ratio * t.zoom / 100;
|
||||
var realHeight = image.height * ratio * t.zoom / 100;
|
||||
core.setAlpha('animate', t.opacity / 255);
|
||||
|
||||
var cx = centerX+t.x, cy=centerY+t.y;
|
||||
|
||||
if (!t.mirror && !t.angle) {
|
||||
core.canvas.animate.drawImage(image, cx-realWidth/2 - core.bigmap.offsetX, cy-realHeight/2 - core.bigmap.offsetY, realWidth, realHeight);
|
||||
}
|
||||
else {
|
||||
core.saveCanvas('animate');
|
||||
core.canvas.animate.translate(cx,cy);
|
||||
if (t.angle)
|
||||
core.canvas.animate.rotate(-t.angle*Math.PI/180);
|
||||
if (t.mirror)
|
||||
core.canvas.animate.scale(-1,1);
|
||||
core.canvas.animate.drawImage(image, -realWidth/2 - core.bigmap.offsetX, -realHeight/2 - core.bigmap.offsetY, realWidth, realHeight);
|
||||
core.loadCanvas('animate');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
////// 绘制动画 //////
|
||||
maps.prototype.drawAnimate = function (name, x, y, callback) {
|
||||
|
||||
@ -1195,49 +1253,22 @@ maps.prototype.drawAnimate = function (name, x, y, callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 清空animate层
|
||||
clearInterval(core.interval.animateInterval);
|
||||
core.clearMap('animate');
|
||||
|
||||
// 开始绘制
|
||||
var animate = core.material.animates[name];
|
||||
var ratio = animate.ratio;
|
||||
var centerX = 32*x+16, centerY = 32*y+16;
|
||||
var index=0;
|
||||
|
||||
var animate = core.material.animates[name], centerX = 32*x+16, centerY = 32*y+16;
|
||||
// 播放音效
|
||||
core.playSound(animate.se);
|
||||
|
||||
var draw = function (index) {
|
||||
core.clearMap('animate');
|
||||
|
||||
var frame = animate.frames[index];
|
||||
frame.forEach(function (t) {
|
||||
var image = animate.images[t.index];
|
||||
if (!core.isset(image)) return;
|
||||
var realWidth = image.width * ratio * t.zoom / 100;
|
||||
var realHeight = image.height * ratio * t.zoom / 100;
|
||||
core.setAlpha('animate', t.opacity / 255);
|
||||
|
||||
var cx = centerX+t.x, cy=centerY+t.y;
|
||||
|
||||
if (!t.mirror && !t.angle) {
|
||||
core.canvas.animate.drawImage(image, cx-realWidth/2 - core.bigmap.offsetX, cy-realHeight/2 - core.bigmap.offsetY, realWidth, realHeight);
|
||||
}
|
||||
else {
|
||||
core.saveCanvas('animate');
|
||||
core.canvas.animate.translate(cx,cy);
|
||||
if (t.angle)
|
||||
core.canvas.animate.rotate(-t.angle*Math.PI/180);
|
||||
if (t.mirror)
|
||||
core.canvas.animate.scale(-1,1);
|
||||
core.canvas.animate.drawImage(image, -realWidth/2 - core.bigmap.offsetX, -realHeight/2 - core.bigmap.offsetY, realWidth, realHeight);
|
||||
core.loadCanvas('animate');
|
||||
}
|
||||
})
|
||||
// 异步绘制:使用requestAnimationFrame进行绘制
|
||||
if (!core.isset(callback)) {
|
||||
core.status.animateObjs.push({"animate": animate, "centerX": centerX, "centerY": centerY, "index": 0});
|
||||
return;
|
||||
}
|
||||
|
||||
draw(index++);
|
||||
var index=0;
|
||||
core.clearMap('animate');
|
||||
core.maps.drawAnimateFrame(animate, centerX, centerY, index++);
|
||||
|
||||
core.interval.animateInterval = setInterval(function (t) {
|
||||
if (index == animate.frames.length) {
|
||||
@ -1247,7 +1278,8 @@ maps.prototype.drawAnimate = function (name, x, y, callback) {
|
||||
if (core.isset(callback)) callback();
|
||||
return;
|
||||
}
|
||||
draw(index++);
|
||||
core.clearMap('animate');
|
||||
core.maps.drawAnimateFrame(animate, centerX, centerY, index++);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
|
||||
15
libs/ui.js
15
libs/ui.js
@ -2056,14 +2056,17 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, cente
|
||||
tempCanvas.drawImage(core.material.images.tilesets[offset.image], 32*offset.x, 32*offset.y, 32, 32, 32*block.x, 32*block.y, 32, 32);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (block.event.id!='none') {
|
||||
var blockIcon = core.material.icons[block.event.cls][block.event.id];
|
||||
var blockImage = core.material.images[block.event.cls];
|
||||
var height = block.event.height || 32;
|
||||
tempCanvas.drawImage(blockImage, 0, blockIcon * height, 32, height, 32*block.x, 32*block.y + 32 - height, 32, height);
|
||||
else if (block.id==17) {
|
||||
if (core.isset(core.material.images.airwall)) {
|
||||
tempCanvas.drawImage(core.material.images.airwall, 32*block.x, 32*block.y);
|
||||
}
|
||||
}
|
||||
else if (block.event.id!='none') {
|
||||
var blockIcon = core.material.icons[block.event.cls][block.event.id];
|
||||
var blockImage = core.material.images[block.event.cls];
|
||||
var height = block.event.height || 32;
|
||||
tempCanvas.drawImage(blockImage, 0, blockIcon * height, 32, height, 32*block.x, 32*block.y + 32 - height, 32, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
// draw hero
|
||||
|
||||
2
main.js
2
main.js
@ -2,7 +2,7 @@ function main() {
|
||||
|
||||
//------------------------ 用户修改内容 ------------------------//
|
||||
|
||||
this.version = "2.4.1"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。
|
||||
this.version = "2.4.2"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。
|
||||
|
||||
this.useCompress = false; // 是否使用压缩文件
|
||||
// 当你即将发布你的塔时,请使用“JS代码压缩工具”将所有js代码进行压缩,然后将这里的useCompress改为true。
|
||||
|
||||
@ -61,7 +61,7 @@ data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
|
||||
"firstData": {
|
||||
"title": "魔塔样板",
|
||||
"name": "template",
|
||||
"version": "Ver 2.4.1",
|
||||
"version": "Ver 2.4.2",
|
||||
"floorId": "sample0",
|
||||
"hero": {
|
||||
"name": "阳光",
|
||||
|
||||
BIN
project/images/airwall.png
Normal file
BIN
project/images/airwall.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
16
更新说明.txt
16
更新说明.txt
@ -1,4 +1,18 @@
|
||||
HTML5魔塔样板V2.4.1
|
||||
HTML5魔塔样板V2.4.2
|
||||
|
||||
允许导入tilesets直接使用,无需PS和注册
|
||||
tilesets的素材允许以矩形方式整体绘制
|
||||
Alt+0~9保存素材,Ctrl+0~9快速选中
|
||||
增加了透明块的支持
|
||||
装备允许按照百分比增加属性
|
||||
多动画的同时播放
|
||||
修复了打开存读档页面时闪屏的问题
|
||||
修复了cannotMove仍然能轻按和瞬移的问题
|
||||
所有已知Bug修复,部分代码重构和细节优化
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
HTML5魔塔样板V2.4.1
|
||||
|
||||
增加背景层和前景层的图块绘制,多层图块可叠加
|
||||
背景层/前景层图块的显示、隐藏、修改等事件
|
||||
|
||||
Loading…
Reference in New Issue
Block a user