Merge pull request #315 from ckcz123/v2.0

V2.0
This commit is contained in:
Zhang Chen 2019-02-04 17:35:36 +08:00 committed by GitHub
commit aa4c3a9251
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 836 additions and 414 deletions

View File

@ -53,6 +53,23 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
## 更新说明 ## 更新说明
### 2019.2.4 V2.5.4
* [x] 发布15x15的版本
* [x] 支持多重装备(一个装备可以装到多个孔上)
* [x] 工具栏按钮增添至8个快捷商店和虚拟键盘同时显示
* [x] 点击状态栏的金币图标也可以打开快捷商店
* [x] 等待事件提供flag:px和flag:py在0~415之间
* [x] 事件:呼出存读档界面;呼出怪物手册
* [x] 事件:使用道具,暂停背景音乐,暂停所有音效
* [x] type:trigger可以触发系统事件
* [x] 独立开关
* [x] 贴图也可以支持帧动画了
* [x] 图块内置颜色选择器
* [x] 标题界面增加音乐按钮
* [x] 等待事件可被Ctrl长按跳过
* [x] 部分Bug修复大量细节优化性能进一步得到提升
### 2018.12.22 V2.5.3 ### 2018.12.22 V2.5.3
* [x] 标题界面事件化;现在可以用事件流来处理标题界面了 * [x] 标题界面事件化;现在可以用事件流来处理标题界面了

View File

