Merge remote-tracking branch 'refs/remotes/origin/dev-2.0-blockly-20180214' into dev-2.0-appendPic-20180218

This commit is contained in:
YouWei Zhao 2018-02-20 20:52:35 +08:00
commit 11fb1b19c1
11 changed files with 188 additions and 65 deletions

View File

@ -51,6 +51,9 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
* [x] 改变图块setBlock事件
* [x] 同一个点的多事件处理(做法详见文档)。
* [x] 增加新地图后可以接档而不用重新开始。
* [x] 增加可以接收用户输入的事件(type:input)。
* [x] 可以同时show/hide多个事件。
* [x] 现在可以支持滑冰和推箱子事件了。
* [x] 地图中每个块的可通行方向控制(悬崖效果)。
* [x] 动画支持带旋转和翻转的帧。

View File

@ -187,6 +187,7 @@ action
| win_s
| lose_s
| if_s
| input_s
| choices_s
| function_s
| pass_s
@ -279,17 +280,23 @@ return code;
*/
show_s
: '显示事件' 'x' Int ',' 'y' Int '楼层' IdString? '动画时间' Int? Newline
: '显示事件' 'x' EvalString ',' 'y' EvalString '楼层' IdString? '动画时间' Int? Newline
;
/* show_s
tooltip : show: 将一个禁用事件启用,楼层和动画时间可不填
tooltip : show: 将禁用事件启用,楼层和动画时间可不填,xy可用逗号分隔表示多个点
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=show-%e5%b0%86%e4%b8%80%e4%b8%aa%e7%a6%81%e7%94%a8%e4%ba%8b%e4%bb%b6%e5%90%af%e7%94%a8
default : [0,0,"",500]
colour : this.eventColor
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
Int_2 = Int_2 ?(', "time": '+Int_2):'';
var code = '{"type": "show", "loc": ['+Int_0+','+Int_1+']'+IdString_0+''+Int_2+'},\n';
var pattern = /^(\d|1[0-2])(,\d|1[0-2])*$/;
if(!pattern.test(EvalString_0) || !pattern.test(EvalString_1))throw new Error('坐标格式错误,请右键点击帮助查看格式');
EvalString_0=EvalString_0.split(',');
EvalString_1=EvalString_1.split(',');
if(EvalString_0.length!==EvalString_1.length)throw new Error('坐标格式错误,请右键点击帮助查看格式');
for(var ii=0;ii<EvalString_0.length;ii++)EvalString_0[ii]='['+EvalString_0[ii]+','+EvalString_1[ii]+']';
Int_0 = Int_0 ?(', "time": '+Int_0):'';
var code = '{"type": "show", "loc": ['+EvalString_0.join(',')+']'+IdString_0+''+Int_0+'},\n';
return code;
*/
@ -298,13 +305,19 @@ hide_s
;
/* hide_s
tooltip : hide: 将一个启用事件禁用,所有参数均可不填,代表禁用事件自身
tooltip : hide: 将一个启用事件禁用,所有参数均可不填,代表禁用事件自身,xy可用逗号分隔表示多个点
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=hide-%e5%b0%86%e4%b8%80%e4%b8%aa%e5%90%af%e7%94%a8%e4%ba%8b%e4%bb%b6%e7%a6%81%e7%94%a8
default : ["","","",500]
colour : this.eventColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
floorstr = ', "loc": ['+EvalString_0+','+EvalString_1+']';
var pattern = /^(\d|1[0-2])(,\d|1[0-2])*$/;
if(!pattern.test(EvalString_0) || !pattern.test(EvalString_1))throw new Error('坐标格式错误,请右键点击帮助查看格式');
EvalString_0=EvalString_0.split(',');
EvalString_1=EvalString_1.split(',');
if(EvalString_0.length!==EvalString_1.length)throw new Error('坐标格式错误,请右键点击帮助查看格式');
for(var ii=0;ii<EvalString_0.length;ii++)EvalString_0[ii]='['+EvalString_0[ii]+','+EvalString_1[ii]+']';
floorstr = ', "loc": ['+EvalString_0.join(',')+']';
}
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
Int_0 = Int_0 ?(', "time": '+Int_0):'';
@ -690,6 +703,19 @@ var code = '{"type": "lose", "reason": "'+EvalString_0+'"},\n';
return code;
*/
input_s
: '接受用户输入,提示' ':' EvalString Newline
;
/* input_s
tooltip : input接受用户输入, 事件只能接受非负整数输入, 所有非法的输入将全部变成0
helpUrl : https://ckcz123.github.io/mota-js/#/event?id=input%ef%bc%9a%e6%8e%a5%e5%8f%97%e7%94%a8%e6%88%b7%e8%be%93%e5%85%a5
default : ["请输入一个数"]
colour : this.dataColor
var code = '{"type": "input", "text": "'+EvalString_0+'"},\n';
return code;
*/
if_s
: '如果' ':' expression BGNL? Newline action+ '否则' ':' BGNL? Newline action+ BEND Newline
;
@ -1109,13 +1135,27 @@ ActionParser.prototype.parseAction = function() {
this.parseAction();
break;
case "show": // 显示
if (typeof data.loc[0] == 'number' && typeof data.loc[1] == 'number')
data.loc = [data.loc];
var x_str=[],y_str=[];
data.loc.forEach(function (t) {
x_str.push(t[0]);
y_str.push(t[1]);
})
this.next = MotaActionBlocks['show_s'].xmlText([
data.loc[0],data.loc[1],data.floorId||'',data.time||0,this.next]);
x_str.join(','),y_str.join(','),data.floorId||'',data.time||0,this.next]);
break;
case "hide": // 消失
data.loc=data.loc||[];
if (typeof data.loc[0] == 'number' && typeof data.loc[1] == 'number')
data.loc = [data.loc];
var x_str=[],y_str=[];
data.loc.forEach(function (t) {
x_str.push(t[0]);
y_str.push(t[1]);
})
this.next = MotaActionBlocks['hide_s'].xmlText([
data.loc[0]||'',data.loc[1]||'',data.floorId||'',data.time||0,this.next]);
x_str.join(','),y_str.join(','),data.floorId||'',data.time||0,this.next]);
break;
case "setBlock": // 设置图块
data.loc=data.loc||[];
@ -1214,6 +1254,10 @@ ActionParser.prototype.parseAction = function() {
MotaActionBlocks['evalString_e'].xmlText([data.value]),
this.next]);
break;
case "input":
this.next = MotaActionBlocks['input_s'].xmlText([
data.text,this.next]);
break;
case "if": // 条件判断
this.next = MotaActionBlocks['if_s'].xmlText([
MotaActionBlocks['evalString_e'].xmlText([data.condition]),

View File

@ -70,6 +70,7 @@ initscript=String.raw`
]),
'<label text="数据相关"></label>',
MotaActionBlocks['setValue_s'].xmlText(),
MotaActionBlocks['input_s'].xmlText(),
MotaActionBlocks['update_s'].xmlText(),
MotaActionBlocks['moveHero_s'].xmlText(),
MotaActionBlocks['changeFloor_s'].xmlText(),
@ -154,12 +155,7 @@ initscript=String.raw`
}
]
},'event'),
'<label text="获取用户输入的字符串"></label>',
MotaActionFunctions.actionParser.parseList([
{"type": "setValue", "name": "flag:inputMsg", "value": "请输入密码"},
{"type": "function", "function": "function(){core.setFlag('input',prompt(core.getFlag('inputMsg','请输入字符串'),'xxx')||'')}"},
{"type": "if", "condition": 'flag:input == "123456"',"true": [],"false": []},
]),
],
}
var toolboxgap = '<sep gap="5"></sep>'

