diff --git a/_server/blockly/MotaAction.g4 b/_server/blockly/MotaAction.g4
index 6fecc669..c4c827c9 100644
--- a/_server/blockly/MotaAction.g4
+++ b/_server/blockly/MotaAction.g4
@@ -183,6 +183,18 @@ var code = '[\n'+action_0+']\n';
return code;
*/;
+//eachArrive 事件编辑器入口之一
+eachArrive_m
+ : '每次到达楼层' BGNL? Newline action+ BEND
+
+
+/* eachArrive_m
+tooltip : 每次到达楼层
+helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%8f%91%e7%9a%84%e8%87%aa%e5%ae%9a%e4%b9%89%e4%ba%8b%e4%bb%b6
+var code = '[\n'+action_0+']\n';
+return code;
+*/;
+
//changeFloor 事件编辑器入口之一
changeFloor_m
: '楼梯, 传送门' BGNL? Newline Floor_List IdString? Stair_List 'x' Number ',' 'y' Number '朝向' DirectionEx_List '动画时间' Int? '允许穿透' Bool BEND
@@ -235,6 +247,7 @@ action
| updateEnemys_s
| sleep_s
| wait_s
+ | waitAsync_s
| battle_s
| openDoor_s
| changeFloor_s
@@ -245,7 +258,7 @@ action
| follow_s
| unfollow_s
| animate_s
- | viberate_s
+ | vibrate_s
| showImage_0_s
| showImage_1_s
| animateImage_0_s
@@ -470,13 +483,13 @@ return code;
show_s
- : '显示事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' Int? Newline
+ : '显示事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' Int? '不等待执行完毕' Bool? Newline
/* show_s
tooltip : show: 将禁用事件启用,楼层和动画时间可不填,xy可用逗号分隔表示多个点
helpUrl : https://h5mota.com/games/template/docs/#/event?id=show%EF%BC%9A%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 : ["","","",500]
+default : ["","","",500,false]
colour : this.eventColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
@@ -497,18 +510,19 @@ if (EvalString_0 && EvalString_1) {
}
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
Int_0 = Int_0 ?(', "time": '+Int_0):'';
-var code = '{"type": "show"'+floorstr+IdString_0+''+Int_0+'},\n';
+Bool_0 = Bool_0 ?', "async": true':'';
+var code = '{"type": "show"'+floorstr+IdString_0+''+Int_0+Bool_0+'},\n';
return code;
*/;
hide_s
- : '隐藏事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' Int? Newline
+ : '隐藏事件' 'x' EvalString? ',' 'y' EvalString? '楼层' IdString? '动画时间' Int? '不等待执行完毕' Bool? Newline
/* hide_s
tooltip : hide: 将一个启用事件禁用,所有参数均可不填,代表禁用事件自身,xy可用逗号分隔表示多个点
helpUrl : https://h5mota.com/games/template/docs/#/event?id=hide%EF%BC%9A%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]
+default : ["","","",500,false]
colour : this.eventColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
@@ -529,7 +543,8 @@ if (EvalString_0 && EvalString_1) {
}
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
Int_0 = Int_0 ?(', "time": '+Int_0):'';
-var code = '{"type": "hide"'+floorstr+IdString_0+''+Int_0+'},\n';
+Bool_0 = Bool_0 ?', "async": true':'';
+var code = '{"type": "hide"'+floorstr+IdString_0+''+Int_0+Bool_0+'},\n';
return code;
*/;
@@ -819,6 +834,7 @@ var code = '{"type": "sleep", "time": '+Int_0+'},\n';
return code;
*/;
+
battle_s
: '强制战斗' IdString Newline
@@ -949,18 +965,18 @@ var code = '{"type": "unfollow"' + EvalString_0 + '},\n';
return code;
*/;
-viberate_s
+vibrate_s
: '画面震动' '时间' Int '不等待执行完毕' Bool Newline
-/* viberate_s
-tooltip : viberate: 画面震动
-helpUrl : https://h5mota.com/games/template/docs/#/event?id=viberate%ef%bc%9a%e7%94%bb%e9%9d%a2%e9%9c%87%e5%8a%a8
+/* vibrate_s
+tooltip : vibrate: 画面震动
+helpUrl : https://h5mota.com/games/template/docs/#/event?id=vibrate%ef%bc%9a%e7%94%bb%e9%9d%a2%e9%9c%87%e5%8a%a8
default : [2000,false]
colour : this.soundColor
Int_0 = Int_0 ?(', "time": '+Int_0):'';
var async = Bool_0?', "async": true':''
-var code = '{"type": "viberate"' + Int_0 + async + '},\n';
+var code = '{"type": "vibrate"' + Int_0 + async + '},\n';
return code;
*/;
@@ -1459,6 +1475,20 @@ var code = '{"type": "wait"},\n';
return code;
*/;
+
+waitAsync_s
+ : '等待所有异步事件执行完毕'
+
+
+/* waitAsync_s
+tooltip : waitAsync: 等待所有异步事件执行完毕
+helpUrl : https://h5mota.com/games/template/docs/#/event?id=waitAsync%ef%bc%9a%e7%ad%89%e5%be%85%e6%89%80%e6%9c%89%e5%bc%82%e6%ad%a5%e4%ba%8b%e4%bb%b6%e6%89%a7%e8%a1%8c%e5%ae%8c%e6%af%95
+colour : this.soundColor
+var code = '{"type": "waitAsync"},\n';
+return code;
+*/;
+
+
function_s
: '自定义JS脚本' BGNL? Newline RawEvalString Newline BEND Newline
@@ -1644,8 +1674,8 @@ Global_Attribute_List
/*Global_Attribute_List ['font','statusLeftBackground','statusTopBackground', 'toolsBackground', 'borderColor', 'statusBarColor', 'hardLabelColor', 'floorChangingBackground', 'floorChangingTextColor']*/;
Global_Value_List
- : '血网伤害'|'中毒伤害'|'衰弱效果'|'红宝石效果'|'蓝宝石效果'|'绿宝石效果'|'红血瓶效果'|'蓝血瓶效果'|'黄血瓶效果'|'绿血瓶效果'|'破甲比例'|'反击比例'|'净化比例'|'仇恨增加值'|'最大合法HP'|'动画时间'
- /*Global_Value_List ['lavaDamage','poisonDamage','weakValue', 'redJewel', 'blueJewel', 'greenJewel', 'redPotion', 'bluePotion', 'yellowPotion', 'greenPotion', 'breakArmor', 'counterAttack', 'purify', 'hatred', 'maxValidHp', 'animateSpeed']*/;
+ : '血网伤害'|'中毒伤害'|'衰弱效果'|'红宝石效果'|'蓝宝石效果'|'绿宝石效果'|'红血瓶效果'|'蓝血瓶效果'|'黄血瓶效果'|'绿血瓶效果'|'破甲比例'|'反击比例'|'净化比例'|'仇恨增加值'|'行走速度'|'动画时间'
+ /*Global_Value_List ['lavaDamage','poisonDamage','weakValue', 'redJewel', 'blueJewel', 'greenJewel', 'redPotion', 'bluePotion', 'yellowPotion', 'greenPotion', 'breakArmor', 'counterAttack', 'purify', 'hatred', 'moveSpeed', 'animateSpeed']*/;
Bool: 'TRUE'
| 'FALSE'
@@ -1901,7 +1931,7 @@ ActionParser.prototype.parseAction = function() {
y_str.push(t[1]);
})
this.next = MotaActionBlocks['show_s'].xmlText([
- x_str.join(','),y_str.join(','),data.floorId||'',data.time||0,this.next]);
+ x_str.join(','),y_str.join(','),data.floorId||'',data.time||0,data.async||false,this.next]);
break;
case "hide": // 消失
data.loc=data.loc||[];
@@ -1913,7 +1943,7 @@ ActionParser.prototype.parseAction = function() {
y_str.push(t[1]);
})
this.next = MotaActionBlocks['hide_s'].xmlText([
- x_str.join(','),y_str.join(','),data.floorId||'',data.time||0,this.next]);
+ x_str.join(','),y_str.join(','),data.floorId||'',data.time||0,data.async||false,this.next]);
break;
case "setBlock": // 设置图块
data.loc=data.loc||['',''];
@@ -2023,8 +2053,8 @@ ActionParser.prototype.parseAction = function() {
this.next = MotaActionBlocks['animate_s'].xmlText([
data.name,animate_loc,data.async||false,this.next]);
break;
- case "viberate": // 画面震动
- this.next = MotaActionBlocks['viberate_s'].xmlText([data.time||0, data.async||false, this.next]);
+ case "vibrate": // 画面震动
+ this.next = MotaActionBlocks['vibrate_s'].xmlText([data.time||0, data.async||false, this.next]);
break;
case "showImage": // 显示图片
if(this.isset(data.name)){
@@ -2221,6 +2251,10 @@ ActionParser.prototype.parseAction = function() {
this.next = MotaActionBlocks['wait_s'].xmlText([
this.next]);
break;
+ case "waitAsync": // 等待所有异步事件执行完毕
+ this.next = MotaActionBlocks['waitAsync_s'].xmlText([
+ this.next]);
+ break;
case "revisit": // 立刻重新执行该事件
this.next = MotaActionBlocks['revisit_s'].xmlText([
this.next]);
diff --git a/_server/comment.js b/_server/comment.js
index 2cdc9364..2b7fcc33 100644
--- a/_server/comment.js
+++ b/_server/comment.js
@@ -330,6 +330,12 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_event": "firstArrive",
"_data": "第一次到该楼层触发的事件,可以双击进入事件编辑器。"
},
+ "eachArrive": {
+ "_leaf": true,
+ "_type": "event",
+ "_event": "eachArrive",
+ "_data": "每次到该楼层触发的事件,可以双击进入事件编辑器;该事件会比firstArrive先执行。"
+ },
"parallelDo": {
"_leaf": true,
"_type": "textarea",
diff --git a/_server/data.comment.js b/_server/data.comment.js
index 681abdf8..300a5fc0 100644
--- a/_server/data.comment.js
+++ b/_server/data.comment.js
@@ -276,6 +276,13 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
}
}
},
+ "startCanvas": {
+ "_leaf": true,
+ "_type": "event",
+ "_event": "firstArrive",
+ "_range": "thiseval==null || thiseval instanceof Array",
+ "_data": "标题界面事件化,可以使用事件流的形式来绘制开始界面等。\n需要开启startUsingCanvas这个开关。\n详见文档-个性化-标题界面事件化。"
+ },
"startText": {
"_leaf": true,
"_type": "event",
@@ -373,11 +380,10 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_type": "textarea",
"_data": "仇恨属性中,每杀死一个怪物获得的仇恨值"
},
- "maxValidHp": {
+ "moveSpeed": {
"_leaf": true,
"_type": "textarea",
- "_range": "thiseval==null||thiseval>0",
- "_data": "最大合法生命值;如果此项不为null且用户通关血量超过本值,则视为作弊,不上传成绩"
+ "_data": "行走速度,即勇士每走一格的时间,一般100比较合适"
},
"animateSpeed": {
"_leaf": true,
@@ -560,6 +566,12 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
"_bool": "bool",
"_data": "是否循环计算临界;如果此项为true则使用循环法(而不是回合数计算法)来算临界"
},
+ "startUsingCanvas": {
+ "_leaf": true,
+ "_type": "checkbox",
+ "_bool": "bool",
+ "_data": "是否开始菜单canvas化;如果此项为true,则将使用canvas来绘制开始菜单"
+ },
"startDirectly": {
"_leaf": true,
"_type": "checkbox",
diff --git a/_server/editor.js b/_server/editor.js
index 7b418d1d..3da2558c 100644
--- a/_server/editor.js
+++ b/_server/editor.js
@@ -11,6 +11,7 @@ function editor() {
if (string.indexOf(substring) > -1){
message = 'Script Error: See Browser Console for Detail';
} else {
+ if (url) url = url.substring(url.lastIndexOf('/')+1);
message = [
'Message: ' + msg,
'URL: ' + url,
@@ -183,6 +184,7 @@ editor.prototype.mapInit = function () {
editor.currentFloorData.fgmap = editor.fgmap;
editor.currentFloorData.bgmap = editor.bgmap;
editor.currentFloorData.firstArrive = [];
+ editor.currentFloorData.eachArrive = [];
editor.currentFloorData.events = {};
editor.currentFloorData.changeFloor = {};
editor.currentFloorData.afterBattle = {};
diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js
index f36cb09e..c16c0a12 100644
--- a/_server/editor_blockly.js
+++ b/_server/editor_blockly.js
@@ -52,6 +52,7 @@ editor_blockly = function () {
MotaActionBlocks['afterGetItem_m'].xmlText(),
MotaActionBlocks['afterOpenDoor_m'].xmlText(),
MotaActionBlocks['firstArrive_m'].xmlText(),
+ MotaActionBlocks['eachArrive_m'].xmlText(),
MotaActionBlocks['level_m'].xmlText(),
],
'显示文字':[
@@ -131,7 +132,8 @@ editor_blockly = function () {
'特效/声音':[
MotaActionBlocks['sleep_s'].xmlText(),
MotaActionBlocks['wait_s'].xmlText(),
- MotaActionBlocks['viberate_s'].xmlText(),
+ MotaActionBlocks['waitAsync_s'].xmlText(),
+ MotaActionBlocks['vibrate_s'].xmlText(),
MotaActionBlocks['animate_s'].xmlText(),
MotaActionBlocks['showStatusBar_s'].xmlText(),
MotaActionBlocks['hideStatusBar_s'].xmlText(),
@@ -420,7 +422,7 @@ document.getElementById('blocklyDiv').onmousewheel = function(e){
var type = args.type;
if (!type) return false;
editor_blockly.id = id_;
- codeAreaHL.setValue(input.value.replace(/\\r/g,'\\\\r'));
+ codeAreaHL.setValue(input.value.replace(/\\r/g,'\\\\r').replace(/\\f/,'\\\\f'));
document.getElementById('entryType').value = type;
editor_blockly.parse();
editor_blockly.show();
diff --git a/_server/editor_file.js b/_server/editor_file.js
index 68d9c8ec..3e938917 100644
--- a/_server/editor_file.js
+++ b/_server/editor_file.js
@@ -156,6 +156,7 @@ editor_file = function (editor, callback) {
color: saveStatus?currData.color:null,
weather: saveStatus?currData.weather:null,
firstArrive: [],
+ eachArrive: [],
parallelDo: "",
events: {},
changeFloor: {},
diff --git a/docs/element.md b/docs/element.md
index fc633a07..254f8ad9 100644
--- a/docs/element.md
+++ b/docs/element.md
@@ -313,6 +313,7 @@ floorId指定的是目标楼层的唯一标识符(ID)。
- 使用`\b[...]`来制作对话框效果,如`\b[up,3,2]`。
- 使用`\r[...]`来动态修改局部文本的颜色,如`\r[red]`。
- 使用`${}`来计算一个表达式的值,如`${status:atk+status:def}`。
+- 使用`\f[...]`来同时插入一张立绘图,如`\f[1.png,100,200]`。
从V2.5.2开始,也允许绘制一张头像图在对话框中,只要通过`\t[1.png]`或`\t[标题,1.png]`的写法。
diff --git a/docs/event.md b/docs/event.md
index 041d9547..7720332f 100644
--- a/docs/event.md
+++ b/docs/event.md
@@ -228,7 +228,7 @@
除此以外,我们还能实现“对话框效果”,只要有`\b[...]`就可以。
- `\b[up]` 直接显示在当前点上方。同样把这里的up换成down则为下方。
- - 如果不存在当前点(如在firstArrive中调用),则显示在屏幕最上方(最下方)
+ - 如果不存在当前点(如在firstArrive或eachArrive中调用),则显示在屏幕最上方(最下方)
- `\b[up,hero]` 显示在勇士上方。同样把这里的up换成down则为下方。
- `\b[up,x,y]` 显示在(x,y)点的上方(下方);x和y都为整数且在0到12之间。
@@ -253,6 +253,20 @@
]
```
+从V2.5.3以后,也可以使用`\f[...]`来同时绘制一张图片。
+
+其基本写法是`\f[图片名,起始x像素,起始y像素]`,或者`\f[图片名,起始x像素,起始y像素,绘制宽度,绘制高度]`。
+
+需要注意的是,这个图片是绘制在UI层上的,下一个事件执行时即会擦除;同时如果使用了\t的图标动画效果,重叠的地方也会被图标动画给覆盖掉。
+
+``` js
+"x,y": [ // 实际执行的事件列表
+ "\t[勇士]\b[up,hero]\f[1.png,100,100]以(100,100)为左上角绘制1.png图片",
+ "\t[hero]\f[1.png,100,100]\f[2.png,300,300]同时绘制了两张图片",
+ "\f[1.png,100,100,300,300]也可以填写宽高,这样会把图片强制进行放缩到指定的宽高值"
+]
+```
+
另外值得一提的是,我们是可以在文字中计算一个表达式的值的。只需要将表达式用 `${ }`整个括起来就可以。
``` js
@@ -441,7 +455,7 @@ value为必填项,代表要修改到的结果。此项无需再手动加单引
name必填项,代表要修改的全局数值,其和全塔属性中的values一一对应。目前只能为`"lavaDamage", "poisonDamage", "weakValue", "redJewel",
"blueJewel", "greenJewel", "redPotion", "bluePotion", "yellowPotion", "greenPotion", "breakArmor", "counterAttack",
-"purify", "hatred", "maxValidHp", "animateSpeed"`。
+"purify", "hatred", "moveSpeed", "animateSpeed"`。
value为必填项,代表要修改到的结果。该项必须是个数值。
@@ -456,7 +470,8 @@ value为必填项,代表要修改到的结果。该项必须是个数值。
{"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} // 我们也可以同时动画显示多个点。
+ {"type": "show", "loc": [[3,6],[2,9],[1,2]], "time": 500}, // 我们也可以同时动画显示多个点。
+ {"type": "show", "loc": [3,6], "time": 500, "async": true} // 可以使用异步动画效果
]
```
@@ -468,13 +483,15 @@ floorId为目标点的楼层,如果不是该楼层的事件(比如4楼小偷
time为动画效果时间,如果指定了某个大于0的数,则会以动画效果慢慢从无到有显示,动画时间为该数值;如果不指定该选项则无动画直接立刻显示。
+async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。
+
!> **要注意的是,调用show事件后只是让该事件从禁用状态变成启用,从不可见不可交互变成可见可交互,但本身不会去执行该点的事件。**
### hide:将一个启用事件禁用
`{"type":"hide"}`和show刚好相反,它会让一个已经启用的事件被禁用。
-其参数和show也完全相同,loc指定事件的位置,floorId为楼层(同层可忽略),time指定的话事件会以动画效果从有到无慢慢消失。
+其参数和show也完全相同,loc指定事件的位置,floorId为楼层(同层可忽略),time指定的话事件会以动画效果从有到无慢慢消失,async代表是否是异步效果。
loc同样可以简单的写[x,y]表示单个点,或二维数组[[x1,y1],[x2,y2],...]表示多个点。
@@ -492,7 +509,7 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
{"type": "hide", "loc": [[3,6],[2,9],[1,2]], "time": 500}, // 也可以同时指定多个点消失
{"type": "hide", "time": 500}, // 如果不指定loc选项则默认为当前点, 例如这个就是500ms消失当前对话的NPC
{"type": "hide"}, // 无动画将当前事件禁用,常常适用于某个空地点(触发陷阱事件、触发机关门这种)
-
+ {"type": "hide", "loc": [3,6], "time": 500, "async": true} // 可以使用异步动画效果
]
```
@@ -807,8 +824,6 @@ time为可选的,指定的话将作为楼层切换动画的时间。
**如果time指定为小于100,则视为没有楼层切换动画。**
-!> **changeFloor到达一个新的楼层,将不会执行firstArrive事件!如有需求请在到达点设置自定义事件,然后使用type: trigger立刻调用之。**
-
### changePos:当前位置切换/勇士转向
有时候我们不想要楼层切换的动画效果,而是直接让勇士从A点到B点。
@@ -863,9 +878,9 @@ name为可选的,是要取消跟随的行走图文件名。
如果name省略,则会取消所有的跟随效果。
-### viberate:画面震动
+### vibrate:画面震动
-使用 `{"type": "viberate", "time": 2000, "async": true}` 可以造成画面震动效果。
+使用 `{"type": "vibrate", "time": 2000, "async": true}` 可以造成画面震动效果。
time可以指定震动时间,默认是2000毫秒。
@@ -1548,6 +1563,19 @@ choices为一个数组,其中每一项都是一个选项列表。
```
+### waitAsync:等待所有异步事件执行完毕
+
+上面有很多很多的异步事件(也就是执行时不等待执行完毕)。
+
+由于录像是加速播放,且会跳过`{"type":"sleep"}`(等待X毫秒)事件;因此异步行为很有可能导致录像播放出错。
+
+例如,异步移动一个NPC去某格,然后等待X毫秒,再勇士走过去对话;
+但是录像播放中,等待X毫秒的行为会被跳过,因此勇士可能走过去时异步还未执行完成,导致录像出错。
+
+我们可以使用`{"type":"waitAsync"}`来等待所有异步事件执行完毕。
+
+该事件会进行等待,直到所有可能的异步事件(异步动画除外)执行完毕。
+
### function: 自定义JS脚本
上述给出了这么多事件,但有时候往往不能满足需求,这时候就需要执行自定义脚本了。
@@ -2113,7 +2141,7 @@ if (core.getFlag("door",0)==2) {
core.stopReplay();
core.waitHeroToStop(function() {
core.removeGlobalAnimate(0,0,true);
- core.clearMap('all'); // 清空全地图
+ core.clearMap('all'); core.clearMap('curtain'); // 清空全地图
core.drawText([
"\t[恭喜通关]你的分数是${status:hp}。"
], function () {
diff --git a/docs/personalization.md b/docs/personalization.md
index e8b6f810..153ee029 100644
--- a/docs/personalization.md
+++ b/docs/personalization.md
@@ -17,10 +17,10 @@ HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们
- fg:前景层;绘制前景图层素材fgmap,和前景贴图
- damage:显伤层;主要用来绘制怪物显伤和领域显伤
- animate:动画层;主要用来绘制动画。showImage事件绘制的图片也是在这一层。
-- image:图片层;主要用来绘制显示图片
- weather:天气层;主要用来绘制天气(雨/雪)
- route:路线层;主要用来绘制勇士的行走路线图,也用来绘制图块的淡入/淡出效果,图块的移动等。
- curtain:色调层;用来控制当前楼层的画面色调
+- image:图片层;主要用来绘制显示图片;该层之所以在curtain层上是为了可以在全黑时贴大头像图
- ui:UI层;用来绘制一切UI窗口,如剧情文本、怪物手册、楼传器、系统菜单等等
- data:数据层;用来绘制一些顶层的或更新比较快的数据,如左上角的提示,战斗界面中数据的变化等等。
@@ -51,7 +51,7 @@ HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们
在地图编辑器中绘图时,下拉框选中“背景层”或“前景层”即可在对应的图层上绘图。
-其中背景层和前景层仅为静态绘图(不支持动画),但可以使用自动元件(autotile)。
+其中背景层和前景层可以使用任何素材,以及使用自动元件(autotile)。
可以使用`showBgFgMap`, `hideBgFgMap`, `setBgFgBlock`等事件对背景和前景图层进行操作。
@@ -560,6 +560,39 @@ this.myfunc = function(x) {
通过这种,将脚本和自定义事件混用的方式,可以达到和RM中公共事件类似的效果,即一个调用触发一系列事件。
-->
+
+## 标题界面事件化
+
+从V2.5.3开始,我们可以将标题界面的绘制和游戏开始用事件来完成。可以通过绘制画布、
+
+全塔属性,flags中的startUsingCanvas可以决定是否开启标题界面事件化。
+
+然后就可以使用“事件流”的形式来绘制标题界面、提供选项等等。
+
+在这里可以调用任意事件。例如,可以贴若干个图,可以事件切换楼层到某个剧情层再执行若干事件,等等。
+
+关于选项,样板默认给出的是最简单的choices事件;你也可以使用贴按钮图,循环处理+等待操作来定制自己的按钮点击效果。
+
+!> 开始游戏、读取存档、录像回放的效果已经默认给出,请不要修改或删减这些内容,以免出现问题。
+
+标题界面事件全部处理完后,将再继续执行startText事件。
+
+## 手机端按键模式
+
+从V2.5.3以后,我们可以给手机端增加按键了,这样将非常有利于技能的释放。
+
+当用户在竖屏模式下点击工具栏,就会在工具栏按钮和快捷键模式之间进行切换。
+
+切换到快捷键模式后,可以点1-7,分别等价于在电脑端按键1-7。
+
+可以在脚本编辑的onKeyUp中定义每个快捷键的使用效果,比如使用道具或释放技能等。
+
+默认值下,1使用破,2使用炸,3使用飞,4使用其他存在的道具,5-7未定义。可以相应修改成自己的效果。
+
+也可以替换icons.png中的对应图标,以及修改main.js中`main.statusBar.image.btn1~7`中的onclick事件来自定义按钮和对应按键。
+
+非竖屏模式下、回放录像中、隐藏状态栏中,将不允许进行切换。
+
## 自定义状态栏(新增显示项)
在V2.2以后,我们可以自定义状态栏背景图(全塔属性 - statusLeftBackground)等等。
@@ -577,7 +610,7 @@ this.myfunc = function(x) {
```
3. 在editor.html中的statusBar(323行起),仿照第二点同样添加;这一项如果不进行则会地图编辑器报错。editor-mobile.html同理。
-4. 使用便捷PS工具,打开icons.png,新增一行并将魔力的图标P上去;记下其索引比如30(从0开始数)。
+4. 使用便捷PS工具,打开icons.png,新增一行并将魔力的图标P上去;记下其索引比如37(从0开始数)。
5. 在main.js的this.statusBar中增加图片、图标和内容的定义。
``` js
this.statusBar = {
diff --git a/editor-mobile.html b/editor-mobile.html
index 9141fe2d..89b98714 100644
--- a/editor-mobile.html
+++ b/editor-mobile.html
@@ -174,6 +174,7 @@
+
@@ -412,6 +413,13 @@
+
+
+
+
+
+
+
diff --git a/editor.html b/editor.html
index 41e3e25c..b5f76989 100644
--- a/editor.html
+++ b/editor.html
@@ -173,6 +173,7 @@
+
@@ -398,6 +399,13 @@
![]()
+
![]()
+
![]()
+
![]()
+
![]()
+
![]()
+
![]()
+
diff --git a/index.html b/index.html
index 2a05eb95..4e65f98a 100644
--- a/index.html
+++ b/index.html
@@ -118,6 +118,13 @@
![]()
+
![]()
+
![]()
+
![]()
+
![]()
+
![]()
+
![]()
+
diff --git a/libs/actions.js b/libs/actions.js
index 6439e095..5b8a3ede 100644
--- a/libs/actions.js
+++ b/libs/actions.js
@@ -166,6 +166,9 @@ actions.prototype.keyDown = function(keyCode) {
if (core.status.event.id=='replay') {
this.keyDownReplay(keyCode);
}
+ if (core.status.event.id=='gameInfo') {
+ this.keyDownGameInfo(keyCode);
+ }
return;
}
if(!core.status.played) {
@@ -280,6 +283,10 @@ actions.prototype.keyUp = function(keyCode, altKey) {
this.keyUpReplay(keyCode);
return;
}
+ if (core.status.event.id=='gameInfo') {
+ this.keyUpGameInfo(keyCode);
+ return;
+ }
if (core.status.event.id=='centerFly') {
this.keyUpCenterFly(keyCode);
return;
@@ -590,6 +597,10 @@ actions.prototype.onclick = function (x, y, stepPostfix) {
return;
}
+ if (core.status.event.id=='gameInfo') {
+ this.clickGameInfo(x,y);
+ }
+
}
////// 滑动鼠标滚轮时的操作 //////
@@ -991,7 +1002,6 @@ actions.prototype.clickViewMaps = function (x,y) {
}
else if (x>=2 && x<=10 && y>=5 && y<=7) {
core.clearMap('data');
- core.setOpacity('data', 1);
core.ui.closePanel();
}
}
@@ -1020,7 +1030,6 @@ actions.prototype.keyUpViewMaps = function (keycode) {
if (keycode==27 || keycode==13 || keycode==32 || (!core.status.replay.replaying && keycode==67)) {
core.clearMap('data');
- core.setOpacity('data', 1);
core.ui.closePanel();
return;
}
@@ -1903,25 +1912,10 @@ actions.prototype.clickSettings = function (x,y) {
core.ui.drawSyncSave();
break;
case 5:
- core.ui.drawStatistics();
+ core.status.event.selection=0;
+ core.ui.drawGameInfo();
break;
case 6:
- if (core.platform.isPC) {
- window.open("/score.php?name="+core.firstData.name+"&num=10", "_blank");
- }
- else {
- if (confirm("即将离开本塔,跳转至本塔评论页面,确认?")) {
- window.location.href = "/score.php?name="+core.firstData.name+"&num=10";
- }
- }
- break;
- case 7:
- core.ui.drawHelp();
- break;
- case 8:
- core.ui.drawAbout();
- break;
- case 9:
core.status.event.selection=1;
core.ui.drawConfirmBox("你确定要返回标题页面吗?", function () {
core.ui.closePanel();
@@ -1931,7 +1925,7 @@ actions.prototype.clickSettings = function (x,y) {
core.ui.drawSettings();
});
break;
- case 10:
+ case 7:
core.ui.closePanel();
break;
}
@@ -2057,7 +2051,7 @@ actions.prototype.clickSyncSave = function (x,y) {
core.ui.drawStorageRemove();
break;
case 7:
- core.status.event.selection=3;
+ core.status.event.selection=4;
core.ui.drawSettings();
break;
@@ -2291,7 +2285,7 @@ actions.prototype.clickStorageRemove = function (x, y) {
}
break;
case 2:
- core.status.event.selection=5;
+ core.status.event.selection=6;
core.ui.drawSyncSave();
break;
}
@@ -2414,6 +2408,77 @@ actions.prototype.keyUpReplay = function (keycode) {
}
}
+
+////// 游戏信息界面时的点击操作 //////
+actions.prototype.clickGameInfo = function (x, y) {
+ if (x<5 || x>7) return;
+ var choices = core.status.event.ui.choices;
+
+ var topIndex = 6 - parseInt((choices.length - 1) / 2);
+
+ if (y>=topIndex && y
=49 && keycode<=57) {
+ var index = keycode-49;
+ if (index=1 && x<=11) {
diff --git a/libs/control.js b/libs/control.js
index c1f03d4b..56bdff04 100644
--- a/libs/control.js
+++ b/libs/control.js
@@ -70,7 +70,7 @@ control.prototype.setRequestAnimationFrame = function () {
}
// Global Animate
- if (core.animateFrame.globalAnimate && core.isPlaying()) {
+ if (core.animateFrame.globalAnimate && core.isPlaying() && core.isset(core.status.floorId)) {
if (timestamp-core.animateFrame.globalTime>core.animateFrame.speed && core.isset(core.status.globalAnimateObjs)) {
@@ -81,9 +81,21 @@ control.prototype.setRequestAnimationFrame = function () {
}
if ((core.status.autotileAnimateObjs.blocks||[]).length>0) {
+ var groundId = (core.status.maps||core.floors)[core.status.floorId].defaultGround || "ground";
+ var blockIcon = core.material.icons.terrains[groundId];
core.status.autotileAnimateObjs.status++;
core.status.autotileAnimateObjs.blocks.forEach(function (block) {
- core.drawAutotile(core.canvas.event, core.status.autotileAnimateObjs.map, block, 32, 0, 0, core.status.autotileAnimateObjs.status);
+ var cv = core.isset(block.name)?core.canvas[block.name]:core.canvas.event;
+ cv.clearRect(block.x * 32, block.y * 32, 32, 32);
+ if (core.isset(block.name)) {
+ if (block.name == 'bg') {
+ core.canvas.bg.drawImage(core.material.images.terrains, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
+ }
+ core.drawAutotile(cv, core.status.autotileAnimateObjs[block.name+"map"], block, 32, 0, 0, core.status.autotileAnimateObjs.status);
+ }
+ else {
+ core.drawAutotile(cv, core.status.autotileAnimateObjs.map, block, 32, 0, 0, core.status.autotileAnimateObjs.status);
+ }
})
}
@@ -221,6 +233,15 @@ control.prototype.showStartAnimate = function (noAnimate, callback) {
core.status.played = false;
core.clearStatus();
core.clearMap('all');
+ core.clearMap('curtain');
+
+ if (core.flags.startUsingCanvas) {
+ core.dom.startTop.style.display = 'none';
+ core.dom.startButtonGroup.style.display = 'block';
+ core.events.startGame('');
+ if (core.isset(callback)) callback();
+ return;
+ }
if(noAnimate) {
core.dom.startTop.style.display = 'none';
@@ -444,7 +465,7 @@ control.prototype.setAutomaticRoute = function (destX, destY, stepPostfix) {
core.control.tryMoveDirectly(destX, destY);
}
core.status.automaticRoute.moveDirectly = false;
- }, 100);
+ }, core.values.moveSpeed || 100);
}
return;
}
@@ -693,7 +714,7 @@ control.prototype.setHeroMoveInterval = function (direction, x, y, callback) {
core.status.heroMoving = 0;
if (core.isset(callback)) callback();
}
- }, 12.5 * toAdd / core.status.replay.speed);
+ }, (core.values.moveSpeed||100) / 8 * toAdd / core.status.replay.speed);
}
////// 实际每一步的行走过程 //////
@@ -836,7 +857,7 @@ control.prototype.moveHero = function (direction, callback) {
/////// 使用事件让勇士移动。这个函数将不会触发任何事件 //////
control.prototype.eventMoveHero = function(steps, time, callback) {
- time = time || 100;
+ time = time || core.values.moveSpeed || 100;
// 要运行的轨迹:将steps展开
var moveSteps=[];
@@ -867,6 +888,7 @@ control.prototype.eventMoveHero = function(steps, time, callback) {
var animate=window.setInterval(function() {
var x=core.getHeroLoc('x'), y=core.getHeroLoc('y');
if (moveSteps.length==0) {
+ delete core.animateFrame.asyncId[animate];
clearInterval(animate);
core.drawHero(null, x, y);
if (core.isset(callback)) callback();
@@ -889,7 +911,9 @@ control.prototype.eventMoveHero = function(steps, time, callback) {
moveSteps.shift();
}
}
- }, time / 8 / core.status.replay.speed)
+ }, time / 8 / core.status.replay.speed);
+
+ core.animateFrame.asyncId[animate] = true;
}
////// 勇士跳跃事件 //////
@@ -944,6 +968,7 @@ control.prototype.jumpHero = function (ex, ey, time, callback) {
nowx - core.bigmap.offsetX, nowy + 32-height - core.bigmap.offsetY, 32, height);
}
else {
+ delete core.animateFrame.asyncId[animate];
clearInterval(animate);
core.setHeroLoc('x', ex);
core.setHeroLoc('y', ey);
@@ -953,8 +978,7 @@ control.prototype.jumpHero = function (ex, ey, time, callback) {
}, time / 16 / core.status.replay.speed);
-
-
+ core.animateFrame.asyncId[animate] = true;
}
////// 每移动一格后执行的事件 //////
@@ -1025,7 +1049,7 @@ control.prototype.updateViewport = function() {
////// 绘制勇士 //////
control.prototype.drawHero = function (direction, x, y, status, offset) {
- if (!core.isPlaying() || core.status.isStarting) return;
+ if (!core.isPlaying()) return;
var scan = {
'up': {'x': 0, 'y': -1},
@@ -1492,26 +1516,26 @@ control.prototype.setFg = function(color, time, callback) {
core.fillRect('curtain', 0, 0, 416, 416, core.arrayToRGBA([nowR,nowG,nowB,nowA]));
if (step>=25) {
+ delete core.animateFrame.asyncId[changeAnimate];
clearInterval(changeAnimate);
core.status.curtainColor = color;
// core.status.replay.animate=false;
if (core.isset(callback)) callback();
}
}, time/25/core.status.replay.speed);
+
+ core.animateFrame.asyncId[changeAnimate] = true;
}
////// 更新全地图显伤 //////
control.prototype.updateDamage = function (floorId, canvas) {
-
- if (!core.isset(floorId)) floorId = core.status.floorId;
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
if (!core.isset(canvas)) {
canvas = core.canvas.damage;
core.clearMap('damage');
}
- // 正在开始游戏中
- if (core.status.isStarting) return;
-
// 更新显伤
var mapBlocks = core.status.maps[floorId].blocks;
// 没有怪物手册
@@ -1655,15 +1679,21 @@ control.prototype.chooseReplayFile = function () {
}
if (core.isset(obj.version) && obj.version!=core.firstData.version) {
// alert("游戏版本不一致!");
- if (!confirm("游戏版本不一致!\n你仍然想播放录像吗?"))
+ if (!confirm("游戏版本不一致!\n你仍然想播放录像吗?")) {
return;
+ }
}
- if (!core.isset(obj.route) || !core.isset(obj.hard)) {
+ if (!core.isset(obj.route)) {
alert("无效的录像!");
return;
}
- core.startGame(obj.hard, obj.seed, core.decodeRoute(obj.route));
+ if (core.flags.startUsingCanvas) {
+ core.startGame('', obj.seed, core.decodeRoute(obj.route));
+ }
+ else {
+ core.startGame(obj.hard, obj.seed, core.decodeRoute(obj.route));
+ }
}, function () {
})
@@ -2672,6 +2702,16 @@ control.prototype.playSound = function (sound) {
}
}
+control.prototype.checkBgm = function() {
+ if (core.musicStatus.startDirectly && core.musicStatus.bgmStatus) {
+ if (core.musicStatus.playingBgm==null
+ || core.material.bgms[core.musicStatus.playingBgm].paused) {
+ core.musicStatus.playingBgm=null;
+ core.playBgm(core.bgms[0]);
+ }
+ }
+}
+
////// 清空状态栏 //////
control.prototype.clearStatusBar = function() {
@@ -2738,7 +2778,8 @@ control.prototype.triggerStatusBar = function (name) {
if (name!='hide') name='show';
var statusItems = core.dom.status;
var toolItems = core.dom.tools;
- if (name == 'hide') {
+ core.domStyle.showStatusBar = name == 'show';
+ if (!core.domStyle.showStatusBar) {
for (var i = 0; i < statusItems.length; ++i)
statusItems[i].style.opacity = 0;
for (var i = 0; i < toolItems.length; ++i)
@@ -2747,10 +2788,8 @@ control.prototype.triggerStatusBar = function (name) {
else {
for (var i = 0; i < statusItems.length; ++i)
statusItems[i].style.opacity = 1;
- for (var i = 0; i < toolItems.length; ++i)
- toolItems[i].style.display = 'block';
- if (core.domStyle.screenMode != 'vertical')
- core.statusBar.image.shop.style.display = 'none';
+ this.setToolbarButton(false);
+ core.dom.tools.hard.style.display = 'block';
}
}
@@ -2832,6 +2871,33 @@ control.prototype.updateGlobalAttribute = function (name) {
}
}
+////// 改变工具栏为按钮1-7 //////
+control.prototype.setToolbarButton = function (useButton) {
+ if (!core.domStyle.showStatusBar) return;
+
+ if (!core.isset(useButton)) useButton = core.domStyle.toolbarBtn;
+ if (core.domStyle.screenMode != 'vertical') useButton = false;
+
+ core.domStyle.toolbarBtn = useButton;
+ if (useButton) {
+ ["book","fly","toolbox","shop","save","load","settings"].forEach(function (t) {
+ core.statusBar.image[t].style.display = 'none';
+ });
+ ["btn1","btn2","btn3","btn4","btn5","btn6","btn7"].forEach(function (t) {
+ core.statusBar.image[t].style.display = 'block';
+ })
+ }
+ else {
+ ["btn1","btn2","btn3","btn4","btn5","btn6","btn7"].forEach(function (t) {
+ core.statusBar.image[t].style.display = 'none';
+ });
+ ["book","fly","toolbox","shop","save","load","settings"].forEach(function (t) {
+ core.statusBar.image[t].style.display = 'block';
+ });
+ core.statusBar.image.shop.style.display = core.domStyle.screenMode != 'vertical' ? "none":"block";
+ }
+}
+
////// 屏幕分辨率改变后重新自适应 //////
control.prototype.resize = function(clientWidth, clientHeight) {
if (main.mode=='editor')return;
@@ -2894,6 +2960,8 @@ control.prototype.resize = function(clientWidth, clientHeight) {
var zoom = (ADAPT_WIDTH - width) / 4.22;
var aScale = 1 - zoom / 100;
+ core.domStyle.toolbarBtn = false;
+
// 移动端
if (width < CHANGE_WIDTH) {
if(width < ADAPT_WIDTH){
@@ -3132,7 +3200,7 @@ control.prototype.resize = function(clientWidth, clientHeight) {
{
imgId: 'shop',
rules:{
- display: shopDisplay
+ display: shopDisplay && core.domStyle.showStatusBar
}
},
{
@@ -3222,6 +3290,7 @@ control.prototype.resize = function(clientWidth, clientHeight) {
},
]
core.domRenderer();
+ this.setToolbarButton();
}
////// 渲染DOM //////
diff --git a/libs/core.js b/libs/core.js
index f14206fe..f6cfe375 100644
--- a/libs/core.js
+++ b/libs/core.js
@@ -41,7 +41,8 @@ function core() {
'level': 0,
'nodes': [],
'data': null,
- }
+ },
+ "asyncId": {}
}
this.musicStatus = {
'audioContext': null, // WebAudioContext
@@ -73,6 +74,8 @@ function core() {
this.domStyle = {
styles: [],
scale: 1.0,
+ toolbarBtn: false,
+ showStatusBar: true,
}
this.bigmap = {
canvas: ["bg", "event", "event2", "fg", "damage", "route"],
@@ -176,7 +179,7 @@ function core() {
// 动画
'globalAnimateObjs': [],
'boxAnimateObjs': [],
- 'autotileAnimateObjs': {},
+ 'autotileAnimateObjs': {"status": 0, "blocks": [], "map": null, "bgmap": null, "fgmap": null},
'animateObjs': [],
};
this.status = {};
diff --git a/libs/events.js b/libs/events.js
index a02099bd..a1a3184a 100644
--- a/libs/events.js
+++ b/libs/events.js
@@ -91,14 +91,15 @@ events.prototype.initGame = function () {
////// 游戏开始事件 //////
events.prototype.startGame = function (hard, seed, route, callback) {
- if (core.status.isStarting) return;
- core.status.isStarting = true;
+ main.dom.levelChooseButtons.style.display='none';
+ main.dom.startButtonGroup.style.display='none';
var start = function () {
console.log('开始游戏');
- core.resetStatus(core.firstData.hero, hard, core.firstData.floorId, null, core.initStatus.maps);
-
- core.status.isStarting = true;
+ core.resetStatus(core.firstData.hero, hard, null, null, core.initStatus.maps);
+ var nowLoc = core.clone(core.getHeroLoc());
+ core.setHeroLoc('x', -1);
+ core.setHeroLoc('y', -1);
if (core.isset(seed)) {
core.setFlag('__seed__', seed);
@@ -106,15 +107,15 @@ events.prototype.startGame = function (hard, seed, route, callback) {
}
else core.utils.__init_seed();
- core.events.setInitData(hard);
core.clearMap('all');
+ core.clearMap('curtain');
core.clearStatusBar();
var post_start = function () {
- core.status.isStarting = false;
+ core.control.triggerStatusBar('show');
- core.changeFloor(core.status.floorId, null, core.status.hero.loc, null, function() {
+ core.changeFloor(core.firstData.floorId, null, nowLoc, null, function() {
if (core.isset(callback)) callback();
}, true);
@@ -125,7 +126,7 @@ events.prototype.startGame = function (hard, seed, route, callback) {
formData.append('name', core.firstData.name);
formData.append('version', core.firstData.version);
formData.append('platform', core.platform.isPC?"PC":core.platform.isAndroid?"Android":core.platform.isIOS?"iOS":"");
- formData.append('hard', core.encodeBase64(hard));
+ formData.append('hard', core.encodeBase64(core.status.hard));
formData.append('hardCode', core.getFlag('hard', 0));
formData.append('base64', 1);
@@ -133,23 +134,36 @@ events.prototype.startGame = function (hard, seed, route, callback) {
})
}
- core.insertAction(core.clone(core.firstData.startText), null, null, function() {
- if (!core.status.replay.replaying && core.flags.showBattleAnimateConfirm) { // 是否提供“开启战斗动画”的选择项
- core.status.event.selection = core.flags.battleAnimate ? 0 : 1;
- core.ui.drawConfirmBox("你想开启战斗动画吗?\n之后可以在菜单栏中开启或关闭。\n(强烈建议新手开启此项)", function () {
- core.flags.battleAnimate = true;
- core.setLocalStorage('battleAnimate', true);
+ var real_start = function () {
+ core.insertAction(core.clone(core.firstData.startText), null, null, function() {
+ if (!core.flags.startUsingCanvas && !core.status.replay.replaying && core.flags.showBattleAnimateConfirm) { // 是否提供“开启战斗动画”的选择项
+ core.status.event.selection = core.flags.battleAnimate ? 0 : 1;
+ core.ui.drawConfirmBox("你想开启战斗动画吗?\n之后可以在菜单栏中开启或关闭。\n(强烈建议新手开启此项)", function () {
+ core.flags.battleAnimate = true;
+ core.setLocalStorage('battleAnimate', true);
+ post_start();
+ }, function () {
+ core.flags.battleAnimate = false;
+ core.setLocalStorage('battleAnimate', false);
+ post_start();
+ });
+ }
+ else {
post_start();
- }, function () {
- core.flags.battleAnimate = false;
- core.setLocalStorage('battleAnimate', false);
- post_start();
- });
- }
- else {
- post_start();
- }
- });
+ }
+ });
+ }
+
+ if (core.flags.startUsingCanvas) {
+ core.control.triggerStatusBar('hide');
+ core.insertAction(core.clone(core.firstData.startCanvas), null, null, function() {
+ real_start();
+ });
+ }
+ else {
+ core.events.setInitData(hard);
+ real_start();
+ }
if (core.isset(route)) {
core.startReplay(route);
@@ -157,6 +171,12 @@ events.prototype.startGame = function (hard, seed, route, callback) {
}
+ if (core.flags.startUsingCanvas) {
+ core.dom.startPanel.style.display = 'none';
+ start();
+ return;
+ }
+
if (core.isset(route)) {
core.dom.startPanel.style.display = 'none';
start();
@@ -290,12 +310,7 @@ events.prototype.gameOver = function (ending, fromReplay, norank) {
}
else {
- if (core.isset(core.values.maxValidHp) && core.status.hero.hp>core.values.maxValidHp) {
- core.drawText("作弊可耻!", function () {
- core.restart();
- });
- }
- else if (core.hasFlag('debug')) {
+ if (core.hasFlag('debug')) {
core.drawText("\t[系统提示]调试模式下无法上传成绩", function () {
core.restart();
})
@@ -438,12 +453,15 @@ events.prototype.doAction = function() {
&& (typeof data.loc[1] == 'number' || typeof data.loc[1] == 'string'))
data.loc = [[core.calValue(data.loc[0]), core.calValue(data.loc[1])]];
if (core.isset(data.time) && data.time>0 && (!core.isset(data.floorId) || data.floorId==core.status.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();
- });
+ if (data.async) {
+ core.animateBlock(data.loc, 'show', data.time);
+ this.doAction();
+ }
+ else {
+ core.animateBlock(data.loc,'show', data.time, function () {
+ core.events.doAction();
+ });
+ }
}
else {
data.loc.forEach(function (t) {
@@ -461,13 +479,16 @@ events.prototype.doAction = function() {
if (core.isset(data.time) && data.time>0 && (!core.isset(data.floorId) || data.floorId==core.status.floorId)) {
data.loc.forEach(function (t) {
core.hideBlock(t[0],t[1],data.floorId);
- })
- core.animateBlock(data.loc,'hide',data.time, function () {
- data.loc.forEach(function (t) {
- core.removeBlock(t[0],t[1],data.floorId)
- })
- core.events.doAction();
});
+ if (data.async) {
+ core.animateBlock(data.loc, 'hide', data.time);
+ this.doAction();
+ }
+ else {
+ core.animateBlock(data.loc,'hide', data.time, function () {
+ core.events.doAction();
+ });
+ }
}
else {
data.loc.forEach(function (t) {
@@ -1059,7 +1080,7 @@ events.prototype.doAction = function() {
core.updateStatusBar();
this.doAction();
break;
- case "viberate":
+ case "vibrate":
if (data.async) {
core.events.vibrate(data.time);
this.doAction();
@@ -1102,6 +1123,16 @@ events.prototype.doAction = function() {
}
}
break;
+ case "waitAsync": // 等待所有异步事件执行完毕
+ {
+ var test = window.setInterval(function () {
+ if (Object.keys(core.animateFrame.asyncId)==0) {
+ clearInterval(test);
+ core.events.doAction();
+ }
+ }, 50);
+ break;
+ }
case "revisit": // 立刻重新执行该事件
{
var block=core.getBlock(x,y); // 重新获得事件
@@ -1312,6 +1343,7 @@ events.prototype.trigger = function (x, y) {
events.prototype.setFloorName = function (floorId) {
floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
// 根据文字判断是否斜体
var floorName = core.status.maps[floorId].name || "";
if (typeof floorName == 'number') floorName = ""+floorName;
@@ -1336,7 +1368,11 @@ events.prototype.setFloorName = function (floorId) {
////// 楼层切换 //////
events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback, fromLoad) {
- if (!core.isset(floorId)) floorId = core.status.floorId;
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) {
+ if (core.isset(callback)) callback();
+ return;
+ }
if (floorId == ':before') {
var index=core.floorIds.indexOf(core.status.floorId);
@@ -1495,33 +1531,40 @@ events.prototype.animateImage = function (type, image, loc, time, keep, callback
}
clearInterval(core.interval.tipAnimate);
- core.setAlpha('data', 1);
- var opacityVal = 0;
- if (type == 'hide') opacityVal = 1;
+ var alpha = 0;
+ if (type == 'hide') alpha = 1;
+
+ var x = core.calValue(loc[0]), y = core.calValue(loc[1]);
if (type == 'hide' && keep) {
- core.clearMap('image');
+ core.clearMap('image', x, y, image.width, image.height);
}
-
- core.setOpacity('data', opacityVal);
- var x = core.calValue(loc[0]), y = core.calValue(loc[1]);
+ core.setAlpha('data', alpha);
core.canvas.data.drawImage(image, x, y);
+ core.setAlpha('data', 1);
+
// core.status.replay.animate=true;
var animate = setInterval(function () {
- if (type=='show') opacityVal += 0.1;
- else opacityVal -= 0.1;
- core.setOpacity('data', opacityVal);
- if (opacityVal >=1 || opacityVal<=0) {
+ if (type=='show') alpha += 0.1;
+ else alpha -= 0.1;
+ core.clearMap('data', x, y, image.width, image.height);
+ if (alpha >=1 || alpha<=0) {
+ delete core.animateFrame.asyncId[animate];
clearInterval(animate);
if (type == 'show' && keep)
core.canvas.image.drawImage(image, x, y);
- core.clearMap('data');
- core.setOpacity('data', 1);
- // core.status.replay.animate=false;
+ core.setAlpha('data', 1);
if (core.isset(callback)) callback();
}
+ else {
+ core.setAlpha('data', alpha);
+ core.canvas.data.drawImage(image, x, y);
+ core.setAlpha('data', 1);
+ }
}, time / 10);
+
+ core.animateFrame.asyncId[animate] = true;
}
////// 移动图片 //////
@@ -1529,7 +1572,6 @@ events.prototype.moveImage = function (image, from, to, time, keep, callback) {
time = time || 1000;
clearInterval(core.interval.tipAnimate);
core.setAlpha('data', 1);
- core.setOpacity('data', 1);
var width = image.width, height = image.height;
@@ -1554,13 +1596,14 @@ events.prototype.moveImage = function (image, from, to, time, keep, callback) {
if (step <= steps)
drawImage();
else {
+ delete core.animateFrame.asyncId[animate];
clearInterval(animate);
- // score.clearMap('data');
- // core.status.replay.animate=false;
if (keep) core.canvas.image.drawImage(image, toX, toY);
if (core.isset(callback)) callback();
}
}, per_time);
+
+ core.animateFrame.asyncId[animate] = true;
}
////// 淡入淡出音乐 //////
@@ -1587,12 +1630,15 @@ events.prototype.setVolume = function (value, time, callback) {
var nowVolume = currVolume+(value-currVolume)*step/32;
set(nowVolume);
if (step>=32) {
+ delete core.animateFrame.asyncId[fade];
clearInterval(fade);
// core.status.replay.animate=false;
if (core.isset(callback))
callback();
}
}, time / 32);
+
+ core.animateFrame.asyncId[fade] = true;
}
////// 画面震动 //////
@@ -1650,11 +1696,14 @@ events.prototype.vibrate = function(time, callback) {
update();
addGameCanvasTranslate(shake, 0);
if(shake_duration===0) {
+ delete core.animateFrame.asyncId[animate];
clearInterval(animate);
// core.status.replay.animate=false;
if (core.isset(callback)) callback();
}
}, 50/3);
+
+ core.animateFrame.asyncId[animate] = true;
}
////// 打开一个全局商店 //////
diff --git a/libs/maps.js b/libs/maps.js
index 229d6ebd..2c9c5f83 100644
--- a/libs/maps.js
+++ b/libs/maps.js
@@ -211,6 +211,7 @@ maps.prototype.save = function(maps, floorId) {
////// 更改地图画布的尺寸
maps.prototype.resizeMap = function(floorId) {
floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
core.bigmap.width = core.floors[floorId].width || 13;
core.bigmap.height = core.floors[floorId].height || 13;
var cwidth = core.bigmap.width * 32;
@@ -229,7 +230,7 @@ maps.prototype.resizeMap = function(floorId) {
////// 将存档中的地图信息重新读取出来 //////
maps.prototype.load = function (data, floorId) {
- if (floorId == undefined) {
+ if (!core.isset(floorId)) {
var map = {};
core.floorIds.forEach(function (id) {
map[id] = core.maps.loadFloor(id, data[id]);
@@ -266,7 +267,8 @@ maps.prototype.canMoveHero = function(x,y,direction,floorId) {
if (!core.isset(x)) x=core.getHeroLoc('x');
if (!core.isset(y)) y=core.getHeroLoc('y');
if (!core.isset(direction)) direction=core.getHeroLoc('direction');
- if (!core.isset(floorId)) floorId=core.status.floorId;
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return false;
// 检查当前块的cannotMove
if (core.isset(core.floors[floorId].cannotMove)) {
@@ -384,6 +386,17 @@ maps.prototype.drawBlock = function (block, animate, dx, dy) {
dx = dx || 0;
dy = dy || 0;
+ if (core.isset(block.name)) {
+ core.canvas[block.name].clearRect(block.x * 32, block.y * 32, 32, 32);
+ if (block.name == 'bg') {
+ var groundId = (core.status.maps||core.floors)[core.status.floorId].defaultGround || "ground";
+ var blockIcon = core.material.icons.terrains[groundId];
+ core.canvas.bg.drawImage(core.material.images.terrains, 0, blockIcon * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
+ }
+ core.canvas[block.name].drawImage(image, x * 32, y * 32, 32, 32, block.x * 32, block.y * 32, 32, 32);
+ return;
+ }
+
core.canvas.event.clearRect(block.x * 32 + dx, block.y * 32 + dy, 32, 32);
core.canvas.event.drawImage(image, x * 32, y * height + height-32, 32, 32, block.x * 32 + dx, block.y * 32 + dy, 32, 32);
if (height>32) {
@@ -394,6 +407,7 @@ maps.prototype.drawBlock = function (block, animate, dx, dy) {
maps.prototype.getBgFgMapArray = function (floorId, name) {
floorId = floorId||core.status.floorId;
+ if (!core.isset(floorId)) return [];
var width = core.floors[floorId].width || 13;
var height = core.floors[floorId].height || 13;
@@ -415,8 +429,9 @@ maps.prototype.getBgFgMapArray = function (floorId, name) {
}
////// 背景/前景图块的绘制 //////
-maps.prototype.drawBgFgMap = function (floorId, canvas, name) {
+maps.prototype.drawBgFgMap = function (floorId, canvas, name, animate) {
floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
var width = core.floors[floorId].width || 13;
var height = core.floors[floorId].height || 13;
@@ -428,10 +443,15 @@ maps.prototype.drawBgFgMap = function (floorId, canvas, name) {
for (var y = 0; y < height; y++) {
if (arr[y][x]>0) {
var block = core.maps.initBlock(x, y, arr[y][x]);
+ this.addInfo(block);
+ block.name = name;
if (core.isset(block.event)) {
var id = block.event.id, cls = block.event.cls;
- if (cls == 'autotile')
+ if (cls == 'autotile') {
core.drawAutotile(canvas, arr, block, 32, 0, 0);
+ if (animate)
+ core.status.autotileAnimateObjs.blocks.push(core.clone(block));
+ }
else if (cls == 'tileset') {
var offset = core.icons.getTilesetOffset(id);
if (offset!=null) {
@@ -443,18 +463,30 @@ maps.prototype.drawBgFgMap = function (floorId, canvas, name) {
canvas.drawImage(core.material.images.airwall, 32*x, 32*y);
}
}
- else
- canvas.drawImage(core.material.images[cls], 0, core.material.icons[cls][id] * 32, 32, 32, x * 32, y * 32, 32, 32);
+ else {
+ if (animate) {
+ this.drawBlock(block);
+ this.addGlobalAnimate(block);
+ }
+ else {
+ canvas.drawImage(core.material.images[cls], 0, core.material.icons[cls][id] * 32, 32, 32, x * 32, y * 32, 32, 32);
+ }
+ }
}
}
}
}
-
+ core.status.autotileAnimateObjs[name+"map"] = core.clone(arr);
}
////// 绘制某张地图 //////
maps.prototype.drawMap = function (mapName, callback) {
mapName = mapName || core.status.floorId;
+ if (!core.isset(mapName)) {
+ if (core.isset(callback))
+ callback();
+ return;
+ }
core.clearMap('all');
core.removeGlobalAnimate(null, null, true);
@@ -511,8 +543,8 @@ maps.prototype.drawMap = function (mapName, callback) {
}
});
- core.maps.drawBgFgMap(mapName, core.canvas.bg, "bg");
- core.maps.drawBgFgMap(mapName, core.canvas.fg, "fg");
+ core.maps.drawBgFgMap(mapName, core.canvas.bg, "bg", true);
+ core.maps.drawBgFgMap(mapName, core.canvas.fg, "fg", true);
}
if (main.mode=='editor'){
@@ -531,7 +563,6 @@ maps.prototype.drawMap = function (mapName, callback) {
core.status.floorId = mapName;
core.status.thisMap = core.status.maps[mapName];
var drawEvent = function(){
- core.status.autotileAnimateObjs = {"status": 0, "blocks": [], "map": null};
var mapData = core.status.maps[core.status.floorId];
var mapBlocks = mapData.blocks;
@@ -707,7 +738,8 @@ maps.prototype.enemyExists = function (x, y, id,floorId) {
////// 获得某个点的block //////
maps.prototype.getBlock = function (x, y, floorId, showDisable) {
- if (!core.isset(floorId)) floorId=core.status.floorId;
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return null;
var blocks = core.status.maps[floorId].blocks;
for (var n=0;n=1 || opacityVal<=0) {
+ if (type=='show') alpha += 0.1;
+ else alpha -= 0.1;
+ clear();
+ if (alpha >=1 || alpha<=0) {
+ delete core.animateFrame.asyncId[animate];
clearInterval(animate);
- core.clearMap('route');
- core.setOpacity('route', 1);
- // core.status.replay.animate=false;
+ core.setAlpha('route', 1);
+ if (type == 'show') {
+ loc.forEach(function (t) {
+ core.showBlock(t[0],t[1],data.floorId);
+ });
+ }
+ else {
+ loc.forEach(function (t) {
+ core.removeBlock(t[0],t[1],data.floorId);
+ });
+ }
if (core.isset(callback)) callback();
}
+ else {
+ core.setAlpha('route', alpha);
+ draw();
+ }
}, time / 10 / core.status.replay.speed);
+
+ core.animateFrame.asyncId[animate] = true;
}
////// 将某个块从禁用变成启用状态 //////
-maps.prototype.showBlock = function(x, y, floodId) {
- floodId = floodId || core.status.floorId;
- var block = core.getBlock(x,y,floodId,true);
+maps.prototype.showBlock = function(x, y, floorId) {
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
+ var block = core.getBlock(x,y,floorId,true);
if (block==null) return; // 不存在
block=block.block;
// 本身是禁用事件,启用之
if (block.disable) {
block.disable = false;
// 在本层,添加动画
- if (floodId == core.status.floorId && core.isset(block.event)) {
+ if (floorId == core.status.floorId && core.isset(block.event)) {
core.drawBlock(block);
core.addGlobalAnimate(block);
core.syncGlobalAnimate();
@@ -1085,6 +1143,7 @@ maps.prototype.showBlock = function(x, y, floodId) {
////// 只隐藏但不删除某块 //////
maps.prototype.hideBlock = function (x, y, floorId) {
floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
var block = core.getBlock(x,y,floorId,true);
if (block==null) return; // 不存在
@@ -1106,6 +1165,7 @@ maps.prototype.hideBlock = function (x, y, floorId) {
////// 将某个块从启用变成禁用状态 //////
maps.prototype.removeBlock = function (x, y, floorId) {
floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
var block = core.getBlock(x,y,floorId,true);
if (block==null) return; // 不存在
@@ -1129,6 +1189,8 @@ maps.prototype.removeBlock = function (x, y, floorId) {
////// 根据block的索引删除该块 //////
maps.prototype.removeBlockById = function (index, floorId) {
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
var blocks = core.status.maps[floorId].blocks, block = blocks[index];
var x=block.x, y=block.y;
@@ -1154,6 +1216,8 @@ maps.prototype.removeBlockById = function (index, floorId) {
////// 一次性删除多个block //////
maps.prototype.removeBlockByIds = function (floorId, ids) {
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
ids.sort(function (a,b) {return b-a}).forEach(function (id) {
core.removeBlockById(id, floorId);
});
@@ -1162,6 +1226,7 @@ maps.prototype.removeBlockByIds = function (floorId, ids) {
////// 改变图块 //////
maps.prototype.setBlock = function (number, x, y, floorId) {
floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
if (!core.isset(number) || !core.isset(x) || !core.isset(y)) return;
if (x<0 || x>=core.bigmap.width || y<0 || y>=core.bigmap.height) return;
@@ -1187,6 +1252,7 @@ maps.prototype.setBlock = function (number, x, y, floorId) {
////// 改变图层块 //////
maps.prototype.setBgFgBlock = function (name, number, x, y, floorId) {
floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
if (!core.isset(number) || !core.isset(x) || !core.isset(y)) return;
if (x<0 || x>=core.bigmap.width || y<0 || y>=core.bigmap.height) return;
if (name!='bg' && name!='fg') return;
@@ -1207,24 +1273,23 @@ maps.prototype.addGlobalAnimate = function (b) {
block.status = 0;
core.status.globalAnimateObjs.push(block);
-
}
////// 删除一个或所有全局动画 //////
-maps.prototype.removeGlobalAnimate = function (x, y, all) {
+maps.prototype.removeGlobalAnimate = function (x, y, all, name) {
if (main.mode=='editor' && main.editor.disableGlobalAnimate) return;
if (all) {
core.status.globalAnimateObjs = [];
- core.status.autotileAnimateObjs = {};
+ core.status.autotileAnimateObjs = {"status": 0, "blocks": [], "map": null, "bgmap": null, "fgmap": null};
return;
}
- core.status.globalAnimateObjs = core.status.globalAnimateObjs.filter(function (block) {return block.x!=x || block.y!=y;});
+ core.status.globalAnimateObjs = core.status.globalAnimateObjs.filter(function (block) {return block.x!=x || block.y!=y || block.name!=name;});
// 检查Autotile
if (core.isset(core.status.autotileAnimateObjs.blocks)) {
- core.status.autotileAnimateObjs.blocks = core.status.autotileAnimateObjs.blocks.filter(function (block) {return block.x!=x || block.y!=y;});
+ core.status.autotileAnimateObjs.blocks = core.status.autotileAnimateObjs.blocks.filter(function (block) {return block.x!=x || block.y!=y || block.name!=name;});
core.status.autotileAnimateObjs.map[y][x] = 0;
}
@@ -1286,6 +1351,7 @@ maps.prototype.drawAnimateFrame = function (animate, centerX, centerY, index) {
core.canvas.animate.drawImage(image, -realWidth/2 - core.bigmap.offsetX, -realHeight/2 - core.bigmap.offsetY, realWidth, realHeight);
core.loadCanvas('animate');
}
+ core.setAlpha('animate', 1);
})
}
@@ -1338,7 +1404,8 @@ maps.prototype.setFloorImage = function (type, loc, floorId, callback) {
if (type!='show') type='hide';
if (typeof loc[0] == 'number' && typeof loc[1] == 'number')
loc = [loc];
- floorId = floorId||core.status.floorId;
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
if (loc.length==0) return;
loc.forEach(function (t) {
@@ -1360,7 +1427,8 @@ maps.prototype.setBgFgMap = function (type, name, loc, floorId, callback) {
if (name!='fg') name='bg';
if (typeof loc[0] == 'number' && typeof loc[1] == 'number')
loc = [loc];
- floorId = floorId||core.status.floorId;
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
if (loc.length==0) return;
loc.forEach(function (t) {
@@ -1379,7 +1447,8 @@ maps.prototype.setBgFgMap = function (type, name, loc, floorId, callback) {
}
maps.prototype.resetMap = function(floorId) {
- var floorId = floorId||core.status.floorId;
+ floorId = floorId || core.status.floorId;
+ if (!core.isset(floorId)) return;
core.status.maps[floorId] = this.loadFloor(floorId);
if (floorId==core.status.floorId) {
this.drawMap(floorId, function () {
diff --git a/libs/ui.js b/libs/ui.js
index 948e9912..635d0221 100644
--- a/libs/ui.js
+++ b/libs/ui.js
@@ -144,7 +144,7 @@ ui.prototype.setAlpha = function (map, alpha) {
else core.canvas[map].globalAlpha = alpha;
}
-////// 设置某个canvas的透明度 //////
+////// 设置某个canvas的透明度;尽量不要使用本函数,而是全部换成setAlpha实现 //////
ui.prototype.setOpacity = function (map, opacity) {
if (map == 'all') {
for (var m in core.canvas) {
@@ -186,10 +186,9 @@ ui.prototype.closePanel = function () {
////// 左上角绘制一段提示 //////
ui.prototype.drawTip = function (text, itemIcon) {
- var textX, textY, width, height, hide = false, opacityVal = 0;
+ var textX, textY, width, height, hide = false, alpha = 0;
clearInterval(core.interval.tipAnimate);
core.setFont('data', "16px Arial");
- core.setOpacity('data', 0);
core.canvas.data.textAlign = 'left';
if (!core.isset(itemIcon)) {
textX = 16;
@@ -205,22 +204,22 @@ ui.prototype.drawTip = function (text, itemIcon) {
}
core.interval.tipAnimate = window.setInterval(function () {
if (hide) {
- opacityVal -= 0.1;
+ alpha -= 0.1;
}
else {
- opacityVal += 0.1;
+ alpha += 0.1;
}
- core.setOpacity('data', opacityVal);
- core.clearMap('data', 5, 5, 400, height);
+ core.clearMap('data', 5, 5, 416, height);
+ core.setAlpha('data', alpha);
core.fillRect('data', 5, 5, width, height, '#000');
if (core.isset(itemIcon)) {
core.canvas.data.drawImage(core.material.images.items, 0, itemIcon * 32, 32, 32, 10, 8, 32, 32);
}
core.fillText('data', text, textX + 5, textY + 15, '#fff');
- if (opacityVal > 0.6 || opacityVal < 0) {
+ core.setAlpha('data', 1);
+ if (alpha > 0.6 || alpha < 0) {
if (hide) {
- core.clearMap('data', 5, 5, 400, height);
- core.setOpacity('data', 1);
+ core.clearMap('data', 5, 5, 416, height);
clearInterval(core.interval.tipAnimate);
return;
}
@@ -231,8 +230,7 @@ ui.prototype.drawTip = function (text, itemIcon) {
core.timeout.getItemTipTimeout = null;
}, 750);
}
- opacityVal = 0.6;
- core.setOpacity('data', opacityVal);
+ alpha = 0.6;
}
}
}, 30);
@@ -500,6 +498,20 @@ ui.prototype.drawTextBox = function(content, showAll) {
core.status.boxAnimateObjs = [];
core.clearMap('ui');
+ // drawImage
+ content = content.replace(/(\f|\\f)\[(.*?)]/g, function (text, sympol, str) {
+ var ss = str.split(",");
+ if (ss.length!=3 && ss.length!=5) return "";
+ var img = core.material.images.images[ss[0]];
+ if (!core.isset(img)) return "";
+ // 绘制
+ if (ss.length==3)
+ core.canvas.ui.drawImage(img, parseFloat(ss[1]), parseFloat(ss[2]));
+ else
+ core.canvas.ui.drawImage(img, 0, 0, img.width, img.height, parseFloat(ss[1]), parseFloat(ss[2]), parseFloat(ss[3]), parseFloat(ss[4]));
+ return "";
+ });
+
var globalFont = core.status.globalAttribute.font;
var font = textfont + 'px '+globalFont;
if (textAttribute.bold) font = "bold "+font;
@@ -519,9 +531,13 @@ ui.prototype.drawTextBox = function(content, showAll) {
width = validWidth + leftSpace + rightSpace;
// left必须在7~416-7-width区间内,以保证left>=7,right<=416-7
left = core.clamp(32*px+16-width/2, 7, 416-7-width);
+
+ left -= core.bigmap.offsetX;
+
right = left + width;
}
+
var content_left = left + leftSpace;
var height = 30 + (textfont+5)*core.splitLines("ui", realContent, validWidth, font).length;
if (core.isset(name)) height += titlefont + 5;
@@ -541,20 +557,24 @@ ui.prototype.drawTextBox = function(content, showAll) {
else if (position=='up') {
if (px==null || py==null)
top = 5 + offset;
- else
+ else {
top = 32 * py - height - ydelta - yoffset;
+ top -= core.bigmap.offsetY;
+ }
}
else if (position=='down') {
if (px==null || py==null)
top = 416 - height - 5 - offset;
- else
+ else {
top = 32 * py + 32 + yoffset;
+ top -= core.bigmap.offsetY;
+ }
}
var bottom = top + height;
if (isWindowSkin) {
core.setAlpha('ui', alpha);
- this.drawWindowSkin(background,'ui',left,top,width,height,position,px==null?null:px*32,py==null?null:py*32);
+ this.drawWindowSkin(background,'ui',left,top,width,height,position,px==null?null:px*32-core.bigmap.offsetX,py==null?null:py*32-core.bigmap.offsetY);
core.setAlpha('ui', 1);
}
else {
@@ -569,17 +589,17 @@ ui.prototype.drawTextBox = function(content, showAll) {
canvas.moveTo(left,top);
// 上边缘
if (position=='down' && core.isset(px) && core.isset(py)) {
- canvas.lineTo(32*px+xoffset, top);
- canvas.lineTo(32*px+16, top-yoffset);
- canvas.lineTo(32*(px+1)-xoffset, top);
+ canvas.lineTo(32*px+xoffset - core.bigmap.offsetX, top);
+ canvas.lineTo(32*px+16 - core.bigmap.offsetX, top-yoffset);
+ canvas.lineTo(32*(px+1)-xoffset - core.bigmap.offsetX, top);
}
canvas.lineTo(right, top);
canvas.lineTo(right, bottom);
// 下边缘
if (position=='up' && core.isset(px) && core.isset(py)) {
- canvas.lineTo(32*(px+1)-xoffset, bottom);
- canvas.lineTo(32*px+16, bottom+yoffset);
- canvas.lineTo(32*px+xoffset, bottom);
+ canvas.lineTo(32*(px+1)-xoffset - core.bigmap.offsetX, bottom);
+ canvas.lineTo(32*px+16 - core.bigmap.offsetX, bottom+yoffset);
+ canvas.lineTo(32*px+xoffset - core.bigmap.offsetX, bottom);
}
canvas.lineTo(left, bottom);
canvas.closePath();
@@ -911,7 +931,7 @@ ui.prototype.drawSettings = function () {
core.status.event.id = 'settings';
this.drawChoices(null, [
- "系统设置", "虚拟键盘", "浏览地图", "绘图模式", "同步存档", "数据统计", "查看评论", "操作帮助", "关于本塔", "返回标题", "返回游戏"
+ "系统设置", "虚拟键盘", "浏览地图", "绘图模式", "同步存档", "游戏信息", "返回标题", "返回游戏"
]);
}
@@ -1010,16 +1030,13 @@ ui.prototype.drawBattleAnimate = function(monsterId, callback) {
var top = (416-height)/2, bottom = height;
- // var left = 97, top = 64, right = 416 - 2 * left, bottom = 416 - 2 * top;
- core.setAlpha('ui', 0.85);
- core.fillRect('ui', left, top, right, bottom, '#000000');
+ core.fillRect('ui', left, top, right, bottom, 'rgba(0,0,0,0.85)');
core.setAlpha('ui', 1);
core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2);
core.clearMap('data');
clearInterval(core.interval.tipAnimate);
core.setAlpha('data', 1);
- core.setOpacity('data', 1);
core.status.boxAnimateObjs = [];
var globalFont = core.status.globalAttribute.font;
@@ -1307,6 +1324,13 @@ ui.prototype.drawReplay = function () {
]);
}
+ui.prototype.drawGameInfo = function () {
+ core.status.event.id = 'gameInfo';
+ this.drawChoices(null, [
+ "数据统计", "查看评论", "操作帮助", "关于本塔", "返回上级菜单"
+ ]);
+}
+
////// 绘制分页 //////
ui.prototype.drawPagination = function (page, totalPage, top) {
// if (totalPage13 || mh>13)) text+=" ["+(x-6)+","+(y-6)+"]";
var textX = 16, textY = 18, width = textX + core.canvas.data.measureText(text).width + 16, height = 42;
- core.fillRect('data', 5, 5, width, height, '#000');
- core.setOpacity('data', 0.4);
- core.fillText('data', text, textX + 5, textY + 15, '#fff');
-
+ core.fillRect('data', 5, 5, width, height, 'rgba(0,0,0,0.4)');
+ core.fillText('data', text, textX + 5, textY + 15, 'rgba(255,255,255,0.6)');
}
////// 绘制道具栏 //////
@@ -2574,7 +2591,6 @@ ui.prototype.drawPaint = function () {
core.clearMap('route');
core.setAlpha('route', 1);
- core.setOpacity('route', 1);
// 将已有的内容绘制到route上
var value = core.paint[core.status.floorId];
diff --git a/main.js b/main.js
index 9285f889..2ff39470 100644
--- a/main.js
+++ b/main.js
@@ -98,7 +98,14 @@ function main() {
'shop': document.getElementById("img-shop"),
'save': document.getElementById("img-save"),
'load': document.getElementById("img-load"),
- 'settings': document.getElementById("img-settings")
+ 'settings': document.getElementById("img-settings"),
+ 'btn1': document.getElementById("img-btn1"),
+ 'btn2': document.getElementById("img-btn2"),
+ 'btn3': document.getElementById("img-btn3"),
+ 'btn4': document.getElementById("img-btn4"),
+ 'btn5': document.getElementById("img-btn5"),
+ 'btn6': document.getElementById("img-btn6"),
+ 'btn7': document.getElementById("img-btn7")
},
'icons': {
'floor': 0,
@@ -132,6 +139,13 @@ function main() {
'erase': 27,
'empty': 28,
'exit': 29,
+ 'btn1': 30,
+ 'btn2': 31,
+ 'btn3': 32,
+ 'btn4': 33,
+ 'btn5': 34,
+ 'btn6': 35,
+ 'btn7': 36
},
'floor': document.getElementById('floor'),
'name': document.getElementById('name'),
@@ -386,7 +400,9 @@ main.dom.data.ontouchend = function (e) {
}
////// 点击状态栏中的怪物手册时 //////
-main.statusBar.image.book.onclick = function () {
+main.statusBar.image.book.onclick = function (e) {
+ e.stopPropagation();
+
if (core.isset(core.status.replay) && core.status.replay.replaying) {
core.triggerReplay();
return;
@@ -402,7 +418,8 @@ main.statusBar.image.book.onclick = function () {
}
////// 点击状态栏中的楼层传送器/装备栏时 //////
-main.statusBar.image.fly.onclick = function () {
+main.statusBar.image.fly.onclick = function (e) {
+ e.stopPropagation();
// 播放录像时
if (core.isset(core.status.replay) && core.status.replay.replaying) {
@@ -427,7 +444,8 @@ main.statusBar.image.fly.onclick = function () {
}
////// 点击状态栏中的工具箱时 //////
-main.statusBar.image.toolbox.onclick = function () {
+main.statusBar.image.toolbox.onclick = function (e) {
+ e.stopPropagation();
if (core.isset(core.status.replay) && core.status.replay.replaying) {
core.rewindReplay();
@@ -445,7 +463,8 @@ main.statusBar.image.toolbox.onclick = function () {
}
////// 双击状态栏中的工具箱时 //////
-main.statusBar.image.toolbox.ondblclick = function () {
+main.statusBar.image.toolbox.ondblclick = function (e) {
+ e.stopPropagation();
if (core.isset(core.status.replay) && core.status.replay.replaying) {
core.rewindReplay();
@@ -458,7 +477,8 @@ main.statusBar.image.toolbox.ondblclick = function () {
}
////// 点击状态栏中的快捷商店时 //////
-main.statusBar.image.shop.onclick = function () {
+main.statusBar.image.shop.onclick = function (e) {
+ e.stopPropagation();
if (core.isset(core.status.replay) && core.status.replay.replaying) {
core.bookReplay();
@@ -470,7 +490,8 @@ main.statusBar.image.shop.onclick = function () {
}
////// 点击状态栏中的存档按钮时 //////
-main.statusBar.image.save.onclick = function () {
+main.statusBar.image.save.onclick = function (e) {
+ e.stopPropagation();
if (core.isset(core.status.replay) && core.status.replay.replaying) {
core.speedDownReplay();
@@ -487,7 +508,8 @@ main.statusBar.image.save.onclick = function () {
}
////// 点击状态栏中的读档按钮时 //////
-main.statusBar.image.load.onclick = function () {
+main.statusBar.image.load.onclick = function (e) {
+ e.stopPropagation();
if (core.isset(core.status.replay) && core.status.replay.replaying) {
core.speedUpReplay();
@@ -504,7 +526,8 @@ main.statusBar.image.load.onclick = function () {
}
////// 点击状态栏中的系统菜单时 //////
-main.statusBar.image.settings.onclick = function () {
+main.statusBar.image.settings.onclick = function (e) {
+ e.stopPropagation();
if (core.isset(core.status.replay) && core.status.replay.replaying) {
core.saveReplay();
@@ -520,18 +543,53 @@ main.statusBar.image.settings.onclick = function () {
main.core.openSettings(true);
}
+////// 点击工具栏时 //////
+main.dom.toolBar.onclick = function () {
+ if (core.isset(core.status.replay) && core.status.replay.replaying)
+ return;
+ main.core.control.setToolbarButton(!core.domStyle.toolbarBtn);
+}
+
+////// 手机端的按钮1-7 //////
+main.statusBar.image.btn1.onclick = function (e) {
+ e.stopPropagation();
+ main.core.onkeyUp({"keyCode": 49});
+};
+
+main.statusBar.image.btn2.onclick = function (e) {
+ e.stopPropagation();
+ main.core.onkeyUp({"keyCode": 50});
+};
+
+main.statusBar.image.btn3.onclick = function (e) {
+ e.stopPropagation();
+ main.core.onkeyUp({"keyCode": 51});
+};
+
+main.statusBar.image.btn4.onclick = function (e) {
+ e.stopPropagation();
+ main.core.onkeyUp({"keyCode": 52});
+};
+
+main.statusBar.image.btn5.onclick = function (e) {
+ e.stopPropagation();
+ main.core.onkeyUp({"keyCode": 53});
+};
+
+main.statusBar.image.btn6.onclick = function (e) {
+ e.stopPropagation();
+ main.core.onkeyUp({"keyCode": 54});
+};
+
+main.statusBar.image.btn7.onclick = function (e) {
+ e.stopPropagation();
+ main.core.onkeyUp({"keyCode": 55});
+};
+
////// 点击“开始游戏”时 //////
main.dom.playGame.onclick = function () {
main.dom.startButtons.style.display='none';
-
- if (main.core.isset(main.core.musicStatus) && main.core.musicStatus.startDirectly
- && main.core.musicStatus.bgmStatus) {
- if (main.core.musicStatus.playingBgm==null
- || core.material.bgms[main.core.musicStatus.playingBgm].paused) {
- main.core.musicStatus.playingBgm=null;
- main.core.playBgm(main.core.bgms[0]);
- }
- }
+ main.core.control.checkBgm();
if (main.core.isset(main.core.flags.startDirectly) && main.core.flags.startDirectly) {
core.events.startGame("");
@@ -543,32 +601,14 @@ main.dom.playGame.onclick = function () {
////// 点击“载入游戏”时 //////
main.dom.loadGame.onclick = function() {
-
- if (main.core.isset(main.core.musicStatus) && main.core.musicStatus.startDirectly
- && main.core.musicStatus.bgmStatus) {
- if (main.core.musicStatus.playingBgm==null
- || core.material.bgms[main.core.musicStatus.playingBgm].paused) {
- main.core.musicStatus.playingBgm=null;
- main.core.playBgm(main.core.bgms[0]);
- }
- }
-
+ main.core.control.checkBgm();
main.core.load();
}
////// 点击“录像回放”时 //////
main.dom.replayGame.onclick = function () {
-
- if (main.core.isset(main.core.musicStatus) && main.core.musicStatus.startDirectly
- && main.core.musicStatus.bgmStatus) {
- if (main.core.musicStatus.playingBgm==null
- || core.material.bgms[main.core.musicStatus.playingBgm].paused) {
- main.core.musicStatus.playingBgm=null;
- main.core.playBgm(main.core.bgms[0]);
- }
- }
-
- core.chooseReplayFile();
+ main.core.control.checkBgm();
+ main.core.chooseReplayFile();
}
diff --git a/project/data.js b/project/data.js
index d2697561..9b4ac12e 100644
--- a/project/data.js
+++ b/project/data.js
@@ -1,4 +1,4 @@
-var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
+var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
{
"main": {
"floorIds": [
@@ -103,6 +103,126 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"flags": {},
"steps": 0
},
+ "startCanvas": [
+ {
+ "type": "comment",
+ "text": "在这里可以用事件来自定义绘制标题界面的背景图等"
+ },
+ {
+ "type": "showImage",
+ "name": "bg.jpg",
+ "loc": [
+ 0,
+ 0
+ ]
+ },
+ {
+ "type": "comment",
+ "text": "给用户提供选择项,这里简单的使用了choices事件"
+ },
+ {
+ "type": "comment",
+ "text": "也可以贴按钮图然后使用循环处理+等待操作来完成"
+ },
+ {
+ "type": "choices",
+ "choices": [
+ {
+ "text": "开始游戏",
+ "action": [
+ {
+ "type": "comment",
+ "text": "检查bgm状态,下同"
+ },
+ {
+ "type": "function",
+ "function": "function(){\ncore.control.checkBgm()\n}"
+ },
+ {
+ "type": "if",
+ "condition": "core.flags.startDirectly",
+ "true": [
+ {
+ "type": "comment",
+ "text": "直接开始游戏,设置初始化数据"
+ },
+ {
+ "type": "function",
+ "function": "function(){\ncore.events.setInitData('')\n}"
+ }
+ ],
+ "false": [
+ {
+ "type": "comment",
+ "text": "动态生成难度选择项"
+ },
+ {
+ "type": "function",
+ "function": "function(){\nvar choices = [];\nmain.levelChoose.forEach(function (one) {\n\tchoices.push({\"text\": one[0], \"action\": [\n\t\t{\"type\": \"function\", \"function\": \"function() { core.status.hard = '\"+one[1]+\"'; core.events.setInitData('\"+one[1]+\"'); }\"}\n\t]});\n})\ncore.insertAction({\"type\": \"choices\", \"choices\": choices});\n}"
+ }
+ ]
+ },
+ {
+ "type": "showImage"
+ },
+ {
+ "type": "comment",
+ "text": "成功选择难度"
+ }
+ ]
+ },
+ {
+ "text": "读取存档",
+ "action": [
+ {
+ "type": "function",
+ "function": "function(){\ncore.control.checkBgm()\n}"
+ },
+ {
+ "type": "showImage"
+ },
+ {
+ "type": "comment",
+ "text": "这段代码会结束事件,打开读档页面,读取存档或重新开始"
+ },
+ {
+ "type": "function",
+ "function": "function(){\ncore.insertAction([{\"type\": \"exit\"}], null, null, function() {\n\tcore.status.played = false;\n\tcore.load();\n})\n}"
+ },
+ {
+ "type": "comment",
+ "text": "不管读档有没有成功,都会重新开始,这个地方不会被执行到"
+ }
+ ]
+ },
+ {
+ "text": "回放录像",
+ "action": [
+ {
+ "type": "function",
+ "function": "function(){\ncore.control.checkBgm()\n}"
+ },
+ {
+ "type": "comment",
+ "text": "这段代码会结束事件,选择录像文件,播放录像或重新开始"
+ },
+ {
+ "type": "function",
+ "function": "function(){\ncore.insertAction([{\"type\": \"exit\"}], null, null, function() {\n\tcore.restart();\n\tcore.chooseReplayFile();\n})\n}"
+ },
+ {
+ "type": "comment",
+ "text": "不管录像有没有成功,都会重新开始,这个地方不会被执行到"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "comment",
+ "text": "接下来会执行startText中的事件"
+ }
+ ],
"startText": [
"Hi,欢迎来到 HTML5 魔塔样板!\n\n本样板由艾之葵制作,可以让你在不会写任何代码\n的情况下也能做出属于自己的H5魔塔!",
"这里游戏开始时的剧情。\n定义在data.js的startText处。\n\n你可以在这里写上自己的内容。",
@@ -217,7 +337,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"counterAttack": 0.1,
"purify": 3,
"hatred": 2,
- "maxValidHp": null,
+ "moveSpeed": 100,
"animateSpeed": 300
},
"flags": {
@@ -248,6 +368,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"hatredDecrease": true,
"betweenAttackCeil": false,
"useLoop": false,
+ "startUsingCanvas": false,
"startDirectly": false,
"canOpenBattleAnimate": true,
"showBattleAnimateConfirm": false,
diff --git a/project/functions.js b/project/functions.js
index c6ee7084..ef3be11d 100644
--- a/project/functions.js
+++ b/project/functions.js
@@ -1,4 +1,4 @@
-var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
+var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
{
"events": {
"initGame": function() {
@@ -59,7 +59,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.stopReplay();
core.waitHeroToStop(function() {
core.removeGlobalAnimate(0,0,true);
- core.clearMap('all'); // 清空全地图
+ core.clearMap('all'); core.clearMap('curtain'); // 清空全地图
// 请注意:
// 成绩统计时是按照hp进行上传并排名,因此光在这里改${status:hp}是无效的
// 如需按照其他的的分数统计方式,请先将hp设置为你的得分
@@ -93,6 +93,10 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
visited.push(floorId);
core.setFlag("__visited__", visited);
}
+ // 每次抵达楼层时执行的事件
+ if (!fromLoad) {
+ core.insertAction(core.floors[floorId].eachArrive);
+ }
},
"addPoint": function (enemy) {
// 加点事件
diff --git a/project/images/icons.png b/project/images/icons.png
index 75301f33..c5a383c6 100644
Binary files a/project/images/icons.png and b/project/images/icons.png differ
diff --git a/常用工具/地图生成器.exe b/常用工具/地图生成器.exe
index 98510404..a17d95e4 100644
Binary files a/常用工具/地图生成器.exe and b/常用工具/地图生成器.exe differ