@ -1,5 +1,7 @@
# editor # editor
>! 以下均是v2.0时的说明, 未及时改动
本目录下所有文件,以及`../editor.html`和`../启动服务.exe`([源码](http://github.com/ckcz123/mota-js-server/))是地图编辑器的所有组件. 本目录下所有文件,以及`../editor.html`和`../启动服务.exe`([源码](http://github.com/ckcz123/mota-js-server/))是地图编辑器的所有组件.
`editor.js`,`editor_file.js`和`editor_mode.js`耦合较强,`editor_blockly.js`和`editor_multi.js`和`fs.js`基本可以独立使用. `editor.js`,`editor_file.js`和`editor_mode.js`耦合较强,`editor_blockly.js`和`editor_multi.js`和`fs.js`基本可以独立使用.
@ -103,23 +105,6 @@ editor_mode.onmode(editor_mode._ids[node.getAttribute('id')]);
`editor.mode.listen`中提供了追加素材的支持. `editor.mode.listen`中提供了追加素材的支持.
处理注释的特殊指令
```
$range(evalstr:thiseval)$end
限制取值范围,要求修改后的eval(evalstr)为true
$leaf(evalstr:thiseval)$end
强制指定为叶节点,如果eval(evalstr)为true
//以下几个中选一个 [
$select(evalstr)$end
渲染成<select>,选项为数组eval(evalstr)['values']
$input(evalstr)$end
渲染成<input>
$textarea(evalstr)$end
渲染成<textarea>
默认选项为$textarea()$end
// ]
```
### editor_blockly.js ### editor_blockly.js
@ -177,9 +162,3 @@ fs.readdir(path, callback)
//所有参数不允许缺省 //所有参数不允许缺省
``` ```
## z-index
目前主体部分使用了 0-15,75,100
blockly使用 200,201
多行文本编辑器使用 300

View File

@ -26,17 +26,6 @@ code=JSON.stringify(code,null,2).split('"data_asdfefw"').join('[\n'+action_0+']\
return code; return code;
*/; */;
//加点 事件编辑器入口之一
point_m
: '加点' BGNL? Newline choicesContext+ BEND
/* point_m
tooltip : 加点事件
helpUrl : https://h5mota.com/games/template/docs/#/event?id=%e5%8a%a0%e7%82%b9%e4%ba%8b%e4%bb%b6
var code = '{"type": "choices", "choices": [\n'+choicesContext_0+']}\n';
return code;
*/;
//升级 事件编辑器入口之一 //升级 事件编辑器入口之一
level_m level_m
@ -217,6 +206,18 @@ var code = '{"floorId": "'+toFloorId+'"'+loc+DirectionEx_List_0+Int_0+Bool_0+' }
return code; return code;
*/; */;
//commonEvent 事件编辑器入口之一
commonEvent_m
: '公共事件' BGNL? Newline action+ BEND
/* commonEvent_m
tooltip : 公共事件
helpUrl : https://h5mota.com/games/template/docs/#/event
var code = '[\n'+action_0+']\n';
return code;
*/;
//为了避免关键字冲突,全部加了_s //为了避免关键字冲突,全部加了_s
//动作 //动作
action action
@ -235,7 +236,8 @@ action
| show_s | show_s
| hide_s | hide_s
| trigger_s | trigger_s
| insert_s | insert_1_s
| insert_2_s
| revisit_s | revisit_s
| exit_s | exit_s
| setBlock_s | setBlock_s
@ -284,6 +286,7 @@ action
| loadBgm_s | loadBgm_s
| freeBgm_s | freeBgm_s
| playSound_s | playSound_s
| stopSound_s
| setVolume_s | setVolume_s
| win_s | win_s
| lose_s | lose_s
@ -598,13 +601,26 @@ var code = '{"type": "trigger", "loc": ['+PosString_0+','+PosString_1+']},\n';
return code; return code;
*/; */;
insert_s insert_1_s
: '插入公共事件' EvalString Newline
/* insert_1_s
tooltip : insert: 插入公共事件并执行
helpUrl : https://h5mota.com/games/template/docs/#/event?id=insert%ef%bc%9a%e6%8f%92%e5%85%a5%e5%85%ac%e5%85%b1%e4%ba%8b%e4%bb%b6%e6%88%96%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6%e5%b9%b6%e6%89%a7%e8%a1%8c
default : ["加点事件"]
colour : this.eventColor
var code = '{"type": "insert", "name": "'+EvalString_0+'"},\n';
return code;
*/;
insert_2_s
: '插入事件' 'x' PosString ',' 'y' PosString '楼层' IdString? Newline : '插入事件' 'x' PosString ',' 'y' PosString '楼层' IdString? Newline
/* insert_s /* insert_2_s
tooltip : insert: 立即插入另一个地点的事件执行,当前事件不会中断,事件坐标不会改变 tooltip : insert: 立即插入另一个地点的事件执行,当前事件不会中断,事件坐标不会改变
helpUrl : https://h5mota.com/games/template/docs/#/event?id=insert%ef%bc%9a%e6%8f%92%e5%85%a5%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6 helpUrl : https://h5mota.com/games/template/docs/#/event?id=insert%ef%bc%9a%e6%8f%92%e5%85%a5%e5%85%ac%e5%85%b1%e4%ba%8b%e4%bb%b6%e6%88%96%e5%8f%a6%e4%b8%80%e4%b8%aa%e5%9c%b0%e7%82%b9%e7%9a%84%e4%ba%8b%e4%bb%b6%e5%b9%b6%e6%89%a7%e8%a1%8c
default : ["0","0",""] default : ["0","0",""]
colour : this.eventColor colour : this.eventColor
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
@ -785,7 +801,7 @@ setBgFgBlock_s
/* setBgFgBlock_s /* setBgFgBlock_s
tooltip : setBgFgBlock设置某个图层块,忽略坐标楼层则为当前点 tooltip : setBgFgBlock设置某个图层块,忽略坐标楼层则为当前点
helpUrl : https://h5mota.com/games/template/docs/#/event?id=setblock%EF%BC%9A%E8%AE%BE%E7%BD%AE%E6%9F%90%E4%B8%AA%E5%9B%BE%E5%9D%97 helpUrl : https://h5mota.com/games/template/docs/#/event?id=setblock%EF%BC%9A%E8%AE%BE%E7%BD%AE%E6%9F%90%E4%B8%AA%E5%9B%BE%E5%9D%97
colour : this.eventColor colour : this.dataColor
default : ["bg",0,"","",""] default : ["bg",0,"","",""]
var floorstr = ''; var floorstr = '';
if (PosString_0 && PosString_1) { if (PosString_0 && PosString_1) {
@ -889,20 +905,21 @@ return code;
*/; */;
openDoor_s openDoor_s
: '开门' 'x' PosString? ',' 'y' PosString? '楼层' IdString? Newline : '开门' 'x' PosString? ',' 'y' PosString? '楼层' IdString? '需要钥匙' Bool? Newline
/* openDoor_s /* openDoor_s
tooltip : openDoor: 开门,楼层可不填表示当前层 tooltip : openDoor: 开门,楼层可不填表示当前层
helpUrl : https://h5mota.com/games/template/docs/#/event?id=opendoor%EF%BC%9A%E5%BC%80%E9%97%A8 helpUrl : https://h5mota.com/games/template/docs/#/event?id=opendoor%EF%BC%9A%E5%BC%80%E9%97%A8
default : ["","",""] default : ["","","",false]
colour : this.dataColor colour : this.dataColor
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"'); IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
var floorstr = ''; var floorstr = '';
if (PosString_0 && PosString_1) { if (PosString_0 && PosString_1) {
floorstr = ', "loc": ['+PosString_0+','+PosString_1+']'; floorstr = ', "loc": ['+PosString_0+','+PosString_1+']';
} }
var code = '{"type": "openDoor"'+floorstr+IdString_0+'},\n'; Bool_0 = Bool_0 ? ', "needKey": true' : '';
var code = '{"type": "openDoor"'+floorstr+IdString_0+Bool_0+'},\n';
return code; return code;
*/; */;
@ -1366,6 +1383,18 @@ var code = '{"type": "playSound", "name": "'+EvalString_0+'"},\n';
return code; return code;
*/; */;
stopSound_s
: '停止所有音效' Newline
/* stopSound_s
tooltip : stopSound: 停止所有音效
helpUrl : https://h5mota.com/games/template/docs/#/event?id=stopSound%ef%bc%9a%e5%81%9c%e6%ad%a2%e6%89%80%e6%9c%89%e9%9f%b3%e6%95%88
colour : this.soundColor
var code = '{"type": "stopSound"},\n';
return code;
*/;
setVolume_s setVolume_s
: '设置音量' Int '渐变时间' Int? '不等待执行完毕' Bool Newline : '设置音量' Int '渐变时间' Int? '不等待执行完毕' Bool Newline
@ -1960,15 +1989,6 @@ ActionParser.prototype.parse = function (obj,type) {
obj.time,!this.isset(obj.portalWithoutTrigger) obj.time,!this.isset(obj.portalWithoutTrigger)
]); ]);
case 'point':
if(!obj)obj={};
var text_choices = null;
for(var ii=obj.choices.length-1,choice;choice=obj.choices[ii];ii--) {
text_choices=MotaActionBlocks['choicesContext'].xmlText([
choice.text,this.parseList(choice.action),text_choices]);
}
return MotaActionBlocks['point_m'].xmlText([text_choices]);
case 'level': case 'level':
if(!obj)obj={}; if(!obj)obj={};
var text_choices = null; var text_choices = null;
@ -2264,7 +2284,7 @@ ActionParser.prototype.parseAction = function() {
case "openDoor": // 开一个门, 包括暗墙 case "openDoor": // 开一个门, 包括暗墙
data.loc=data.loc||['',''] data.loc=data.loc||['','']
this.next = MotaActionBlocks['openDoor_s'].xmlText([ this.next = MotaActionBlocks['openDoor_s'].xmlText([
data.loc[0],data.loc[1],data.floorId||'',this.next]); data.loc[0],data.loc[1],data.floorId||'',data.needKey||false,this.next]);
break; break;
case "useItem": // 使用道具 case "useItem": // 使用道具
this.next = MotaActionBlocks['useItem_s'].xmlText([ this.next = MotaActionBlocks['useItem_s'].xmlText([
@ -2287,8 +2307,14 @@ ActionParser.prototype.parseAction = function() {
data.loc[0],data.loc[1],this.next]); data.loc[0],data.loc[1],this.next]);
break; break;
case "insert": // 强制插入另一个点的事件在当前事件列表执行,当前坐标和楼层不会改变 case "insert": // 强制插入另一个点的事件在当前事件列表执行,当前坐标和楼层不会改变
this.next = MotaActionBlocks['insert_s'].xmlText([ if (this.isset(data.name)) {
this.next = MotaActionBlocks['insert_1_s'].xmlText([
data.name, this.next]);
}
else {
this.next = MotaActionBlocks['insert_2_s'].xmlText([
data.loc[0],data.loc[1],data.floorId||'',this.next]); data.loc[0],data.loc[1],data.floorId||'',this.next]);
}
break; break;
case "playSound": case "playSound":
this.next = MotaActionBlocks['playSound_s'].xmlText([ this.next = MotaActionBlocks['playSound_s'].xmlText([
@ -2314,6 +2340,10 @@ ActionParser.prototype.parseAction = function() {
this.next = MotaActionBlocks['freeBgm_s'].xmlText([ this.next = MotaActionBlocks['freeBgm_s'].xmlText([
data.name,this.next]); data.name,this.next]);
break break
case "stopSound":
this.next = MotaActionBlocks['stopSound_s'].xmlText([
this.next]);
break
case "setVolume": case "setVolume":
this.next = MotaActionBlocks['setVolume_s'].xmlText([ this.next = MotaActionBlocks['setVolume_s'].xmlText([
data.value, data.time||0, data.async||false, this.next]); data.value, data.time||0, data.async||false, this.next]);

View File

@ -62,6 +62,7 @@ editor.prototype.init = function (callback) {
editor.mode.floor(); editor.mode.floor();
editor.mode.tower(); editor.mode.tower();
editor.mode.functions(); editor.mode.functions();
editor.mode.commonevent();
editor.mode.showMode('tower'); editor.mode.showMode('tower');
editor_multi = editor_multi(); editor_multi = editor_multi();

View File

@ -23,17 +23,6 @@ editor_blockly = function () {
{"type": "hide", "time": 500}, {"type": "hide", "time": 500},
],'event'), ],'event'),
MotaActionBlocks['changeFloor_m'].xmlText(), MotaActionBlocks['changeFloor_m'].xmlText(),
//MotaActionFunctions.actionParser.parse({"type": "choices", "choices": [
// {"text": "攻击+\${point}", "action": [
// {"type": "setValue", "name": "status:atk", "value": "status:atk+\${point}"},
// ]},
// {"text": "防御+\${2*point}", "action": [
// {"type": "setValue", "name": "status:def", "value": "status:def+\${2*point}"},
// ]},
// {"text": "生命+\${200*point}", "action": [
// {"type": "setValue", "name": "status:hp", "value": "status:hp+\${200*point}"},
// ]},
//]},'point'),
MotaActionFunctions.actionParser.parse([{ MotaActionFunctions.actionParser.parse([{
"id": "moneyShop1", "id": "moneyShop1",
"name": "贪婪之神", "name": "贪婪之神",
@ -55,6 +44,7 @@ editor_blockly = function () {
MotaActionBlocks['firstArrive_m'].xmlText(), MotaActionBlocks['firstArrive_m'].xmlText(),
MotaActionBlocks['eachArrive_m'].xmlText(), MotaActionBlocks['eachArrive_m'].xmlText(),
MotaActionBlocks['level_m'].xmlText(), MotaActionBlocks['level_m'].xmlText(),
MotaActionBlocks['commonEvent_m'].xmlText(),
], ],
'显示文字':[ '显示文字':[
MotaActionBlocks['text_0_s'].xmlText(), MotaActionBlocks['text_0_s'].xmlText(),
@ -103,6 +93,7 @@ editor_blockly = function () {
MotaActionBlocks['useItem_s'].xmlText(), MotaActionBlocks['useItem_s'].xmlText(),
MotaActionBlocks['openShop_s'].xmlText(), MotaActionBlocks['openShop_s'].xmlText(),
MotaActionBlocks['setBlock_s'].xmlText(), MotaActionBlocks['setBlock_s'].xmlText(),
MotaActionBlocks['setBgFgBlock_s'].xmlText(),
MotaActionBlocks['setHeroIcon_s'].xmlText(), MotaActionBlocks['setHeroIcon_s'].xmlText(),
MotaActionBlocks['follow_s'].xmlText(), MotaActionBlocks['follow_s'].xmlText(),
MotaActionBlocks['unfollow_s'].xmlText(), MotaActionBlocks['unfollow_s'].xmlText(),
@ -125,9 +116,9 @@ editor_blockly = function () {
MotaActionBlocks['hideFloorImg_s'].xmlText(), MotaActionBlocks['hideFloorImg_s'].xmlText(),
MotaActionBlocks['showBgFgMap_s'].xmlText(), MotaActionBlocks['showBgFgMap_s'].xmlText(),
MotaActionBlocks['hideBgFgMap_s'].xmlText(), MotaActionBlocks['hideBgFgMap_s'].xmlText(),
MotaActionBlocks['setBgFgBlock_s'].xmlText(),
MotaActionBlocks['trigger_s'].xmlText(), MotaActionBlocks['trigger_s'].xmlText(),
MotaActionBlocks['insert_s'].xmlText(), MotaActionBlocks['insert_1_s'].xmlText(),
MotaActionBlocks['insert_2_s'].xmlText(),
MotaActionBlocks['move_s'].xmlText(), MotaActionBlocks['move_s'].xmlText(),
MotaActionBlocks['jump_s'].xmlText(), MotaActionBlocks['jump_s'].xmlText(),
MotaActionBlocks['disableShop_s'].xmlText(), MotaActionBlocks['disableShop_s'].xmlText(),
@ -150,6 +141,7 @@ editor_blockly = function () {
MotaActionBlocks['loadBgm_s'].xmlText(), MotaActionBlocks['loadBgm_s'].xmlText(),
MotaActionBlocks['freeBgm_s'].xmlText(), MotaActionBlocks['freeBgm_s'].xmlText(),
MotaActionBlocks['playSound_s'].xmlText(), MotaActionBlocks['playSound_s'].xmlText(),
MotaActionBlocks['stopSound_s'].xmlText(),
MotaActionBlocks['setVolume_s'].xmlText(), MotaActionBlocks['setVolume_s'].xmlText(),
MotaActionBlocks['callBook_s'].xmlText(), MotaActionBlocks['callBook_s'].xmlText(),
MotaActionBlocks['callSave_s'].xmlText(), MotaActionBlocks['callSave_s'].xmlText(),
@ -607,7 +599,8 @@ function omitedcheckUpdateFunction(event) {
'exit_s', 'exit_s',
'revisit_s', 'revisit_s',
'sleep_s', 'sleep_s',
'setBlock_s' 'setBlock_s',
'insert_1_s'
]; // 最常用的15个图块 ]; // 最常用的15个图块
editor_blockly.lastUsedTypeNum=15; editor_blockly.lastUsedTypeNum=15;

View File

@ -7,6 +7,7 @@ editor_file = function (editor, callback) {
'comment': 'comment', 'comment': 'comment',
'data.comment': 'dataComment', 'data.comment': 'dataComment',
'functions.comment': 'functionsComment', 'functions.comment': 'functionsComment',
'events.comment': 'eventsComment',
} }
for (var key in commentjs) { for (var key in commentjs) {
(function (key) { (function (key) {
@ -49,25 +50,7 @@ editor_file = function (editor, callback) {
throw('未设置callback') throw('未设置callback')
} }
; ;
/* var fs = editor.fs;
fs.readFile('project/floors/'+filename+'.js','utf-8',function(err, data){
if (err!=null){callback(err);return;}
data=data.split('=');
data=[data[0],data.slice(1).join('=')];
var varnameId = data[0].split('.').slice(-1)[0].trim();
var filenameId = filename.split('/').slice(-1)[0].split('\\').slice(-1)[0];
eval('b3917d1d_71c2_41f2_a8aa_481b215ffb99='+data[1]);
var floorData = b3917d1d_71c2_41f2_a8aa_481b215ffb99;
delete(b3917d1d_71c2_41f2_a8aa_481b215ffb99);
var floorId = floorData.floorId;
if (varnameId!=filenameId || filenameId!=floorId){
callback('文件名,第一行的变量名以及floorId不一致');
return;
}
editor.currentFloorId = floorId;
editor.currentFloorData = floorData;
callback(null)
}); */
editor.currentFloorId = editor.core.status.floorId; editor.currentFloorId = editor.core.status.floorId;
editor.currentFloorData = editor.core.floors[editor.currentFloorId]; editor.currentFloorData = editor.core.floors[editor.currentFloorId];
} }
@ -833,6 +816,39 @@ editor_file = function (editor, callback) {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
editor_file.editCommonEvent = function (actionList, callback) {
/*actionList:[
["change","['test']",['123']],
]
[]时只查询不修改
*/
var data_obj = events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent;
if (!isset(callback)) {
printe('未设置callback');
throw('未设置callback')
}
;
if (isset(actionList) && actionList.length > 0) {
actionList.forEach(function (value) {
value[1] = "['commonEvent']" + value[1];
});
saveSetting('events', actionList, function (err) {
callback([
Object.assign({},data_obj),
editor_file.eventsComment._data.commonEvent,
err]);
});
} else {
callback([
Object.assign({},data_obj),
editor_file.eventsComment._data.commonEvent,
null]);
}
}
//callback([obj,commentObj,err:String])
////////////////////////////////////////////////////////////////////
var isset = function (val) { var isset = function (val) {
if (val == undefined || val == null) { if (val == undefined || val == null) {
return false; return false;
@ -996,37 +1012,20 @@ editor_file = function (editor, callback) {
editor_file.saveFloorFile(callback); editor_file.saveFloorFile(callback);
return; return;
} }
if (file == 'events') {
actionList.forEach(function (value) {
eval("events_c12a15a8_c380_4b28_8144_256cba95f760" + value[1] + '=' + JSON.stringify(value[2]));
});
var datastr = 'var events_c12a15a8_c380_4b28_8144_256cba95f760 = \n';
datastr += JSON.stringify(events_c12a15a8_c380_4b28_8144_256cba95f760, null, '\t');
fs.writeFile('project/events.js', encode(datastr), 'base64', function (err, data) {
callback(err);
});
return;
}
callback('出错了,要设置的文件名不识别'); callback('出错了,要设置的文件名不识别');
} }
/*
$select({\"values\":[\"keys\",\"items\",\"constants\",\"tools\"]})$end
$range(thiseval==~~thiseval &&thiseval>0)$end
$leaf(true)$end
$select({\"values\":[true]})$end
$select({\"values\":[false]})$end
$select({\"values\":[true,false]})$end
*/
/*
所有注释中的特殊指令
$range(evalstr:thiseval)$end
限制取值范围,要求修改后的eval(evalstr)为true
$leaf(evalstr:thiseval)$end
强制指定为叶节点,如果eval(evalstr)为true
//以下几个中选一个 [
$select(evalstr)$end
渲染成<select>,选项为数组eval(evalstr)['values']
$input(evalstr)$end
渲染成<input>
$textarea(evalstr)$end
渲染成<textarea>
默认选项为$textarea()$end
// ]
*/
return editor_file; return editor_file;
} }
//editor_file = editor_file(editor); //editor_file = editor_file(editor);

View File

@ -11,6 +11,8 @@ editor_mode = function (editor) {
'map': 'left', 'map': 'left',
'appendpic': 'left1', 'appendpic': 'left1',
'commonevent': 'left9',
} }
this._ids = {} this._ids = {}
this.dom = {} this.dom = {}
@ -223,21 +225,29 @@ editor_mode = function (editor) {
editor_mode.addAction(['delete', field, undefined]); editor_mode.addAction(['delete', field, undefined]);
editor_mode.onmode('save');//自动保存 删掉此行的话点保存按钮才会保存 editor_mode.onmode('save');//自动保存 删掉此行的话点保存按钮才会保存
} else { } else {
printe(field + ' : 该值不允许为null,无法删除'); printe(field + ' : 该值不允许为null无法删除');
} }
} }
var addfunc=function(){ var addfunc=function(){
editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]); editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]);
var mode = document.getElementById('editModeSelect').value;
// 1.输入id // 1.输入id
var newid=prompt('请输入新项的id'); var newid=prompt('请输入新项的ID仅公共事件支持中文ID');
if (newid == null || newid.length==0) { if (newid == null || newid.length==0) {
return; return;
} }
// 检查commentEvents
if (mode !== 'commonevent') {
// 2.检查id是否符合规范或与已有id重复 // 2.检查id是否符合规范或与已有id重复
if (!/^[a-zA-Z0-9_]+$/.test(newid)){ if (!/^[a-zA-Z0-9_]+$/.test(newid)){
printe('id不符合规范, 请使用大小写字母数字下划线来构成'); printe('id不符合规范, 请使用大小写字母数字下划线来构成');
return; return;
} }
}
var conflict=true; var conflict=true;
var basefield=field.replace(/\[[^\[]*\]$/,''); var basefield=field.replace(/\[[^\[]*\]$/,'');
if (basefield==="['main']"){ if (basefield==="['main']"){
@ -341,75 +351,40 @@ editor_mode = function (editor) {
editor_mode.prototype.doActionList = function (mode, actionList) { editor_mode.prototype.doActionList = function (mode, actionList) {
if (actionList.length == 0) return; if (actionList.length == 0) return;
printf('修改中...'); printf('修改中...');
switch (mode) { var cb=function(objs_){
case 'loc':
editor.file.editLoc(editor_mode.pos.x, editor_mode.pos.y, actionList, function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) { if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]); printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0]) throw(objs_.slice(-1)[0])
} }
;printf('修改成功'); ;printf('修改成功');
}
switch (mode) {
case 'loc':
editor.file.editLoc(editor_mode.pos.x, editor_mode.pos.y, actionList, function (objs_) {
cb(objs_);
editor.drawPosSelection(); editor.drawPosSelection();
}); });
break; break;
case 'enemyitem': case 'enemyitem':
if (editor_mode.info.images == 'enemys' || editor_mode.info.images == 'enemy48') { if (editor_mode.info.images == 'enemys' || editor_mode.info.images == 'enemy48') {
editor.file.editEnemy(editor_mode.info.id, actionList, function (objs_) {//console.log(objs_); editor.file.editEnemy(editor_mode.info.id, actionList, cb);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0])
}
;printf('修改成功')
});
} else if (editor_mode.info.images == 'items') { } else if (editor_mode.info.images == 'items') {
editor.file.editItem(editor_mode.info.id, actionList, function (objs_) {//console.log(objs_); editor.file.editItem(editor_mode.info.id, actionList, cb);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0])
}
;printf('修改成功')
});
} else { } else {
editor.file.editMapBlocksInfo(editor_mode.info.idnum, actionList, function (objs_) {//console.log(objs_); editor.file.editMapBlocksInfo(editor_mode.info.idnum, actionList, cb);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0])
}
;printf('修改成功');
});
} }
break; break;
case 'floor': case 'floor':
editor.file.editFloor(actionList, cb);
editor.file.editFloor(actionList, function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0])
}
;printf('修改成功');
});
break; break;
case 'tower': case 'tower':
editor.file.editTower(actionList, cb);
editor.file.editTower(actionList, function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0])
}
;printf('修改成功')
});
break; break;
case 'functions': case 'functions':
editor.file.editFunctions(actionList, cb);
editor.file.editFunctions(actionList, function (objs_) {//console.log(objs_); break;
if (objs_.slice(-1)[0] != null) { case 'commonevent':
printe(objs_.slice(-1)[0]); editor.file.editCommonEvent(actionList, cb);
throw(objs_.slice(-1)[0])
}
;printf('修改成功')
});
break; break;
default: default:
break; break;
@ -540,6 +515,19 @@ editor_mode = function (editor) {
if (Boolean(callback)) callback(); if (Boolean(callback)) callback();
} }
editor_mode.prototype.commonevent = function (callback) {
var objs = [];
editor.file.editCommonEvent([], function (objs_) {
objs = objs_;
//console.log(objs_)
});
//只查询不修改时,内部实现不是异步的,所以可以这么写
var tableinfo = editor_mode.objToTable_(objs[0], objs[1]);
document.getElementById('table_b7bf0124_99fd_4af8_ae2f_0017f04a7c7d').innerHTML = tableinfo.HTML;
tableinfo.listen(tableinfo.guids);
if (Boolean(callback)) callback();
}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
editor_mode.prototype.listen = function (callback) { editor_mode.prototype.listen = function (callback) {
@ -1208,11 +1196,11 @@ editor_mode = function (editor) {
editor_mode.changeDoubleClickModeByButton=function(mode){ editor_mode.changeDoubleClickModeByButton=function(mode){
({ ({
delete:function(){ delete:function(){
printf('下一次双击表格的项删除, 编辑后刷新浏览器生效 (正常模式下双击是用事件或文本编辑器编辑);切换下拉菜单可取消。'); printf('下一次双击表格的项删除,切换下拉菜单可取消;编辑后需刷新浏览器生效。');
editor_mode.doubleClickMode=mode; editor_mode.doubleClickMode=mode;
}, },
add:function(){ add:function(){
printf('下一次双击表格的项, 在同级添加新项, 编辑后刷新浏览器生效 (正常模式下双击是用事件或文本编辑器编辑);切换下拉菜单可取消。'); printf('下一次双击表格的项则在同级添加新项,切换下拉菜单可取消;编辑后需刷新浏览器生效。');
editor_mode.doubleClickMode=mode; editor_mode.doubleClickMode=mode;
} }
}[mode])(); }[mode])();

36
_server/events.comment.js Normal file
View File

@ -0,0 +1,36 @@
var events_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
{
"_type": "object",
"_data": {
"commonEvent": {
"_type": "object",
"_data": function (key) {
var obj = {
"加点事件": {
"_leaf": true,
"_type": "event",
"_range": "thiseval instanceof Array",
"_event": "commonEvent",
"_data": "打败怪物后进行加点"
},
"毒衰咒处理": {
"_leaf": true,
"_type": "event",
"_range": "thiseval instanceof Array",
"_event": "commonEvent",
"_data": "对毒衰咒效果进行的处理"
},
}
if (obj[key]) return obj[key];
return {
"_leaf": true,
"_type": "event",
"_event": "commonEvent",
"_data": "自定义公共事件,可以双击进入事件编辑器"
}
}
}
}
}

View File

@ -1,4 +1,4 @@
var maps_comment_90f36752_8815_4be8_b32b_d7fad1d0542e = var maps_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
{ {
////////////////////////// 地形部分 ////////////////////////// ////////////////////////// 地形部分 //////////////////////////

View File

View File

@ -1,6 +1,6 @@
# V2.0版本介绍 # V2.0版本介绍
?> 目前版本**v2.5.3**,上次更新时间:* {docsify-updated} * ?> 目前版本**v2.5.4**,上次更新时间:* {docsify-updated} *
目前样板已经更新到V2.0版本以上本章将对V2.0的一些内容进行介绍。 目前样板已经更新到V2.0版本以上本章将对V2.0的一些内容进行介绍。

View File

@ -1,6 +1,6 @@
# 附录: API列表 # 附录: API列表
?> 目前版本**v2.5.3**,上次更新时间:* {docsify-updated} * ?> 目前版本**v2.5.4**,上次更新时间:* {docsify-updated} *
**这里只列出所有可能会被造塔者用到的常用API更多的有关内容请在代码内进行查询。** **这里只列出所有可能会被造塔者用到的常用API更多的有关内容请在代码内进行查询。**
@ -124,6 +124,9 @@ core.insertAction(list, x, y, callback)
x和y如果设置则覆盖"当前事件点"的坐标callback如果设置则覆盖事件执行完毕后的回调函数。 x和y如果设置则覆盖"当前事件点"的坐标callback如果设置则覆盖事件执行完毕后的回调函数。
例如: core.insertAction(["楼层切换", {"type":"changeFloor", "floorId": "MT3"}]) 例如: core.insertAction(["楼层切换", {"type":"changeFloor", "floorId": "MT3"}])
将依次显示剧情文本,并执行一个楼层切换的自定义事件。 将依次显示剧情文本,并执行一个楼层切换的自定义事件。
--------
从V2.5.4开始提出了“公共事件”的说法,这里也可以插入一个公共事件名。
例如core.insertAction("毒衰咒处理") 将插入公共事件“毒衰咒处理”。
core.changeFloor(floorId, stair, heroLoc, time, callback) [异步] core.changeFloor(floorId, stair, heroLoc, time, callback) [异步]
@ -430,6 +433,10 @@ core.events.doAction()
执行下一个事件。此函数中将对所有自定义事件类型分别处理。 执行下一个事件。此函数中将对所有自定义事件类型分别处理。
core.events.getCommonEvent(name)
根据名称获得一个公共事件如果不存在对应的公共事件则返回null。
core.events.openShop(shopId, needVisited) [异步] core.events.openShop(shopId, needVisited) [异步]
打开一个全局商店。needVisited表示是否需要该商店已被打开过。 打开一个全局商店。needVisited表示是否需要该商店已被打开过。
@ -610,6 +617,10 @@ core.utils.cropImage(image, size)
纵向对图片进行切分(裁剪)。 纵向对图片进行切分(裁剪)。
core.utils.push(a,b)
向某个数组后插入另一个数组或元素
core.utils.unshift(a, b) core.utils.unshift(a, b)
向某个数组前插入另一个数组或元素 向某个数组前插入另一个数组或元素

View File

@ -1,6 +1,6 @@
# 元件说明 # 元件说明
?> 目前版本**v2.5.3**,上次更新时间:* {docsify-updated} * ?> 目前版本**v2.5.4**,上次更新时间:* {docsify-updated} *
在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。 在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。

View File

@ -1,6 +1,6 @@
# 事件 # 事件
?> 目前版本**v2.5.3**,上次更新时间:* {docsify-updated} * ?> 目前版本**v2.5.4**,上次更新时间:* {docsify-updated} *
本章内将对样板所支持的事件进行介绍。 本章内将对样板所支持的事件进行介绍。
@ -573,23 +573,31 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
例如上面这个例子,下面的文字将不会再被显示,而是直接跳转到`"3,6"`对应的事件列表从头执行。 例如上面这个例子,下面的文字将不会再被显示,而是直接跳转到`"3,6"`对应的事件列表从头执行。
### insert插入另一个地点的事件 !> 从V2.5.4开始,允许执行另一个点的“系统事件”,如打怪、开门、拾取道具等等。对应点的战后事件等也会被执行。
`{"type":"insert"}` 会插入另一个地点的事件执行。 ### insert插入公共事件或另一个地点的事件并执行
`{"type":"insert"}` 会插入公共事件或另一个地点的事件并执行。
其基本写法如下: 其基本写法如下:
``` js ``` js
"x,y": [ // 实际执行的事件列表 "x,y": [ // 实际执行的事件列表
{"type": "insert", "name": "加点事件"}, // 插入公共事件:加点事件
{"type": "insert", "name": "毒衰咒处理"}, // 插入公共事件:毒衰咒处理
{"type": "insert", "loc": [3,6]}, // 插入[3,6]点的事件并执行 {"type": "insert", "loc": [3,6]}, // 插入[3,6]点的事件并执行
{"type": "insert", "loc": [10,10], "floorId": "MT1"}, // 插入MT1层[10,10]点的事件并执行 {"type": "insert", "loc": [10,10], "floorId": "MT1"}, // 插入MT1层[10,10]点的事件并执行
"上面的插入事件执行完毕后会接着继续执行后面的事件" "上面的插入事件执行完毕后会接着继续执行后面的事件"
] ]
``` ```
loc是必须的代表另一个地点的坐标 `insert`的写法有两种,可以写`name`,或者`loc`
floorId可选代表另一个地点所在的楼层如果不写则默认为当前层。 - 如果写了`"name": "xxx"`,则会去公共事件列表中找寻对应的事件,并执行。
- name为公共事件的名称如果对应公共事件不存在则跳过。
- 否则,如果写了`"loc": [x,y]`,则会插入另一个地点的事件
- loc为另一个地点的坐标
- floorId可选代表另一个地点所在的楼层如果不写则默认为当前层。
和`type:trigger`不同的是,**`type:trigger`是立刻将当前事件结束剩下所有内容都忽略然后重新启动另一个地点的action事件。** 和`type:trigger`不同的是,**`type:trigger`是立刻将当前事件结束剩下所有内容都忽略然后重新启动另一个地点的action事件。**
@ -597,8 +605,6 @@ floorId可选代表另一个地点所在的楼层如果不写则默认为
**这个过程中,当前事件不会被结束,当前的楼层和事件坐标不会发生改变。** 插入的事件执行完毕后,会继续执行接下来的内容。 **这个过程中,当前事件不会被结束,当前的楼层和事件坐标不会发生改变。** 插入的事件执行完毕后,会继续执行接下来的内容。
我们某个事件写在某个角落的墙上然后远程调用,从而达到“公共事件”的效果。
### revisit立即重启当前事件 ### revisit立即重启当前事件
revisit和trigger完全相同只不过是立刻触发的还是本地点的事件 revisit和trigger完全相同只不过是立刻触发的还是本地点的事件
@ -836,6 +842,7 @@ name是可选的代表目标行走图的文件名。
"x,y": [ // 实际执行的事件列表 "x,y": [ // 实际执行的事件列表
{"type": "openDoor", "loc": [3,6], "floorId": "MT1"}, // 打开MT1层的[3,6]位置的门 {"type": "openDoor", "loc": [3,6], "floorId": "MT1"}, // 打开MT1层的[3,6]位置的门
{"type": "openDoor", "loc": [3,6]}, // 如果是本层则可省略floorId {"type": "openDoor", "loc": [3,6]}, // 如果是本层则可省略floorId
{"type": "openDoor", "loc": [3,6], "needKey": true} // 打开此门需要钥匙
] ]
``` ```
@ -845,6 +852,10 @@ loc指定门的坐标floorId指定门所在的楼层ID。如果是当前层
如果loc所在的点既不是门也不是墙壁则忽略本事件。 如果loc所在的点既不是门也不是墙壁则忽略本事件。
needKey是可选的如果设置为true则需要钥匙才能打开此门。如果没有钥匙则跳过此事件。
!> needKey仅对当前楼层开门有效跨楼层的门仍然不需要钥匙即可打开如有需求请自行判定。
### changeFloor楼层切换 ### changeFloor楼层切换
在事件中也可以对楼层进行切换。一个比较典型的例子就是TSW中勇士在三楼的陷阱被扔到了二楼就是一个楼层切换事件。 在事件中也可以对楼层进行切换。一个比较典型的例子就是TSW中勇士在三楼的陷阱被扔到了二楼就是一个楼层切换事件。
@ -1302,13 +1313,19 @@ async可选如果为true则会异步执行即不等待当前事件执行
值得注意的是如果是额外添加进文件的音效则需在main.js中this.sounds里加载它。 值得注意的是如果是额外添加进文件的音效则需在main.js中this.sounds里加载它。
### stopSound停止所有音效
使用`{"type": "stopSound"}`可以停止所有音效。
这在人物对话音效时很有用。
### setVolume设置音量 ### setVolume设置音量
使用setVolume可以设置音量大小。 使用setVolume可以设置音量大小。
使用方法: `{"type": "setVolume", "value": 90, "time": 500, "async": true}` 使用方法: `{"type": "setVolume", "value": 90, "time": 500, "async": true}`
value为音量大小在0到100之间默认为100。设置后BGM和SE都将使用该音量进行播放。 value为音量大小在0到100之间默认为100。设置后BGM将使用该音量进行播放。SE的音量大小不会发生改变。
可以设置time为音量渐变时间。 可以设置time为音量渐变时间。

BIN
docs/img/commonEvent.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -1,6 +1,6 @@
# HTML5 魔塔样板说明文档 # HTML5 魔塔样板说明文档
?> 目前版本**v2.5.3**,上次更新时间:* {docsify-updated} * ?> 目前版本**v2.5.4**,上次更新时间:* {docsify-updated} *
众所周知魔塔的趋势是向移动端发展贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中NekoRPG有着比较大的局限性游戏感较差更是完全没法在iOS上运行。而一些APP的魔塔虽然可用但是必须要下载安装对于Android和iOS还必须开发不同的版本非常麻烦。 众所周知魔塔的趋势是向移动端发展贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中NekoRPG有着比较大的局限性游戏感较差更是完全没法在iOS上运行。而一些APP的魔塔虽然可用但是必须要下载安装对于Android和iOS还必须开发不同的版本非常麻烦。

View File

@ -1,6 +1,6 @@
# 个性化 # 个性化
?> 目前版本**v2.5.3**,上次更新时间:* {docsify-updated} * ?> 目前版本**v2.5.4**,上次更新时间:* {docsify-updated} *
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。 有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。
@ -21,7 +21,7 @@ HTML5魔塔是使用画布canvas来绘制存在若干个图层它们
- route**[D]**:路线层;主要用来绘制勇士的行走路线图。 (z-index: 95) - route**[D]**:路线层;主要用来绘制勇士的行走路线图。 (z-index: 95)
- paint**[D]**绘图层主要用来进行绘图模式。z-index: 95) - paint**[D]**绘图层主要用来进行绘图模式。z-index: 95)
- curtain色调层用来控制当前楼层的画面色调 (z-index: 125) - curtain色调层用来控制当前楼层的画面色调 (z-index: 125)
- image\***[D]**图片层用来绘制图片等操作。z-index: 100+code, 101~150也就是图片编号在1~25的在色调层之下26~50的在色调层之上 - image1\~50**[D]**图片层用来绘制图片等操作。z-index: 100+code, 101~150也就是图片编号在1~25的在色调层之下26~50的在色调层之上
- uiUI层用来绘制一切UI窗口如剧情文本、怪物手册、楼传器、系统菜单等等 (z-index: 160) - uiUI层用来绘制一切UI窗口如剧情文本、怪物手册、楼传器、系统菜单等等 (z-index: 160)
- data数据层用来绘制一些顶层的或更新比较快的数据如左上角的提示战斗界面中数据的变化等等。 (z-index: 170) - data数据层用来绘制一些顶层的或更新比较快的数据如左上角的提示战斗界面中数据的变化等等。 (z-index: 170)
@ -84,13 +84,13 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana');
由于HTML5功能素材有限导致了对很多比较复杂的素材比如房子内等无法有着较好的绘图方式。 由于HTML5功能素材有限导致了对很多比较复杂的素材比如房子内等无法有着较好的绘图方式。
为了解决这个问题,我们允许用户自己放置一张或多张图片作为某一层的背景素材。 为了解决这个问题,我们允许用户自己放置一张或多张图片作为某一层的背景/前景素材。
要启用这个功能,我们首先需要在`data.js`中将可能的图片进行加载。 要启用这个功能,我们首先需要在`data.js`中将可能的图片进行加载。
``` js ``` js
"images": [ // 在此存放所有可能使用的图片 "images": [ // 在此存放所有可能使用的图片
// 图片可以被作为背景图(的一部分),也可以直接用自定义事件进行显示。 // 图片可以被作为背景/前景图,也可以直接用自定义事件进行显示。
// 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 // 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
// 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 // 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量
"bg.jpg", "house.png", "bed.png"// 依次向后添加 "bg.jpg", "house.png", "bed.png"// 依次向后添加
@ -99,18 +99,21 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana');
!> 请使用网上的一些[在线图片压缩工具](http://compresspng.com/zh/)对图片进行压缩,以节省流量。 !> 请使用网上的一些[在线图片压缩工具](http://compresspng.com/zh/)对图片进行压缩,以节省流量。
之后,我们可以在每层剧本的`"images"`里来定义该层的默认背景图片素材。 之后,我们可以在每层剧本的`"images"`里来定义该层的默认背景/前景层的图片素材。
从V2.5.4开始,贴图也允许进行帧动画,只要设置第五项的数值。
``` js ``` js
"images": [[3,5,"bg.jpg",0]], // 背景图;你可以选择一张或多张图片来作为背景/前景素材。 "images": [[96,120,"bg.jpg",0]], // 背景图;你可以选择一张或多张图片来作为背景/前景素材。
"images": [], // 无任何背景图 "images": [], // 无任何背景图
"images": [[1,1,"house.png",0], [6,7,"bed.png",1]] // 在(1,1)放一个house.png在背景层且(6,7)放bed.png在前景层 "images": [[32,32,"house.png",0], [160,170,"bed.png",1]] // 在(32,32)放一个house.png在背景层且(160,170)放bed.png在前景层
"images": [[3,5,"tree.png",2]] // 如果写2则会自动调节遮挡效果 "images": [[96,120,"tree.png",2]] // 如果写2则会自动调节遮挡效果
"images": [[64,0,"x.png",1,4]] // 这是一个前景层的4帧动画贴图
``` ```
images为一个数组代表当前层所有作为背景素材的图片信息。 images为一个数组代表当前层所有作为背景素材的图片信息。每一项为一个五元组分别为该背景素材的xy图片名遮挡方式和帧数。
每一项为一个四元组分别为该背景素材的xy图片名和遮挡方式。其中x和y分别为横纵坐标在0-12之间图片名则必须在上面的images中定义过。 其中x和y分别为左上角的像素坐标图片名则必须在全塔属性的images中定义过。
第四项为遮挡方式,定义如下: 第四项为遮挡方式,定义如下:
@ -118,17 +121,33 @@ images为一个数组代表当前层所有作为背景素材的图片信息
- 1该图片将全部画在前景层可以遮挡勇士。举例云彩等效果。 - 1该图片将全部画在前景层可以遮挡勇士。举例云彩等效果。
- 2该图片将上部分画在前景层下部分画在背景层。从而可以达到一个“自动调节遮挡的效果”。举例树、房子等等。 - 2该图片将上部分画在前景层下部分画在背景层。从而可以达到一个“自动调节遮挡的效果”。举例树、房子等等。
!> 如果写2的话请确保图片高度是32的倍数 !> 如果写2的话最好让xy和图片高度都是32的倍数
第五项为图片的帧数,可选。如果进行了设置,则会将该贴图视为帧动画,并切分成对应的帧数。
例如假设图片是100x100的且帧数设为4则视为四帧帧动画每次绘制的图片大小实际上是25x100。
关于楼层贴图和前景、背景层的层叠覆盖关系,默认是:**地板 - 背景贴图 - 背景图块 - 事件 - 勇士 - 前景贴图 - 前景图块**。
可以通过修改`libs/maps.js`的`drawMap`函数中下面三行的顺序来改变其覆盖关系。
``` js
// ----- 可以调整这三行的顺序来修改覆盖关系;同层画布上,后绘制的覆盖先绘制的
// ----- ui.js的drawThumbnail函数也需要对应进行修改。
// 绘制楼层贴图
core.maps.drawFloorImages(floorId, images);
// 绘制背景层图块
core.maps.drawBgFgMap(floorId, core.canvas.bg, "bg", true);
// 绘制前景层图块
core.maps.drawBgFgMap(floorId, core.canvas.fg, "fg", true);
```
楼层贴图可以被事件隐藏和显示,详见[隐藏贴图](event#hideFloorImg隐藏贴图)的写法。 楼层贴图可以被事件隐藏和显示,详见[隐藏贴图](event#hideFloorImg隐藏贴图)的写法。
**如果你需要让某些点不可通行(比如你建了个房子,墙壁和家具等位置不让通行),则需在`events`中指定`{"noPass": false}`,参见[自定义事件](event#自定义事件)的写法。** **如果要让贴图的某些点不可通行则可以使用noPass或者空气墙。**
``` js !> 小技巧:可以使用帧动画贴图来贴一些大型怪物,比如魔龙、章鱼,或者《永不复还》中的恐怖利刃等等。如果使用帧贴图来贴怪物,则可以使用一个“透明的怪物”放置在对应位置并写上具体属性数值(这样就可以进行战斗和显伤了);然后可以使用[displayIdInBook](element#怪物的朝向问题)在怪物手册中将该透明怪物映射到另一个有素材的怪物ID上。战斗完毕后使用[隐藏贴图](event#hideFloorImg隐藏贴图)事件将贴图隐藏即可。
"events": {
"x,y": {"noPass": true} // (x,y)点不可通行
}
```
### 使用便捷PS工具生成素材 ### 使用便捷PS工具生成素材
@ -543,18 +562,17 @@ case 89: // 使用该按键的keyCode比如Y键就是89
## 公共事件 ## 公共事件
2.5.1开始H5提供了`{"type":"insert"}`事件,完美支持了公共事件的写法 V2.5.4开始,样板提供了“公共事件”下拉框,我们可以在里面用事件编辑器进行编辑,并通过`{"type":"insert"}`进行调用
我们只需要将需要的公共事件放在某个角落的墙上(或者甚至单独弄一层专门摆放公共事件),并使用“插入事件”,即可进行调用。 ![公共事件](./img/commonEvent.png)
具体详见[插入另一个地点的事件](event#insert插入另一个地点的事件)。 具体详见[插入公共事件或另一个地点的事件并执行](event#insert插入公共事件或另一个地点的事件并执行)。
当然,继续使用**插件**的写法也是可以的。具体参见“脚本编辑 - 插件编写”。 当然,继续使用**插件**的写法也是可以的。
<!-- ## 插件系统
在RM中存在公共事件的说法也就是通过某个指令来调用一系列事件的触发。
在H5中我们可以使用“插件”的形式来达成这个效果。具体参见“脚本编辑 - 插件编写”。 在H5中提供了“插件”系统。具体参见“脚本编辑 - 插件编写”。
![插件编写](./img/plugin.png) ![插件编写](./img/plugin.png)
@ -562,7 +580,7 @@ case 89: // 使用该按键的keyCode比如Y键就是89
在这个插件编写的过程中,我们可以使用任何[常见API](api)里面的代码调用;也可以通过`core.insertAction`来插入自定义事件执行。 在这个插件编写的过程中,我们可以使用任何[常见API](api)里面的代码调用;也可以通过`core.insertAction`来插入自定义事件执行。
下面是一个很简单的例子,我编写一个公共事件(插件)其效果是让勇士生命值变成原来的x倍并令面前的图块消失。 下面是一个很简单的例子,我编写一个插件函数其效果是让勇士生命值变成原来的x倍并令面前的图块消失。
``` js ``` js
this.myfunc = function(x) { this.myfunc = function(x) {
@ -575,10 +593,9 @@ this.myfunc = function(x) {
} }
``` ```
然后比如我们在某个道具的使用效果 `useItemEffect` 中写 `core.plugin.myfunc(2)` 即可调用此公共事件(插件)。也可以在战后事件或自定义脚本等位置来写。 然后比如我们在某个道具的使用效果 `useItemEffect` 中写 `core.plugin.myfunc(2)` 即可调用此插件函数。也可以在战后事件或自定义脚本等位置来写。
通过这种将脚本和自定义事件混用的方式可以达到和RM中公共事件类似的效果即一个调用触发一系列事件。 网站上也提供了一个[插件库](https://h5mota.com/plugins/),欢迎大家把自己写的插件进行共享。
-->
## 标题界面事件化 ## 标题界面事件化

View File

@ -1,6 +1,6 @@
# 快速上手 # 快速上手
?> 目前版本**v2.5.3**,上次更新时间:* {docsify-updated} * ?> 目前版本**v2.5.4**,上次更新时间:* {docsify-updated} *
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔! 在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!

View File

@ -185,7 +185,6 @@
<select id="entryType" disabled="disabled" style="display: none"> <select id="entryType" disabled="disabled" style="display: none">
<option value="event">event</option> <option value="event">event</option>
<option value="changeFloor">changeFloor</option> <option value="changeFloor">changeFloor</option>
<option value="point">point</option>
<option value="level">level</option> <option value="level">level</option>
<option value="shop">shop</option> <option value="shop">shop</option>
<option value="afterBattle">afterBattle</option> <option value="afterBattle">afterBattle</option>
@ -193,6 +192,7 @@
<option value="afterOpenDoor">afterOpenDoor</option> <option value="afterOpenDoor">afterOpenDoor</option>
<option value="firstArrive">firstArrive</option> <option value="firstArrive">firstArrive</option>
<option value="eachArrive">eachArrive</option> <option value="eachArrive">eachArrive</option>
<option value="commonEvent">commonEvent</option>
</select> </select>
<button onclick="editor_blockly.confirm()">确认</button> <button onclick="editor_blockly.confirm()">确认</button>
<button onclick="editor_blockly.parse()">解析</button> <button onclick="editor_blockly.parse()">解析</button>
@ -242,6 +242,23 @@
</div> </div>
</div> </div>
</div> </div>
<div id="left9" class='leftTab' style="z-index:-1;opacity: 0;"><!-- commonevent -->
<h3 class="leftTabHeader">公共事件&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('add')">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_b7bf0124_99fd_4af8_ae2f_0017f04a7c7d'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="mid"> <div id="mid">
<div class="col" id='mapColMark'></div> <div class="col" id='mapColMark'></div>
<div class="row" id='mapRowMark'></div> <div class="row" id='mapRowMark'></div>
@ -309,6 +326,7 @@
<option value="tower">全塔属性</option> <option value="tower">全塔属性</option>
<option value="functions">脚本编辑</option> <option value="functions">脚本编辑</option>
<option value="appendpic">追加素材</option> <option value="appendpic">追加素材</option>
<option value="commonevent">公共事件</option>
</select> </select>
<select id="brushMod" style="clear:right"> <select id="brushMod" style="clear:right">
<option value="line">画线</option> <option value="line">画线</option>

View File

@ -181,7 +181,6 @@
<select id="entryType" disabled="disabled" style="display: none"> <select id="entryType" disabled="disabled" style="display: none">
<option value="event">event</option> <option value="event">event</option>
<option value="changeFloor">changeFloor</option> <option value="changeFloor">changeFloor</option>
<option value="point">point</option>
<option value="level">level</option> <option value="level">level</option>
<option value="shop">shop</option> <option value="shop">shop</option>
<option value="afterBattle">afterBattle</option> <option value="afterBattle">afterBattle</option>
@ -189,6 +188,7 @@
<option value="afterOpenDoor">afterOpenDoor</option> <option value="afterOpenDoor">afterOpenDoor</option>
<option value="firstArrive">firstArrive</option> <option value="firstArrive">firstArrive</option>
<option value="eachArrive">eachArrive</option> <option value="eachArrive">eachArrive</option>
<option value="commonEvent">commonEvent</option>
</select> </select>
<button onclick="editor_blockly.confirm()">确认</button> <button onclick="editor_blockly.confirm()">确认</button>
<button onclick="editor_blockly.parse()">解析</button> <button onclick="editor_blockly.parse()">解析</button>
@ -238,6 +238,23 @@
</div> </div>
</div> </div>
</div> </div>
<div id="left9" class='leftTab' style="z-index:-1;opacity: 0;"><!-- commonevent -->
<h3 class="leftTabHeader">公共事件&nbsp;&nbsp;<button onclick="editor.mode.onmode('save')">保存</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('add')">添加</button>&nbsp;&nbsp;<button onclick="editor.mode.changeDoubleClickModeByButton('delete')">删除</button>
</h3>
<div class="leftTabContent">
<div class='etable'>
<table>
<tbody id='table_b7bf0124_99fd_4af8_ae2f_0017f04a7c7d'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="mid"> <div id="mid">
<table class="col" id='mapColMark'></table> <table class="col" id='mapColMark'></table>
<table class="row" id='mapRowMark'></table> <table class="row" id='mapRowMark'></table>
@ -277,6 +294,7 @@
<option value="tower">全塔属性</option> <option value="tower">全塔属性</option>
<option value="functions">脚本编辑</option> <option value="functions">脚本编辑</option>
<option value="appendpic">追加素材</option> <option value="appendpic">追加素材</option>
<option value="commonevent">公共事件</option>
</select> </select>
<br/> <br/>
<span style="font-size: 12px;"> <span style="font-size: 12px;">

View File

@ -70,8 +70,17 @@ control.prototype.setRequestAnimationFrame = function () {
core.drawBlock(block, core.status.globalAnimateStatus % (block.event.animate||1)); core.drawBlock(block, core.status.globalAnimateStatus % (block.event.animate||1));
}); });
// Global floor images
core.maps.drawFloorImages(core.status.floorId, core.status.floorAnimateObjs||[], core.status.globalAnimateStatus);
// Global Autotile Animate // Global Autotile Animate
core.status.autotileAnimateObjs.blocks.forEach(function (block) { core.status.autotileAnimateObjs.blocks.forEach(function (block) {
// ------ 界面外的动画不绘制
if (block.x * 32 < core.bigmap.offsetX - 64 || block.x * 32 > core.bigmap.offsetX + 416 + 32
|| block.y * 32 < core.bigmap.offsetY - 64 || block.y * 32 > core.bigmap.offsetY + 416 + 32 + 16) {
return;
}
var cv = core.isset(block.name)?core.canvas[block.name]:core.canvas.event; var cv = core.isset(block.name)?core.canvas[block.name]:core.canvas.event;
cv.clearRect(block.x * 32, block.y * 32, 32, 32); cv.clearRect(block.x * 32, block.y * 32, 32, 32);
if (core.isset(block.name)) { if (core.isset(block.name)) {
@ -1416,6 +1425,7 @@ control.prototype.screenFlash = function (color, time, times, callback) {
control.prototype.updateDamage = function (floorId, canvas) { control.prototype.updateDamage = function (floorId, canvas) {
floorId = floorId || core.status.floorId; floorId = floorId || core.status.floorId;
if (!core.isset(floorId)) return; if (!core.isset(floorId)) return;
if (core.status.gameOver) return;
if (!core.isset(canvas)) { if (!core.isset(canvas)) {
canvas = core.canvas.damage; canvas = core.canvas.damage;
core.clearMap('damage'); core.clearMap('damage');
@ -2666,6 +2676,10 @@ control.prototype.playSound = function (sound) {
var source = core.musicStatus.audioContext.createBufferSource(); var source = core.musicStatus.audioContext.createBufferSource();
source.buffer = core.material.sounds[sound]; source.buffer = core.material.sounds[sound];
source.connect(core.musicStatus.gainNode); source.connect(core.musicStatus.gainNode);
var id = parseInt(Math.random()*10000000);
source.onended = function () {
delete core.musicStatus.playingSounds[id];
}
try { try {
source.start(0); source.start(0);
} }
@ -2675,8 +2689,10 @@ control.prototype.playSound = function (sound) {
} }
catch (ee) { catch (ee) {
main.log(ee); main.log(ee);
return;
} }
} }
core.musicStatus.playingSounds[id] = source;
} }
else { else {
core.material.sounds[sound].volume = core.musicStatus.volume; core.material.sounds[sound].volume = core.musicStatus.volume;
@ -2689,6 +2705,23 @@ control.prototype.playSound = function (sound) {
} }
} }
control.prototype.stopSound = function () {
for (var i in core.musicStatus.playingSounds) {
var source = core.musicStatus.playingSounds[i];
try {
source.stop();
}
catch (e) {
try {
source.noteOff(0);
}
catch (e) {
main.log(e);
}
}
}
}
control.prototype.checkBgm = function() { control.prototype.checkBgm = function() {
core.playBgm(core.musicStatus.playingBgm || main.startBgm); core.playBgm(core.musicStatus.playingBgm || main.startBgm);
} }

View File

@ -54,6 +54,7 @@ function core() {
'soundStatus': true, // 是否播放SE 'soundStatus': true, // 是否播放SE
'playingBgm': null, // 正在播放的BGM 'playingBgm': null, // 正在播放的BGM
'gainNode': null, 'gainNode': null,
'playingSounds': {}, // 正在播放的SE
'volume': 1.0, // 音量 'volume': 1.0, // 音量
'cachedBgms': [], // 缓存BGM内容 'cachedBgms': [], // 缓存BGM内容
'cachedBgmCount': 4, // 缓存的bgm数量 'cachedBgmCount': 4, // 缓存的bgm数量
@ -196,6 +197,7 @@ function core() {
// 动画 // 动画
'globalAnimateObjs': [], 'globalAnimateObjs': [],
'floorAnimateObjs': [],
'boxAnimateObjs': [], 'boxAnimateObjs': [],
'autotileAnimateObjs': {"blocks": [], "map": null, "bgmap": null, "fgmap": null}, 'autotileAnimateObjs': {"blocks": [], "map": null, "bgmap": null, "fgmap": null},
"globalAnimateStatus": 0, "globalAnimateStatus": 0,
@ -1071,6 +1073,11 @@ core.prototype.unshift = function (a,b) {
return core.utils.unshift(a,b); return core.utils.unshift(a,b);
} }
////// 向某个数组后插入另一个数组或元素 //////
core.prototype.push = function (a,b) {
return core.utils.push(a,b);
}
////// 设置本地存储 ////// ////// 设置本地存储 //////
core.prototype.setLocalStorage = function(key, value) { core.prototype.setLocalStorage = function(key, value) {
return core.utils.setLocalStorage(key, value); return core.utils.setLocalStorage(key, value);
@ -1388,6 +1395,11 @@ core.prototype.insertAction = function (list, x, y, callback) {
core.events.insertAction(list, x, y, callback); core.events.insertAction(list, x, y, callback);
} }
////// 获得一个公共事件内容 //////
core.prototype.getCommonEvent = function (name) {
return core.events.getCommonEvent(name);
}
////// 锁定状态栏,常常用于事件处理 ////// ////// 锁定状态栏,常常用于事件处理 //////
core.prototype.lockControl = function () { core.prototype.lockControl = function () {
core.control.lockControl(); core.control.lockControl();
@ -1491,6 +1503,11 @@ core.prototype.playSound = function (sound) {
core.control.playSound(sound); core.control.playSound(sound);
} }
////// 停止所有音效 //////
core.prototype.stopSound = function () {
core.control.stopSound();
}
////// 动画显示某对象 ////// ////// 动画显示某对象 //////
core.prototype.show = function (obj, speed, callback) { core.prototype.show = function (obj, speed, callback) {
core.utils.show(obj, speed, callback); core.utils.show(obj, speed, callback);

View File

@ -7,39 +7,24 @@ function events() {
////// 初始化 ////// ////// 初始化 //////
events.prototype.init = function () { events.prototype.init = function () {
this.eventdata = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.events; this.eventdata = functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.events;
this.commonEvent = events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent;
this.events = { this.events = {
'battle': function (data, core, callback) { 'battle': function (data, callback) {
// 正在执行自定义事件:不允许战斗
if (core.status.event.id == 'action') {
if (core.isset(callback)) callback();
return;
}
core.battle(data.event.id, data.x, data.y); core.battle(data.event.id, data.x, data.y);
if (core.isset(callback)) if (core.isset(callback))
callback(); callback();
}, },
'getItem': function (data, core, callback) { 'getItem': function (data, callback) {
core.getItem(data.event.id, 1, data.x, data.y); core.getItem(data.event.id, 1, data.x, data.y);
if (core.isset(callback)) if (core.isset(callback))
callback(); callback();
}, },
'openDoor': function (data, core, callback) { 'openDoor': function (data, callback) {
// 正在执行自定义事件:不允许开门
if (core.status.event.id == 'action') {
if (core.isset(callback)) callback();
return;
}
core.openDoor(data.event.id, data.x, data.y, true, function () { core.openDoor(data.event.id, data.x, data.y, true, function () {
if (core.isset(callback)) callback(); if (core.isset(callback)) callback();
core.replay();
}); });
}, },
'changeFloor': function (data, core, callback) { 'changeFloor': function (data, callback) {
// 正在执行自定义事件:不允许切换楼层
if (core.status.event.id == 'action') {
if (core.isset(callback)) callback();
return;
}
var heroLoc = {}; var heroLoc = {};
if (core.isset(data.event.data.loc)) if (core.isset(data.event.data.loc))
heroLoc = {'x': data.event.data.loc[0], 'y': data.event.data.loc[1]}; heroLoc = {'x': data.event.data.loc[0], 'y': data.event.data.loc[1]};
@ -49,30 +34,29 @@ events.prototype.init = function () {
core.changeFloor(data.event.data.floorId, data.event.data.stair, core.changeFloor(data.event.data.floorId, data.event.data.stair,
heroLoc, data.event.data.time, function () { heroLoc, data.event.data.time, function () {
if (core.isset(callback)) callback(); if (core.isset(callback)) callback();
core.replay();
}); });
}, },
'passNet': function (data, core, callback) { 'passNet': function (data, callback) {
core.events.passNet(data); core.events.passNet(data);
if (core.isset(callback)) if (core.isset(callback))
callback(); callback();
}, },
"changeLight": function (data, core, callback) { "changeLight": function (data, callback) {
core.events.changeLight(data.x, data.y); core.events.changeLight(data.x, data.y);
if (core.isset(callback)) if (core.isset(callback))
callback(); callback();
}, },
"ski": function (data, core, callback) { "ski": function (data, callback) {
core.events.ski(); core.events.ski();
if (core.isset(callback)) if (core.isset(callback))
callback(); callback();
}, },
"pushBox": function (data, core, callback) { "pushBox": function (data, callback) {
core.events.pushBox(data); core.events.pushBox(data);
if (core.isset(callback)) if (core.isset(callback))
callback(); callback();
}, },
'action': function (data, core, callback) { 'action': function (data, callback) {
var ev = core.clone(data.event.data), ex = data.x, ey = data.y; var ev = core.clone(data.event.data), ex = data.x, ey = data.y;
// 检查是否需要改变朝向 // 检查是否需要改变朝向
if (ex == core.nextX() && ey == core.nextY()) { if (ex == core.nextX() && ey == core.nextY()) {
@ -232,6 +216,11 @@ events.prototype.gameOver = function (ending, fromReplay, norank) {
core.setWeather(); core.setWeather();
core.ui.closePanel(); core.ui.closePanel();
if (main.isCompetition && core.isset(ending)) {
if (ending == "") ending = "恭喜通关";
ending += "[比赛]";
}
// 下载录像 // 下载录像
var confirmDownload = function () { var confirmDownload = function () {
@ -852,7 +841,7 @@ events.prototype.doAction = function() {
} }
var floorId=data.floorId || core.status.floorId; var floorId=data.floorId || core.status.floorId;
if (floorId==core.status.floorId) if (floorId==core.status.floorId)
core.openDoor(null, x, y, false, function() { core.openDoor(null, x, y, data.needKey, function() {
core.lockControl(); core.lockControl();
core.events.doAction(); core.events.doAction();
}) })
@ -898,27 +887,49 @@ events.prototype.doAction = function() {
var block=core.getBlock(toX, toY); var block=core.getBlock(toX, toY);
if (block!=null) { if (block!=null) {
block = block.block; block = block.block;
if (core.isset(block.event) && block.event.trigger=='action') { if (core.isset(block.event) && core.isset(block.event.trigger)) {
// 触发 core.status.event.data.x=block.x;
core.status.event.data.y=block.y;
core.status.event.data.list = [
{"todo": [], "total": [], "condition": "false"}
];
if (block.event.trigger == 'action') {
core.status.event.data.list = [ core.status.event.data.list = [
{"todo": core.clone(block.event.data), "total": core.clone(block.event.data), "condition": "false"} {"todo": core.clone(block.event.data), "total": core.clone(block.event.data), "condition": "false"}
]; ];
core.status.event.data.x=block.x; }
core.status.event.data.y=block.y; else {
core.material.events[block.event.trigger](block, function () {
core.lockControl();
core.doAction();
});
return;
}
} }
} }
this.doAction(); this.doAction();
break; break;
} }
case "insert": case "insert":
{ if (core.isset(data.name)) {
// ----- 公共事件
var commonEvent = this.getCommonEvent(data.name);
if (core.isset(commonEvent)) {
core.insertAction(commonEvent);
}
}
else {
var toX=core.calValue(data.loc[0], prefix), toY=core.calValue(data.loc[1], prefix); var toX=core.calValue(data.loc[0], prefix), toY=core.calValue(data.loc[1], prefix);
var floorId = data.floorId || core.status.floorId; var floorId = data.floorId || core.status.floorId;
var event = core.floors[floorId].events[toX+","+toY]; var event = core.floors[floorId].events[toX+","+toY];
if (core.isset(event)) core.insertAction(event); if (core.isset(event)) {
if (core.isset(event.data)) event = event.data;
if (typeof event == 'string' || event instanceof Array || core.isset(event.type))
core.insertAction(event);
}
}
this.doAction(); this.doAction();
break; break;
}
case "playSound": case "playSound":
if (!core.isReplaying()) if (!core.isReplaying())
core.playSound(data.name); core.playSound(data.name);
@ -947,6 +958,9 @@ events.prototype.doAction = function() {
core.freeBgm(data.name); core.freeBgm(data.name);
this.doAction(); this.doAction();
break; break;
case "stopSound":
core.stopSound();
break;
case "setVolume": case "setVolume":
data.value = core.clamp(parseInt(data.value)/100, 0, 1); data.value = core.clamp(parseInt(data.value)/100, 0, 1);
core.setFlag("__volume__", data.value); core.setFlag("__volume__", data.value);
@ -1200,7 +1214,7 @@ events.prototype.doAction = function() {
core.timeout.sleepTimeout = setTimeout(function() { core.timeout.sleepTimeout = setTimeout(function() {
core.timeout.sleepTimeout = null; core.timeout.sleepTimeout = null;
core.events.doAction(); core.events.doAction();
}, core.isReplaying()?20:data.time); }, core.isReplaying()?Math.min(data.time, 20):data.time);
break; break;
case "wait": case "wait":
if (core.isReplaying()) { if (core.isReplaying()) {
@ -1309,6 +1323,13 @@ events.prototype.doAction = function() {
events.prototype.insertAction = function (action, x, y, callback) { events.prototype.insertAction = function (action, x, y, callback) {
if (core.hasFlag("__statistics__")) return; if (core.hasFlag("__statistics__")) return;
// ------ 判定commonEvent
var commonEvent = this.getCommonEvent(action);
if (core.isset(commonEvent) && commonEvent instanceof Array) {
action = commonEvent;
}
if (!core.isset(action)) return;
if (core.status.event.id != 'action') { if (core.status.event.id != 'action') {
this.doEvents(action, x, y, callback); this.doEvents(action, x, y, callback);
} }
@ -1335,6 +1356,12 @@ events.prototype.recoverEvents = function (data) {
return false; return false;
} }
////// 获得一个公共事件 //////
events.prototype.getCommonEvent = function (name) {
if (!core.isset(name) || !(typeof name === 'string')) return null;
return this.commonEvent[name] || null;
}
////// 获得面前的物品(轻按) ////// ////// 获得面前的物品(轻按) //////
events.prototype.getNextItem = function() { events.prototype.getNextItem = function() {
if (!core.status.heroStop || !core.flags.enableGentleClick) return false; if (!core.status.heroStop || !core.flags.enableGentleClick) return false;
@ -1391,6 +1418,7 @@ events.prototype.openDoor = function (id, x, y, needKey, callback) {
core.drawTip("你没有" + ((core.material.items[key]||{}).name||"钥匙")); core.drawTip("你没有" + ((core.material.items[key]||{}).name||"钥匙"));
else core.drawTip("无法开启此门"); else core.drawTip("无法开启此门");
core.clearContinueAutomaticRoute(); core.clearContinueAutomaticRoute();
if (core.isset(callback)) callback();
return; return;
} }
core.autosave(true); core.autosave(true);
@ -1441,6 +1469,7 @@ events.prototype.battle = function (id, x, y, force, callback) {
if (!core.enemys.canBattle(id, x, y) && !force && !core.isset(core.status.event.id)) { if (!core.enemys.canBattle(id, x, y) && !force && !core.isset(core.status.event.id)) {
core.drawTip("你打不过此怪物!"); core.drawTip("你打不过此怪物!");
core.clearContinueAutomaticRoute(); core.clearContinueAutomaticRoute();
if (core.isset(callback)) callback();
return; return;
} }
@ -1461,47 +1490,47 @@ events.prototype.battle = function (id, x, y, force, callback) {
////// 触发(x,y)点的事件 ////// ////// 触发(x,y)点的事件 //////
events.prototype.trigger = function (x, y) { events.prototype.trigger = function (x, y) {
if (core.status.event.id == 'action') return;
core.status.isSkiing = false; core.status.isSkiing = false;
var mapBlocks = core.status.thisMap.blocks; var block = core.getBlock(x, y);
var noPass; if (block != null) {
for (var b = 0; b < mapBlocks.length; b++) { block = block.block;
if (mapBlocks[b].x == x && mapBlocks[b].y == y && !mapBlocks[b].disable) { // 启用事件 if (core.isset(block.event) && core.isset(block.event.trigger)) {
noPass = mapBlocks[b].event && mapBlocks[b].event.noPass; var noPass = block.event.noPass, trigger = block.event.trigger;
if (noPass) { if (noPass) {
core.clearAutomaticRouteNode(x, y); core.clearAutomaticRouteNode(x, y);
} }
if (core.isset(mapBlocks[b].event) && core.isset(mapBlocks[b].event.trigger)) {
var trigger = mapBlocks[b].event.trigger;
if (trigger == 'ski') core.status.isSkiing = true; if (trigger == 'ski') core.status.isSkiing = true;
// 转换楼层能否穿透 // 转换楼层能否穿透
if (trigger=='changeFloor' && !noPass) { if (trigger=='changeFloor' && !noPass) {
var canCross = core.flags.portalWithoutTrigger; var canCross = core.flags.portalWithoutTrigger;
if (core.isset(mapBlocks[b].event.data) && core.isset(mapBlocks[b].event.data.portalWithoutTrigger)) if (core.isset(block.event.data) && core.isset(block.event.data.portalWithoutTrigger))
canCross=mapBlocks[b].event.data.portalWithoutTrigger; canCross=block.event.data.portalWithoutTrigger;
if (canCross) { if (canCross) {
if (core.isReplaying()) { if (core.isReplaying()) {
if (core.status.replay.toReplay[0]=='no') { if (core.status.replay.toReplay[0]=='no') {
core.status.replay.toReplay.shift(); core.status.replay.toReplay.shift();
core.status.route.push("no"); core.status.route.push("no");
continue; return;
} }
} }
else if (core.status.automaticRoute.autoHeroMove || core.status.automaticRoute.autoStep<core.status.automaticRoute.autoStepRoutes.length) { else if (core.status.automaticRoute.autoHeroMove || core.status.automaticRoute.autoStep<core.status.automaticRoute.autoStepRoutes.length) {
core.status.route.push("no"); core.status.route.push("no");
continue; return;
} }
} }
} }
core.status.automaticRoute.moveDirectly = false; core.status.automaticRoute.moveDirectly = false;
core.material.events[trigger](mapBlocks[b], core, function (data) { core.material.events[trigger](block, function () {
if (trigger == 'openDoor' || trigger == 'changeFloor')
core.replay();
}); });
} }
} }
} }
}
events.prototype.setFloorName = function (floorId) { events.prototype.setFloorName = function (floorId) {
floorId = floorId || core.status.floorId; floorId = floorId || core.status.floorId;
@ -1779,7 +1808,7 @@ events.prototype.setVolume = function (value, time, callback) {
if (core.isset(core.musicStatus.playingBgm)) { if (core.isset(core.musicStatus.playingBgm)) {
core.material.bgms[core.musicStatus.playingBgm].volume = value; core.material.bgms[core.musicStatus.playingBgm].volume = value;
} }
core.musicStatus.gainNode.gain.value = value; // core.musicStatus.gainNode.gain.value = value;
} }
if (!core.isset(time) || time<100) { if (!core.isset(time) || time<100) {
@ -2037,24 +2066,16 @@ events.prototype.passNet = function (data) {
// core.drawTip('经过血网,生命-'+core.values.lavaDamage); // core.drawTip('经过血网,生命-'+core.values.lavaDamage);
} }
if (data.event.id=='poisonNet') { // 毒网 if (data.event.id=='poisonNet') { // 毒网
if (core.hasFlag('poison')) return; core.setFlag('debuff', 'poison');
core.setFlag('poison', true); core.insertAction('毒衰咒处理');
} }
if (data.event.id=='weakNet') { // 衰网 else if (data.event.id=='weakNet') { // 衰网
if (core.hasFlag('weak')) return; core.setFlag('debuff', 'weak');
core.setFlag('weak', true); core.insertAction('毒衰咒处理');
if (core.values.weakValue>=1) { // >=1直接扣数值
core.status.hero.atk -= core.values.weakValue;
core.status.hero.def -= core.values.weakValue;
} }
else { // <1扣比例 else if (data.event.id=='curseNet') { // 咒网
core.setFlag("equip_atk_buff", core.getFlag("equip_atk_buff", 1) - core.values.weakValue); core.setFlag('debuff', 'curse');
core.setFlag("equip_def_buff", core.getFlag("equip_def_buff", 1) - core.values.weakValue); core.insertAction('毒衰咒处理');
}
}
if (data.event.id=='curseNet') { // 咒网
if (core.hasFlag('curse')) return;
core.setFlag('curse', true);
} }
core.updateStatusBar(); core.updateStatusBar();
} }

View File

@ -88,8 +88,6 @@ loader.prototype.loadIcons = function () {
core.statusBar.image[key].src = core.statusBar.icons[key].src; core.statusBar.image[key].src = core.statusBar.icons[key].src;
} }
} }
core.statusBar.image.keyboard.src =
core.platform.extendKeyboard ? core.statusBar.icons.keyboard.src : core.statusBar.icons.shop.src;
}); });
} }

View File

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

View File

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

View File

@ -62,18 +62,18 @@ utils.prototype.replaceText = function (text, need, times) {
////// 计算表达式的值 ////// ////// 计算表达式的值 //////
utils.prototype.calValue = function (value, prefix, need, times) { utils.prototype.calValue = function (value, prefix, need, times) {
if (!core.isset(value)) return value; if (!core.isset(value)) return value;
if (typeof value == 'number') { if (typeof value === 'string') {
return value;
}
if (value instanceof Function) {
return value();
}
value=value.replace(/status:([\w\d_]+)/g, "core.getStatus('$1')"); value=value.replace(/status:([\w\d_]+)/g, "core.getStatus('$1')");
value=value.replace(/item:([\w\d_]+)/g, "core.itemCount('$1')"); value=value.replace(/item:([\w\d_]+)/g, "core.itemCount('$1')");
value=value.replace(/flag:([\w\d_]+)/g, "core.getFlag('$1', 0)"); value=value.replace(/flag:([\w\d_]+)/g, "core.getFlag('$1', 0)");
value=value.replace(/switch:([\w\d_]+)/g, "core.getFlag('"+(prefix||"global")+"@$1', 0)"); value=value.replace(/switch:([\w\d_]+)/g, "core.getFlag('"+(prefix||"global")+"@$1', 0)");
return eval(value); return eval(value);
} }
if (value instanceof Function) {
return value();
}
return value;
}
////// 字符串自动换行的分割 ////// ////// 字符串自动换行的分割 //////
utils.prototype.splitLines = function(canvas, text, maxLength, font) { utils.prototype.splitLines = function(canvas, text, maxLength, font) {
@ -116,6 +116,18 @@ utils.prototype.unshift = function (a,b) {
return a; return a;
} }
////// 向某个数组后插入另一个数组或元素 //////
utils.prototype.push = function (a,b) {
if (!(a instanceof Array) || !core.isset(b)) return;
if (b instanceof Array) {
core.clone(b).forEach(function (e) {
a.push(e);
});
}
else a.push(b);
return a;
}
////// 设置本地存储 ////// ////// 设置本地存储 //////
utils.prototype.setLocalStorage = function(key, value) { utils.prototype.setLocalStorage = function(key, value) {
try { try {

12
main.js
View File

@ -75,7 +75,7 @@ function main() {
'loader', 'control', 'utils', 'items', 'icons', 'maps', 'enemys', 'events', 'actions', 'data', 'ui', 'core' 'loader', 'control', 'utils', 'items', 'icons', 'maps', 'enemys', 'events', 'actions', 'data', 'ui', 'core'
]; ];
this.pureData = [ this.pureData = [
'data', 'enemys', 'icons', 'maps', 'items', 'functions' 'data', 'enemys', 'icons', 'maps', 'items', 'functions', 'events'
]; ];
this.materials = [ this.materials = [
'animates', 'enemys', 'hero', 'items', 'npcs', 'terrains', 'enemy48', 'npc48' 'animates', 'enemys', 'hero', 'items', 'npcs', 'terrains', 'enemy48', 'npc48'
@ -183,7 +183,7 @@ function main() {
this.canvas = {}; this.canvas = {};
this.__VERSION__ = "2.5.4"; this.__VERSION__ = "2.5.4";
this.__VERSION_CODE__ = 20; this.__VERSION_CODE__ = 24;
} }
main.prototype.init = function (mode, callback) { main.prototype.init = function (mode, callback) {
@ -520,6 +520,14 @@ main.statusBar.image.shop.onclick = function (e) {
main.core.openQuickShop(true); main.core.openQuickShop(true);
} }
////// 点击金币时也可以开启虚拟键盘 //////
main.statusBar.image.money.onclick = function (e) {
e.stopPropagation();
if (main.core.isPlaying())
main.core.openQuickShop(true);
}
////// 点击状态栏中的存档按钮时 ////// ////// 点击状态栏中的存档按钮时 //////
main.statusBar.image.save.onclick = function (e) { main.statusBar.image.save.onclick = function (e) {
e.stopPropagation(); e.stopPropagation();

View File

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

167
project/events.js Normal file
View File

@ -0,0 +1,167 @@
var events_c12a15a8_c380_4b28_8144_256cba95f760 =
{
"commonEvent": {
"加点事件": [
{
"type": "comment",
"text": "flag:point表示当前应该的加点数值"
},
{
"type": "choices",
"choices": [
{
"text": "攻击+${1*flag:point}",
"action": [
{
"type": "setValue",
"name": "status:atk",
"value": "status:atk+1*flag:point"
}
]
},
{
"text": "防御+${2*flag:point}",
"action": [
{
"type": "setValue",
"name": "status:def",
"value": "status:def+2*flag:point"
}
]
},
{
"text": "生命+${200*flag:point}",
"action": [
{
"type": "setValue",
"name": "status:hp",
"value": "status:hp+200*flag:point"
}
]
}
]
},
{
"type": "setValue",
"name": "flag:point",
"value": "null"
}
],
"毒衰咒处理": [
{
"type": "comment",
"text": "获得毒衰咒效果flag:debuff为要获得的类型"
},
{
"type": "switch",
"condition": "flag:debuff",
"caseList": [
{
"case": "'poison'",
"action": [
{
"type": "comment",
"text": "获得毒效果"
},
{
"type": "if",
"condition": "!flag:poison",
"true": [
{
"type": "setValue",
"name": "flag:poison",
"value": "true"
}
],
"false": []
}
]
},
{
"case": "'weak'",
"action": [
{
"type": "comment",
"text": "获得衰效果"
},
{
"type": "if",
"condition": "!flag:weak",
"true": [
{
"type": "setValue",
"name": "flag:weak",
"value": "true"
},
{
"type": "if",
"condition": "core.values.weakValue>=1",
"true": [
{
"type": "comment",
"text": ">=1直接扣数值"
},
{
"type": "setValue",
"name": "status:atk",
"value": "status:atk-core.values.weakValue"
},
{
"type": "setValue",
"name": "status:def",
"value": "status:def-core.values.weakValue"
}
],
"false": [
{
"type": "comment",
"text": "<1扣比例"
},
{
"type": "setValue",
"name": "flag:equip_atk_buff",
"value": "core.getFlag('equip_atk_buff',1)-core.values.weakValue"
},
{
"type": "setValue",
"name": "flag:equip_def_buff",
"value": "core.getFlag('equip_def_buff',1)-core.values.weakValue"
}
]
}
],
"false": []
}
]
},
{
"case": "'curse'",
"action": [
{
"type": "comment",
"text": "获得咒效果"
},
{
"type": "if",
"condition": "!flag:curse",
"true": [
{
"type": "setValue",
"name": "flag:curse",
"value": "true"
}
],
"false": []
}
]
}
]
},
{
"type": "setValue",
"name": "flag:debuff",
"value": "null"
}
]
}
}

View File

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

View File

@ -168,21 +168,9 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
if (!core.flags.enableAddPoint || !core.isset(point) || point<=0) return []; if (!core.flags.enableAddPoint || !core.isset(point) || point<=0) return [];
// 加点返回一个choices事件 // 加点返回一个choices事件
return [ // ----- 从V2.5.4开始,移动到“公共事件-加点事件”中
{"type": "choices", core.setFlag('point', point); // 设置flag:point
"choices": [ return core.getCommonEvent('加点事件');
{"text": "攻击+"+(1*point), "action": [
{"type": "setValue", "name": "status:atk", "value": "status:atk+"+(1*point)}
]},
{"text": "防御+"+(2*point), "action": [
{"type": "setValue", "name": "status:def", "value": "status:def+"+(2*point)}
]},
{"text": "生命+"+(200*point), "action": [
{"type": "setValue", "name": "status:hp", "value": "status:hp+"+(200*point)}
]},
]
}
];
}, },
"afterBattle": function(enemyId,x,y,callback) { "afterBattle": function(enemyId,x,y,callback) {
// 战斗结束后触发的事件 // 战斗结束后触发的事件
@ -236,27 +224,24 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.removeBlock(x, y); core.removeBlock(x, y);
} }
// 毒衰咒的处理 // 事件的处理
var todo = [];
var special = enemy.special; var special = enemy.special;
// 中毒 // 中毒
if (core.enemys.hasSpecial(special, 12) && !core.hasFlag('poison')) { if (core.enemys.hasSpecial(special, 12)) {
core.setFlag('poison', true); core.push(todo, [{"type": "setValue", "name": "flag:debuff", "value": "'poison'"}]);
core.push(todo, [{"type": "insert", "name": "毒衰咒处理"}]);
} }
// 衰弱 // 衰弱
if (core.enemys.hasSpecial(special, 13) && !core.hasFlag('weak')) { if (core.enemys.hasSpecial(special, 13)) {
core.setFlag('weak', true); core.push(todo, [{"type": "setValue", "name": "flag:debuff", "value": "'weak'"}]);
if (core.values.weakValue>=1) { // >=1直接扣数值 core.push(todo, [{"type": "insert", "name": "毒衰咒处理"}]);
core.status.hero.atk -= core.values.weakValue;
core.status.hero.def -= core.values.weakValue;
}
else { // <1扣比例
core.setFlag("equip_atk_buff", core.getFlag("equip_atk_buff", 1) - core.values.weakValue);
core.setFlag("equip_def_buff", core.getFlag("equip_def_buff", 1) - core.values.weakValue);
}
} }
// 诅咒 // 诅咒
if (core.enemys.hasSpecial(special, 14) && !core.hasFlag('curse')) { if (core.enemys.hasSpecial(special, 14)) {
core.setFlag('curse', true); core.push(todo, [{"type": "setValue", "name": "flag:debuff", "value": "'curse'"}]);
core.push(todo, [{"type": "insert", "name": "毒衰咒处理"}]);
} }
// 仇恨属性:减半 // 仇恨属性:减半
if (core.flags.hatredDecrease && core.enemys.hasSpecial(special, 17)) { if (core.flags.hatredDecrease && core.enemys.hasSpecial(special, 17)) {
@ -287,30 +272,24 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
core.setFlag('skill', 0); core.setFlag('skill', 0);
core.setFlag('skillName', '无'); core.setFlag('skillName', '无');
} }
core.updateStatusBar(); core.updateStatusBar();
// 事件的处理
var todo = [];
// 如果该点存在,且有事件 -- V2.5.4 以后阻击怪也可以有战后事件了
if (core.isset(x) && core.isset(y)) {
var event = core.floors[core.status.floorId].afterBattle[x+","+y];
if (core.isset(event)) {
// 插入事件
core.unshift(todo, event);
}
}
// 如果有加点 // 如果有加点
var point = core.material.enemys[enemyId].point; var point = core.material.enemys[enemyId].point;
if (core.isset(point) && point>0) { if (core.flags.enableAddPoint && core.isset(point) && point>0) {
core.unshift(todo, core.events.addPoint(core.material.enemys[enemyId])); core.push(todo, [{"type": "setValue", "name": "flag:point", "value": point}]);
core.push(todo, [{"type": "insert", "name": "加点事件"}]);
}
// 如果该点存在,且有事件 -- V2.5.4 以后阻击怪也可以有战后事件了
if (core.isset(x) && core.isset(y)) {
core.push(todo, core.floors[core.status.floorId].afterBattle[x+","+y]);
} }
// 在这里增加其他的自定义事件需求 // 在这里增加其他的自定义事件需求
/* /*
if (enemyId=='xxx') { if (enemyId=='xxx') {
core.unshift(todo, [ core.push(todo, [
{"type": "...", ...}, {"type": "...", ...},
]); ]);
} }

View File

@ -1,4 +1,23 @@
HTML5魔塔样板V2.5.2 HTML5魔塔样板V2.5.4
发布15x15的版本
支持多重装备(一个装备可以装到多个孔上)
工具栏按钮增添至8个快捷商店和虚拟键盘同时显示
点击状态栏的金币图标也可以打开快捷商店
等待事件提供flag:px和flag:py在0~415之间
事件:呼出存读档界面;呼出怪物手册
事件:使用道具,暂停背景音乐,暂停所有音效
type:trigger可以触发系统事件
独立开关
贴图也可以支持帧动画了
图块内置颜色选择器
标题界面增加音乐按钮
等待事件可被Ctrl长按跳过
部分Bug修复大量细节优化性能进一步得到提升
-----------------------------------------------------------------------
HTML5魔塔样板V2.5.3
标题界面事件化;现在可以用事件流来处理标题界面了 标题界面事件化;现在可以用事件流来处理标题界面了
动态canvas管理无限图层可以任意创建图层并使用 动态canvas管理无限图层可以任意创建图层并使用
@ -20,6 +39,8 @@ BGM缓存管理新增事件预加载BGM
地图编辑器中选中点高亮双击选中素材WASD平移大地图 地图编辑器中选中点高亮双击选中素材WASD平移大地图
修复所有Bug部分代码重构大量细节优化 修复所有Bug部分代码重构大量细节优化
-----------------------------------------------------------------------
HTML5魔塔样板V2.5.2 HTML5魔塔样板V2.5.2
怪物和NPC的行走图和朝向问题详见文档 怪物和NPC的行走图和朝向问题详见文档
@ -39,6 +60,8 @@ HTML5魔塔样板V2.5.2
菜单栏中新增虚拟键盘的弹出 菜单栏中新增虚拟键盘的弹出
修复所有已知Bug部分细节优化 修复所有已知Bug部分细节优化
-----------------------------------------------------------------------
HTML5魔塔样板V2.5.1 HTML5魔塔样板V2.5.1
新增事件type:insert可以插入另一个地点的事件执行公共事件 新增事件type:insert可以插入另一个地点的事件执行公共事件