View File

@ -332,13 +332,14 @@ value是一个表达式将通过这个表达式计算出的结果赋值给nam
``` js
"x,y": [ // 实际执行的事件列表
{"type": "show", "loc": [3,6], "floorId": "MT1", "time": 500 } // 启用MT1层[3,6]位置事件动画500ms
{"type": "show", "loc": [3,6], "time": 500 } // 如果启用目标是当前层则可以省略floorId项
{"type": "show", "loc": [3,6]} // 如果不指定动画时间则立刻显示否则动画效果逐渐显示time为动画时间
{"type": "show", "loc": [3,6], "floorId": "MT1", "time": 500}, // 启用MT1层[3,6]位置事件动画500ms
{"type": "show", "loc": [3,6], "time": 500}, // 如果启用目标是当前层则可以省略floorId项
{"type": "show", "loc": [3,6]}, // 如果不指定动画时间则立刻显示否则动画效果逐渐显示time为动画时间
{"type": "show", "loc": [[3,6],[2,9],[1,2]], "time": 500} // 我们也可以同时动画显示多个点。
]
```
show事件需要用loc指定目标点的坐标剩下有两个参数floorId和time
show事件需要用loc指定目标点的坐标,可以简单的写[x,y]代表一个点,也可以写个二维数组[[x1,y1],[x2,y2],...]来同时显示多个点
floorId为目标点的楼层如果不是该楼层的事件比如4楼小偷开2楼的门则是必须的如果是当前楼层可以忽略不写。
@ -352,6 +353,8 @@ time为动画效果时间如果指定了某个大于0的数则会以动画
其参数和show也完全相同loc指定事件的位置floorId为楼层同层可忽略time指定的话事件会以动画效果从有到无慢慢消失。
loc同样可以简单的写[x,y]表示单个点,或二维数组[[x1,y1],[x2,y2],...]表示多个点。
但是和show事件有所区别的是loc选项也可以忽略如果忽略loc则使当前事件禁用。即使禁用当前事件也不会立刻结束当前正在进行的而是仍然会依次将列表中剩下的事件执行完
请注意,一次性事件必须要加 `{"type":"hide"}`,尤其是例如走到某个点,触发对话或机关门(陷阱)这种,否则每次都会重复触发。
@ -360,11 +363,13 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
``` js
"x,y": [ // 实际执行的事件列表
{"type": "hide", "loc": [3,6], "floorId": "MT1", "time": 500 } // 禁用MT1层[3,6]位置事件动画500ms
{"type": "hide", "loc": [3,6], "time": 500 } // 如果启用目标是当前层则可以省略floorId项
{"type": "hide", "loc": [3,6] } // 如果不指定动画时间则立刻消失否则动画效果逐渐消失time为动画时间
{"type": "hide", "time": 500 } // 如果不指定loc选项则默认为当前点 例如这个就是500ms消失当前对话的NPC
{"type": "hide" } // 无动画将当前事件禁用,常常适用于某个空地点(触发陷阱事件、触发机关门这种)
{"type": "hide", "loc": [3,6], "floorId": "MT1", "time": 500}, // 禁用MT1层[3,6]位置事件动画500ms
{"type": "hide", "loc": [3,6], "time": 500}, // 如果启用目标是当前层则可以省略floorId项
{"type": "hide", "loc": [3,6]}, // 如果不指定动画时间则立刻消失否则动画效果逐渐消失time为动画时间
{"type": "hide", "loc": [[3,6],[2,9],[1,2]], "time": 500}, // 也可以同时指定多个点消失
{"type": "hide", "time": 500}, // 如果不指定loc选项则默认为当前点 例如这个就是500ms消失当前对话的NPC
{"type": "hide"}, // 无动画将当前事件禁用,常常适用于某个空地点(触发陷阱事件、触发机关门这种)
]
```
@ -749,6 +754,25 @@ move完毕后移动的NPC/怪物一定会消失只不过可以通过immediate
该事件会显示失败页面,并重新开始游戏。
### input接受用户输入
使用`{"type": "input"}`可以接受用户的输入。
``` js
"x,y": [ // 实际执行的事件列表
{"type": "input", "text": "请输入一个数"}, // 显示一个弹窗让用户输入内容
"你刚刚输入的数是${flag:input}" // 输入结果将被赋值为flag:input
]
```
text为提示文字可以在这里给输入提示文字。这里同样可以使用${ }来计算表达式的值。
当执行input事件时将显示一个弹窗并提示用户输入一个内容。
!> 该事件只能接受非负整数输入,所有非法的输入将全部变成`0`。例如用户在输入框内输入“你好”或者-3都将实际得到0。
输入得到的结果将被赋值给flag:input可以供后续if来进行判断。
### if: 条件判断
使用`{"type": "if"}`可以对条件进行判断,根据判断结果将会选择不同的分支执行。

View File

@ -1982,7 +1982,7 @@ core.prototype.canMoveHero = function(x,y,direction,floorId) {
'down': {'x': 0, 'y': 1},
'right': {'x': 1, 'y': 0}
};
var nextBlock = core.getBlock(x+scan[direction].x,y+scan[direction].y);
var nextBlock = core.getBlock(x+scan[direction].x,y+scan[direction].y,floorId);
if (nextBlock!=null){
nextId = nextBlock.block.event.id;
// 遇到单向箭头处理
@ -2978,7 +2978,7 @@ core.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) {
}
////// 显示/隐藏某个块时的动画效果 //////
core.prototype.animateBlock = function (x,y,type,time,callback) {
core.prototype.animateBlock = function (loc,type,time,callback) {
if (type!='hide') type='show';
core.status.replay.animate=true;
@ -2986,31 +2986,46 @@ core.prototype.animateBlock = function (x,y,type,time,callback) {
core.saveCanvas('animate');
core.clearMap('animate', 0, 0, 416, 416);
var block = core.getBlock(x,y,core.status.floorId,false);
if (block==null) {// 不存在
if (typeof loc[0] == 'number' && typeof loc[1] == 'number')
loc = [loc];
var list = [];
loc.forEach(function (t) {
var block = core.getBlock(t[0],t[1],core.status.floorId,false);
if (block==null) return;
block=block.block;
list.push({
'x': t[0], 'y': t[1],
'blockIcon': core.material.icons[block.event.cls][block.event.id],
'blockImage': core.material.images[block.event.cls]
})
})
if (list.length==0) {
if (core.isset(callback)) callback();
return;
}
// 清空UI
//core.clearMap('ui', 0, 0, 416, 416);
//core.setAlpha('ui', 1.0);
block=block.block;
blockIcon = core.material.icons[block.event.cls][block.event.id];
blockImage = core.material.images[block.event.cls];
var draw = function () {
list.forEach(function (t) {
core.canvas.animate.drawImage(t.blockImage, 0, t.blockIcon * 32, 32, 32, t.x * 32, t.y * 32, 32, 32);
})
}
var opacityVal = 0;
if (type=='hide') opacityVal=1;
core.setOpacity('animate', opacityVal);
core.canvas.animate.drawImage(blockImage, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
draw();
var animate = window.setInterval(function () {
if (type=='show') opacityVal += 0.1;
else opacityVal -= 0.1;
core.setOpacity('animate', opacityVal);
core.clearMap('animate',block.x * 32, block.y * 32, 32, 32);
core.canvas.animate.drawImage(blockImage, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
core.clearMap('animate',0,0,416,416);
// core.canvas.animate.drawImage(blockImage, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
draw();
if (opacityVal >=1 || opacityVal<=0) {
clearInterval(animate);
core.loadCanvas('animate');

View File

@ -320,26 +320,33 @@ events.prototype.doAction = function() {
core.events.doAction();
break;
case "show": // 显示
if (typeof data.loc[0] == 'number' && typeof data.loc[1] == 'number')
data.loc = [data.loc];
if (core.isset(data.time) && data.time>0 && (!core.isset(data.floorId) || data.floorId==core.status.floorId)) {
core.animateBlock(data.loc[0],data.loc[1],'show', data.time, function () {
core.showBlock(data.loc[0],data.loc[1],data.floorId);
core.animateBlock(data.loc,'show', data.time, function () {
data.loc.forEach(function (t) {
core.showBlock(t[0],t[1],data.floorId)
})
core.events.doAction();
});
}
else {
core.showBlock(data.loc[0],data.loc[1],data.floorId)
data.loc.forEach(function (t) {
core.showBlock(t[0],t[1],data.floorId)
})
this.doAction();
}
break;
case "hide": // 消失
var toX=x, toY=y, toId=core.status.floorId;
if (core.isset(data.loc)) {
toX=data.loc[0]; toY=data.loc[1];
}
if (core.isset(data.floorId)) toId=data.floorId;
core.removeBlock(toX,toY,toId)
if (core.isset(data.time) && data.time>0 && toId==core.status.floorId) {
core.animateBlock(toX,toY,'hide',data.time, function () {
if (!core.isset(data.loc))
data.loc = [x,y];
if (typeof data.loc[0] == 'number' && typeof data.loc[1] == 'number')
data.loc = [data.loc];
data.loc.forEach(function (t) {
core.removeBlock(t[0],t[1],data.floorId);
})
if (core.isset(data.time) && data.time>0 && (!core.isset(data.floorId) || data.floorId==core.status.floorId)) {
core.animateBlock(data.loc,'hide',data.time, function () {
core.events.doAction();
});
}
@ -531,6 +538,30 @@ events.prototype.doAction = function() {
this.doAction();
}
break;
case "input":
{
var value;
if (core.status.replay.replaying) {
var action = core.status.replay.toReplay.shift();
if (action.indexOf("input:")==0 ) {
value=parseInt(action.substring(6));
}
else {
core.stopReplay();
core.drawTip("录像文件出错");
return;
}
}
else {
value = prompt(core.replaceText(data.text));
}
value = Math.abs(parseInt(value)||0);
core.status.route.push("input:"+value);
core.setFlag("input", value);
this.doAction();
}
break;
case "if": // 条件判断
if (core.calValue(data.condition))
core.events.insertAction(data["true"])

View File

@ -174,9 +174,9 @@ maps.prototype.save = function(maps, floorId) {
maps.prototype.load = function (data, floorId) {
if (floorId == undefined) {
var map = {};
for (var id in data) {
map[id] = this.load(data, id);
}
core.floorIds.forEach(function (id) {
map[id] = core.maps.loadFloor(id, data[id]);
})
return map;
}
return this.loadFloor(floorId, data[floorId]);

View File

@ -18,13 +18,16 @@ comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
'def': '防御力',
'money': '金币',
'experience': '经验',
'special': '特殊属性\n\n0:无,1:先攻,2:魔攻,3:坚固,4:2连击,\n5:3连击,6:n连击,7:破甲,8:反击,9:净化,\n10:模仿,11:吸血,12:中毒,13:衰弱,14:诅咒,\n15:领域,16:夹击,17:仇恨,18:阻击,19:自爆,\n20:无敌\n\n多个属性例如用[1,4,11]表示先攻2连击吸血\n模仿怪的攻防设为0就好\n$leaf(true)$end',
'special': '特殊属性\n\n0:无,1:先攻,2:魔攻,3:坚固,4:2连击,\n5:3连击,6:n连击,7:破甲,8:反击,9:净化,\n10:模仿,11:吸血,12:中毒,13:衰弱,14:诅咒,\n15:领域,16:夹击,17:仇恨,18:阻击,19:自爆,\n20:无敌,21:退化,22:固伤\n\n多个属性例如用[1,4,11]表示先攻2连击吸血\n模仿怪的攻防设为0就好\n$leaf(true)$end',
'value': '特殊属性的数值\n领域怪需要加value表示领域伤害的数值\n吸血怪需要在后面添加value代表吸血比例',
'zoneSquare': '领域怪zoneSquare代表是否九宫格伤害',
'range': 'range可选代表领域伤害的范围不加默认为1\n$range((thiseval==~~thiseval && thiseval>0)||thiseval==null)$end',
'bomb':' 加入 "bomb": false 代表该怪物不可被炸弹或圣锤炸掉\n$select({\"values\":[true,false]})$end',
'point': 'point可以在打败怪物后进行加点详见文档说明\n$range((thiseval==~~thiseval && thiseval>0)||thiseval==null)$end',
'n': '多连击需要在后面指定n代表是几连击\n$range((thiseval==~~thiseval && thiseval>0)||thiseval==null)$end',
'atkValue':'退化时勇士下降的攻击力点数\n$range(thiseval==~~thiseval||thiseval==null)$end',
'defValue':'退化时勇士下降的防御力点数\n$range(thiseval==~~thiseval||thiseval==null)$end',
'damage':'战前扣血的点数\n$range(thiseval==~~thiseval||thiseval==null)$end'
},
"enemys_template" : {'name': '新敌人', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'experience': 0, 'special': 0},
"floors" : {

View File

@ -53,18 +53,12 @@ main.floors.sample1 =
{"type": "show", "loc": [1,5], "time": 1500}, // 显示红衣魔王动画效果1500ms
{"type": "sleep", "time": 500}, // 等待500ms
"\t[redKing]欢迎来到魔塔,你是第一百位挑战者。\n若你能打败我所有的手下我就与你一对一的决斗。\n现在你必须接受我的安排。",
{"type": "show", "loc": [1,6], "time": 500}, // 显示四个白衣武士每个动画效果500ms
{"type": "show", "loc": [0,7], "time": 500},
{"type": "show", "loc": [1,8], "time": 500},
{"type": "show", "loc": [2,7], "time": 500},
{"type": "show", "loc": [[1,6],[0,7],[1,8],[2,7]], "time": 500}, // 显示四个白衣武士每个动画效果500ms
"\t[hero]什么?",
{"type": "playSound", "name": "attack.ogg"}, // 播放战斗音频
{"type": "setValue", "name": "status:atk", "value": "status:atk/10"}, // 勇士的攻防变成原来的十分之一
{"type": "setValue", "name": "status:def", "value": "status:def/10"},
{"type": "hide", "loc": [1,6]}, // 直接隐藏四个白衣武士,没有动画效果
{"type": "hide", "loc": [0,7]},
{"type": "hide", "loc": [2,7]},
{"type": "hide", "loc": [1,8]},
{"type": "hide", "loc": [[1,6],[0,7],[2,7],[1,8]]}, // 直接隐藏四个白衣武士,没有动画效果
{"type": "hide", "loc": [1,5], "time": 500}, // 隐藏红衣魔王动画500ms
{"type": "hide"}, // 隐藏本事件
{"type": "setFg", "color": [0,0,0], "time": 1250}, // 渐变为白色
@ -259,7 +253,8 @@ main.floors.sample1 =
"12,11": [ // 自定义事件的老人
"\t[老人,womanMagician]使用 {\"type\":\"function\"} 可以写自定义的JS脚本。\n本塔支持的所有主要API会在doc文档内给出。",
"\t[老人,womanMagician]例如这个例子:即将弹出一个输入窗口,然后会将你的输入结果直接加到你的攻击力上。",
{"type": "function", "function": `function() { // 自己写JS脚本并执行
/*
{"type": "function", "function": function() { // 自己写JS脚本并执行
// 注意一下prompt对于录像是如何处理的
var value;
@ -289,7 +284,19 @@ main.floors.sample1 =
"操作成功,攻击+"+value // 对话框提示
]);
}
}`},
}},
*/
{"type": "input", "text": "请输入你要加攻击力的数值:"},
{"type": "if", "condition": "flag:input>0",
"true": [
{"type": "setValue", "name": "status:atk", "value": "status:atk+flag:input"},
{"type": "tip", "text": "操作成功,攻击+${flag:input}"},
"操作成功,攻击+${flag:input}"
],
"false": [
]
},
"\t[老人,womanMagician]具体可参见样板中本事件的写法。"
]
},

View File

@ -176,10 +176,7 @@ main.floors.sample2 =
{"type": "changePos", "direction": "up"},
{"type": "playSound", "name": "item.ogg"},
"\t[blackMagician]出来吧!禁忌——紫电凶杀阵!",
{"type": "show", "loc": [4,3], "time": 500}, // 依次显示四个角的法师
{"type": "show", "loc": [4,6], "time": 500}, // 依次显示四个角的法师
{"type": "show", "loc": [8,6], "time": 500}, // 依次显示四个角的法师
{"type": "show", "loc": [8,3], "time": 500}, // 依次显示四个角的法师
{"type": "show", "loc": [[4,3],[4,6],[8,6],[8,3]], "time": 500}, // 依次显示四个角的法师
{"type": "sleep", "time": 500},
"\t[blackMagician]感受绝望吧!冥顽不化的蠢货!",
/*

View File

@ -2,6 +2,9 @@
改变图块setBlock事件
同一个点的多事件处理(做法详见文档)。
增加新地图后可以接档而不用重新开始。
增加可以接收用户输入的事件(type:input)。
可以同时show/hide多个事件。
现在可以支持滑冰和推箱子事件了。
地图中每个块的可通行方向控制(悬崖效果)。
动画支持带旋转和翻转的帧。