Merge pull request #369 from ckcz123/v2.x

V2.x
This commit is contained in:
Zhang Chen 2019-05-02 21:35:01 +08:00 committed by GitHub
commit 8a16a48420
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 756 additions and 370 deletions

View File

@ -1949,6 +1949,17 @@ errorCallback可选如果失败则会将错误信息传入errorCallback()
此函数是异步的,只能通过回调函数来获得读取的结果或错误信息。
core.setGlobal(key, value)
设置一个全局存储适用于global:xxx。
录像播放时将忽略此函数否则直接调用core.setLocalStorage。
core.getGlobal(key, value)
获得一个全局存储适用于global:xxx支持录像。
正常游戏时将使用core.getLocalStorage获得具体的数据并将结果存放到录像中。
录像播放时会直接从录像中获得对应的数据。
core.clone(data, filter, recursion)
深拷贝一个对象。有关浅拷贝,深拷贝,基本类型和引用类型等相关知识可参见:
https://zhuanlan.zhihu.com/p/26282765

View File

@ -55,6 +55,25 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
## 更新说明
### 2019.5.2 V2.6.1
* [x] 区域优化的录像播放功能R键使用
* [x] 强制战斗可以指定怪物坐标,将自动隐藏并执行该点战后事件
* [x] flag:xxx也支持中文例如 flag:2楼机关门
* [x] 增加文件名映射可以用中文映射到某个图片或bgm文件并使用
* [x] 勇士宽度可以超过32例如48x48的勇士行走图
* [x] 现在允许修改floorId和图块ID了在表格下方
* [x] 增加事件:自动存档,返回标题界面;部分事件优化
* [x] 商店长按空格可以连续加点
* [x] 增设global:xxx使用全局存储可被录像支持
* [x] 支持\b[hero]和\b[null,x,y]来自动调整上下方向
* [x] 支持\t[yellowKey]等只显示图标而没有标题
* [x] 编辑器中前景层对于有事件的点半透明显示
* [x] 存档改成1000页长按上下页可快速翻页
* [x] 录像播放初始默认暂停N键可以单步执行
* [x] 增设本地API文档部分API和事件的优化
* [x] 所有已知的bug修复大量细节优化
### 2019.4.13 V2.6
* [x] 拆分整个项目大幅重构代码新增大量API

View File

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

View File

@ -1,6 +1,6 @@
# 附录API列表
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} *
这里将列出所有被转发到core的API没有被转发的函数此处不会列出请自行在代码中查看。
@ -1915,6 +1915,17 @@ errorCallback可选如果失败则会将错误信息传入errorCallback()
此函数是异步的,只能通过回调函数来获得读取的结果或错误信息。
core.setGlobal(key, value)
设置一个全局存储适用于global:xxx。
录像播放时将忽略此函数否则直接调用core.setLocalStorage。
core.getGlobal(key, value)
获得一个全局存储适用于global:xxx支持录像。
正常游戏时将使用core.getLocalStorage获得具体的数据并将结果存放到录像中。
录像播放时会直接从录像中获得对应的数据。
core.clone(data, filter, recursion)
深拷贝一个对象。有关浅拷贝,深拷贝,基本类型和引用类型等相关知识可参见:
https://zhuanlan.zhihu.com/p/26282765

View File

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

View File

@ -1,6 +1,6 @@
# 事件
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} *
本章内将对样板所支持的事件进行介绍。
@ -188,6 +188,8 @@
从V2.5.2以后,新增了绘制大头像的功能。绘制大头像图的基本写法是`\t[1.png]`或者`\t[标题,1.png]`。
从V2.6开始所有图块都允许只写ID对于非怪物则没有标题。
``` js
[
"一段普通文字",
@ -198,7 +200,9 @@
"\t[小妖精,fairy]这是一段小妖精说的话,使用仙子(fairy)的图标",
"\t[你赢了]直接显示标题为【你赢了】",
"\t[1.png]绘制1.png这个头像图",
"\t[标题,1.png]同时绘制标题和1.png这个头像图"
"\t[标题,1.png]同时绘制标题和1.png这个头像图",
"\t[sword1]获得铁剑,没有标题",
"\t[man]没有标题的npc动画"
]
```
@ -283,18 +287,22 @@
我们可以使用 `status:xxx` 代表勇士的一个属性值;`item:xxx` 代表某个道具的个数;`flag:xxx` 代表某个自定义的变量或flag值。
从V2.6开始,也可以使用`global:xxx`代表全局存储(和存档无关的存储)。
``` js
[
"你当前的攻击力是${status:atk}, 防御是${status:def},坐标是(${status:x},${status:y})",
"你的攻防和的十倍是${10*(status:atk+status:def)}",
"你的红黄蓝钥匙总数为${item:yellowKey+item:blueKey+item:redKey}",
"你访问某个老人的次数为${flag:man_times}",
"当前的存档编号是${global:saveIndex}",
]
```
- `status:xxx` 获取勇士属性时只能使用如下几个hp生命值atk攻击力def防御力mdef魔防值money金币experience经验x勇士的横坐标y勇士的纵坐标direction勇士的方向
- `item:xxx` 中的xxx为道具ID。所有道具的ID定义在items.js中请自行查看。例如`item:centerFly` 代表中心对称飞行器的个数。
- `flag:xxx` 中的xxx为一个自定义的变量/Flag如果没有对其进行赋值则默认值为false。
- `flag:xxx` 中的xxx为一个自定义的变量/Flag支持中文如果没有对其进行赋值则默认值为0。
- `global:xxx` 中的xxx为一个全局存储的名称支持中文如果没有对其进行赋值则默认值为0。
### autoText自动剧情文本
@ -413,7 +421,7 @@ icon是可选的如果设置则会绘制图标其可以是一个有效的I
name为你要修改的属性/道具/Flag每次只能修改一个值。写法和上面完全相同`status:xxx` 表示勇士一个属性,`item:xxx` 表示某个道具个数,`flag:xxx` 表示某个变量或flag值。参见上面的介绍。
value是一个表达式将通过这个表达式计算出的结果赋值给name。该表达式同样可以使用`status:xxx`, `item:xxx`, `flag:xxx`的写法表示勇士当前属性,道具个数和某个变量/Flag值。
value是一个表达式将通过这个表达式计算出的结果赋值给name。该表达式同样可以使用`status:xxx`, `item:xxx`, `flag:xxx`, `global:xxx`的写法表示勇士当前属性,道具个数,某个变量/Flag值和某个全局存储值。
``` js
[
@ -424,6 +432,7 @@ value是一个表达式将通过这个表达式计算出的结果赋值给nam
{"type": "setValue", "name": "item:bomb", "value": "item:bomb+10" } // 炸弹个数+10
{"type": "setValue", "name": "flag:man_times", "value": "0" } // 将变量man_times设为0
{"type": "setValue", "name": "flag:man_times", "value": "flag:man_times+2*status:atk" } // 将变量man_times的值加上勇士的攻击数值的两倍
{"type": "setValue", "name": "global:123", "value": "4"} // 设置全局存储233为4任何存档都可以读取它
]
```
@ -570,24 +579,22 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
`{"type":"trigger"}` 会立刻触发当层另一个地点的自定义事件。
上面我们说到show事件会让一个禁用事件启用且可被交互但是如果我想立刻让它执行应该怎么办呢使用trigger就行。
其基本写法如下:
``` js
[
{"type": "trigger", "loc": [3,6]}, // 立即触发loc位置的事件当前剩下的事件全部不再执行
"执行trigger后这段文字将不会再被显示"
{"type": "trigger", "loc": [3,6], "keep": true}, // 触发loc位置的事件不结束当前事件
]
```
其后面带有loc选项代表另一个地点的坐标。
执行trigger事件后当前事件将立刻被结束剩下所有内容被忽略然后重新启动另一个地点的action事件
keep可选如果此项为true则不会结束当前的事件列表否则会中断当前的事件流
例如上面这个例子,下面的文字将不会再被显示,而是直接跳转到`"3,6"`对应的事件列表从头执行。
从V2.5.4开始允许执行另一个点的系统事件,如打怪开门拾取道具等等,对应点的战后等事件也会被插入执行。
!> 从V2.5.4开始,允许执行另一个点的“系统事件”,如打怪、开门、拾取道具等等。对应点的战后事件等也会被执行
值得注意的是,此事件会**改变当前点坐标**为目标点
### insert插入公共事件或另一个地点的事件并执行
@ -615,11 +622,12 @@ NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`
- floorId可选代表另一个地点所在的楼层如果不写则默认为当前层。
- 从V2.6开始还可以传可选的which可以为`afterBattle`/`afterGetItem`/`afterOpenDoor`,代表插入该点的战后/获得道具后/开门后事件。
和`type:trigger`不同的是,**`type:trigger`是立刻将当前事件结束剩下所有内容都忽略然后重新启动另一个地点的action事件。**
和`type:trigger`不同点如下:
- `type:trigger`只能指定当前楼层且会改变当前点坐标,`type:insert`可以跨楼层且不会改变当前点坐标。
- `type:trigger`如果不设置`keep:true`则还会结束当前事件,`type:insert`而是将另一个点的事件插入到当前事件列表中执行。
- `type:trigger`可以触发系统事件,`type:insert`只能触发该点的自定义事件或战后事件等。
但是`type:insert`不会结束当前事件,而是直接将另一个地点的事件列表“插入”到当前事件列表中执行。
**这个过程中,当前事件不会被结束,当前的楼层和事件坐标不会发生改变。** 插入的事件执行完毕后,会继续执行接下来的内容。
插入的事件执行完毕后,会继续执行接下来的内容。
从V2.6开始,插入事件允许传参。如果需要传参,则需要增加一个`args`数组。
@ -836,28 +844,20 @@ name是可选的代表目标行走图的文件名。
调用battle可强制与某怪物进行战斗而无需去触碰到它
其基本写法是: `{"type": "battle", "id": xxx}`其中xxx为怪物ID。
``` js
[
"\t[blackKing]你终于还是来了。",
"\t[hero]放开我们的公主!",
"\t[blackKing]如果我不愿意呢?",
"\t[hero]无需多说,拔剑吧!",
{"type": "battle", "id": "blackKing"}, // 强制战斗
// 如果战斗失败直接死亡,不会继续触发接下来的剧情。
{"type": "hide", "loc": [10,2]}, // 战斗后需要手动使怪物消失战斗后不会引发afterBattle事件。
{"type": "openDoor", "loc": [8,7]}, // 开门口的机关门
"\t[blackKing]没想到你已经变得这么强大了... 算你厉害。\n公主就交给你了请好好对她。",
{"type": "hide"} // 隐藏本事件
{"type": "battle", "id": "blackKing"}, // 强制战斗黑衣魔王
{"type": "battle", "loc": [2,3]}, // 强制战斗(2,3)点的怪物
],
```
上面就是样板层中右上角的强制战斗例子。
从V2.6开始,有两种写法:
- 写id则视为和空降怪物进行强制战斗不会执行一些战后事件也不会隐藏任何点。
- 写loc可选不填默认当前点则视为和某点怪物进行强制战斗会隐藏该点并且插入该点战后事件执行。
如果强制战斗失败则会立刻生命归0并死亡调用lose函数接下来的事件不会再被执行。
强制战斗不会自动存档,如果战斗失败则立刻死亡。
强制战斗没有指定loc的选项因此战斗后需要调用hide使怪物消失如果有必要
值得注意的是,如果是和某个点的怪物强制战斗,并且该点存在战后事件,执行时会**修改当前点坐标**为目标点
### openDoor开门
@ -867,7 +867,7 @@ name是可选的代表目标行走图的文件名。
[
{"type": "openDoor", "loc": [3,6], "floorId": "MT1"}, // 打开MT1层的[3,6]位置的门
{"type": "openDoor", "loc": [3,6]}, // 如果是本层则可省略floorId
{"type": "openDoor", "loc": [3,6], "needKey": true} // 打开此门需要钥匙
{"type": "openDoor", "loc": [3,6], "needKey": true, "async": true} // 打开此门需要钥匙,异步执行
]
```
@ -879,8 +879,12 @@ loc指定门的坐标floorId指定门所在的楼层ID。如果是当前层
needKey是可选的如果设置为true则需要钥匙才能打开此门。如果没有钥匙则跳过此事件。
async可选如果为true则会异步执行即不等待当前事件执行完毕立刻执行下一个事件
!> needKey仅对当前楼层开门有效跨楼层的门仍然不需要钥匙即可打开如有需求请自行判定。
值得注意的是,如果该点存在开门事件,执行时会**修改当前点坐标**为目标点。
### closeDoor关门
从V2.6开始提供了关门事件`{"type": "closeDoor"}`,拥有关门动画和对应的音效。
@ -903,6 +907,8 @@ yellowWall, blueWall, whiteWall
loc可选为要关的位置不填默认为当前点。
async可选如果为true则会异步执行即不等待当前事件执行完毕立刻执行下一个事件
关门事件需要保证该点是空地,否则将无视此事件。
### changeFloor楼层切换

View File

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

View File

@ -1,6 +1,6 @@
# 个性化
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} *
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。

View File

@ -1,6 +1,6 @@
# 脚本
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.1**,上次更新时间:* {docsify-updated} *
在V2.6版本中,基本对整个项目代码进行了重写,更加方便造塔者的使用和复写函数。
@ -224,7 +224,11 @@ function () {
- 清晰明了。很容易方便知道自己修改过什么,尤其是可以和系统原有代码进行对比。
- 方便整理成新的插件,给其他的塔使用。
如果我想对xxx文件中的yyy函数进行重写其模式一般是`core.xxx.yyy = function (参数列表) { ... }`
一般而言,复写规则如下:
**对xxx文件中的yyy函数进行复写规则是`core.xxx.yyy = function (参数列表) { ... }`。**
但是,对于`registerXXX`所注册的函数是无效的,例如直接复写`core.control._animationFrame_globalAnimate`函数是没有效果的。对于这种情况引入的函数,需要注册同名函数,可参见最下面的样例。
下面是几个例子,从简单到复杂。
@ -317,6 +321,32 @@ core.maps.drawMap = function (floorId, callback) {
详见[call和apply的用法](https://www.jianshu.com/p/80ea0d1c04f8)。
### 复写全局动画绘制函数
全局动画绘制在`control.js`的`_animationFrame_globalAnimate`函数。
注意到此函数是由`registerAnimationFrame`注册的,因此直接复写是无效的。
其在control.js的注册的定义如下
```js
// 注册全局动画函数
this.registerAnimationFrame("globalAnimate", true, this._animationFrame_globalAnimate);
```
因此,可以在插件中自行注册一个**同名**的函数来覆盖原始的内容。
```js
// 插件中复写全局动画绘制函数
this.myGlobalAnimate = function (timestamp) {
// ...... 实际复写的函数内容
}
// 注册同名globalAnimate函数来覆盖系统原始内容
core.registerAnimationFrame("globalAnimate", true, "myGlobalAnimate");
```
==========================================================================================
[继续阅读下一章API列表](api)

View File

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

View File

@ -287,6 +287,7 @@ action
| wait_s
| waitAsync_s
| battle_s
| battle_1_s
| openDoor_s
| closeDoor_s
| changeFloor_s
@ -441,7 +442,7 @@ helpUrl : https://h5mota.com/games/template/docs/#/event?id=settext%EF%BC%9A%E8%
default : [null,"",null,"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',null,"","",""]
SetTextPosition_List_0 =SetTextPosition_List_0==='null'?'': ', "position": "'+SetTextPosition_List_0+'"';
SetTextAlign_List_0 =SetTextAlign_List_0==='null'?'': ', "align": "'+SetTextAlign_List_0+'"';
var colorRe = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/;
var colorRe = MotaActionFunctions.pattern.colorRe;
if (EvalString_0) {
if (!/^\d+$/.test(EvalString_0))throw new Error('像素偏移量必须是整数或不填');
EvalString_0 = ', "offset": '+EvalString_0;
@ -587,7 +588,7 @@ default : ["","","",500,false]
colour : this.mapColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
var pattern1 = /^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/;
var pattern1 = MotaActionFunctions.pattern.id;
if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){
EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0);
EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1);
@ -620,7 +621,7 @@ default : ["","","",500,false]
colour : this.mapColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
var pattern1 = /^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/;
var pattern1 = MotaActionFunctions.pattern.id;
if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){
EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0);
EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1);
@ -643,15 +644,16 @@ return code;
*/;
trigger_s
: '触发事件' 'x' PosString ',' 'y' PosString Newline
: '触发事件' 'x' PosString ',' 'y' PosString '不结束当前事件' Bool Newline
/* trigger_s
tooltip : trigger: 立即触发另一个地点的事件
helpUrl : https://h5mota.com/games/template/docs/#/event?id=trigger%EF%BC%9A%E7%AB%8B%E5%8D%B3%E8%A7%A6%E5%8F%91%E5%8F%A6%E4%B8%80%E4%B8%AA%E5%9C%B0%E7%82%B9%E7%9A%84%E4%BA%8B%E4%BB%B6
default : ["0","0"]
default : ["0","0",false]
colour : this.eventColor
var code = '{"type": "trigger", "loc": ['+PosString_0+','+PosString_1+']},\n';
Bool_0 = Bool_0 ?', "keep": true':'';
var code = '{"type": "trigger", "loc": ['+PosString_0+','+PosString_1+']'+Bool_0+'},\n';
return code;
*/;
@ -761,7 +763,7 @@ default : ["","",""]
colour : this.mapColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
var pattern1 = /^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/;
var pattern1 = MotaActionFunctions.pattern.id;
if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){
EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0);
EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1);
@ -792,7 +794,7 @@ default : ["","",""]
colour : this.mapColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
var pattern1 = /^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/;
var pattern1 = MotaActionFunctions.pattern.id;
if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){
EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0);
EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1);
@ -823,7 +825,7 @@ default : ["bg","","",""]
colour : this.mapColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
var pattern1 = /^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/;
var pattern1 = MotaActionFunctions.pattern.id;
if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){
EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0);
EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1);
@ -854,7 +856,7 @@ default : ["bg","","",""]
colour : this.mapColor
var floorstr = '';
if (EvalString_0 && EvalString_1) {
var pattern1 = /^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/;
var pattern1 = MotaActionFunctions.pattern.id;
if(pattern1.test(EvalString_0) || pattern1.test(EvalString_1)){
EvalString_0=MotaActionFunctions.PosString_pre(EvalString_0);
EvalString_1=MotaActionFunctions.PosString_pre(EvalString_1);
@ -984,14 +986,32 @@ var code = '{"type": "battle", "id": "'+IdString_0+'"},\n';
return code;
*/;
battle_1_s
: '强制战斗' 'x' PosString? ',' 'y' PosString? Newline
/* battle_1_s
tooltip : battle: 强制战斗
helpUrl : https://h5mota.com/games/template/docs/#/event?id=battle%EF%BC%9A%E5%BC%BA%E5%88%B6%E6%88%98%E6%96%97
default : ["","",""]
colour : this.mapColor
var floorstr = '';
if (PosString_0 && PosString_1) {
floorstr = ', "loc": ['+PosString_0+','+PosString_1+']';
}
var code = '{"type": "battle"'+floorstr+'},\n';
return code;
*/;
openDoor_s
: '开门' 'x' PosString? ',' 'y' PosString? '楼层' IdString? '需要钥匙' Bool? Newline
: '开门' 'x' PosString? ',' 'y' PosString? '楼层' IdString? '需要钥匙' Bool? '不等待执行完毕' Bool Newline
/* openDoor_s
tooltip : openDoor: 开门,楼层可不填表示当前层
helpUrl : https://h5mota.com/games/template/docs/#/event?id=opendoor%EF%BC%9A%E5%BC%80%E9%97%A8
default : ["","","",false]
default : ["","","",false,false]
colour : this.mapColor
IdString_0 = IdString_0 && (', "floorId": "'+IdString_0+'"');
var floorstr = '';
@ -999,24 +1019,26 @@ if (PosString_0 && PosString_1) {
floorstr = ', "loc": ['+PosString_0+','+PosString_1+']';
}
Bool_0 = Bool_0 ? ', "needKey": true' : '';
var code = '{"type": "openDoor"'+floorstr+IdString_0+Bool_0+'},\n';
Bool_1 = Bool_1 ? ', "async": true' : '';
var code = '{"type": "openDoor"'+floorstr+IdString_0+Bool_0+Bool_1+'},\n';
return code;
*/;
closeDoor_s
: '关门' 'x' PosString? ',' 'y' PosString? 'ID' IdString Newline
: '关门' 'x' PosString? ',' 'y' PosString? 'ID' IdString '不等待执行完毕' Bool Newline
/* closeDoor_s
tooltip : closeDoor: 关门事件,需要该点本身无事件
helpUrl : https://h5mota.com/games/template/docs/#/event?id=opendoor%EF%BC%9A%E5%BC%80%E9%97%A8
default : ["","","yellowDoor"]
default : ["","","yellowDoor",false]
colour : this.mapColor
var floorstr = '';
if (PosString_0 && PosString_1) {
floorstr = ', "loc": ['+PosString_0+','+PosString_1+']';
}
var code = '{"type": "closeDoor", "id": "'+IdString_0+'"'+floorstr+'},\n';
Bool_0 = Bool_0 ? ', "async": true' : '';
var code = '{"type": "closeDoor", "id": "'+IdString_0+'"'+floorstr+Bool_0+'},\n';
return code;
*/;
@ -1157,7 +1179,7 @@ helpUrl : https://h5mota.com/games/template/docs/#/event?id=animate%EF%BC%9A%E6%
default : ["zone","hero",false]
colour : this.soundColor
if (EvalString_0) {
if(/^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+),flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/.test(EvalString_0)) {
if(MotaActionFunctions.pattern.id2.test(EvalString_0)) {
EvalString_0=', "loc": ["'+EvalString_0.split(',').join('","')+'"]';
} else if (/hero|([+-]?\d+),([+-]?\d+)/.test(EvalString_0)) {
if(EvalString_0.indexOf(',')!==-1)EvalString_0='['+EvalString_0+']';
@ -1293,7 +1315,7 @@ tooltip : setCurtain: 更改画面色调,动画时间可不填
helpUrl : https://h5mota.com/games/template/docs/#/event?id=setcurtain%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83
default : ["255,255,255,1",'rgba(255,255,255,1)',500,false]
colour : this.soundColor
var colorRe = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/;
var colorRe = MotaActionFunctions.pattern.colorRe;
if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1');
Int_0 = Int_0!=='' ?(', "time": '+Int_0):'';
var async = Bool_0?', "async": true':'';
@ -1324,7 +1346,7 @@ tooltip : screenFlash: 画面闪烁,动画时间可不填
helpUrl : https://h5mota.com/games/template/docs/#/event?id=screenFlash%EF%BC%9A%E7%94%BB%E9%9D%A2%E9%97%AA%E7%83%81
default : ["255,255,255,1",'rgba(255,255,255,1)',500,1,false]
colour : this.soundColor
var colorRe = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/;
var colorRe = MotaActionFunctions.pattern.colorRe;
if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1');
Int_1 = Int_1!=='' ?(', "times": '+Int_1):'';
var async = Bool_0?', "async": true':'';
@ -1354,7 +1376,7 @@ move_s
/* move_s
tooltip : move: 让某个NPC/怪物移动,位置可不填代表当前事件
helpUrl : https://h5mota.com/games/template/docs/#/event?id=move%EF%BC%9A%E8%AE%A9%E6%9F%90%E4%B8%AAnpc%E6%80%AA%E7%89%A9%E7%A7%BB%E5%8A%A8
default : ["","",500,false,false,"上右3下2左上左2"]
default : ["","",500,false,false,"上右3下2后4左前2"]
colour : this.mapColor
var floorstr = '';
if (PosString_0 && PosString_1) {
@ -1682,7 +1704,7 @@ helpUrl : https://h5mota.com/games/template/docs/#/event?id=choices%EF%BC%9A%E7%
default : ["提示文字:红钥匙","",""]
colour : this.subColor
if (EvalString_1) {
var colorRe = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/;
var colorRe = MotaActionFunctions.pattern.colorRe;
if (colorRe.test(EvalString_1))
EvalString_1 = ', "color": ['+EvalString_1+']';
else
@ -1735,7 +1757,7 @@ return code;
*/;
break_s
: '跳出循环' Newline
: '跳出当前循环或公共事件' Newline
/* break_s
tooltip : break跳出循环, 如果break事件不在任何循环中被执行则和exit等价即会立刻结束当前事件
@ -2113,8 +2135,8 @@ FixedId_List
/*FixedId_List ['status:hp','status:atk','status:def','status:mdef','item:yellowKey','item:blueKey','item:redKey','status:money','status:experience']*/;
Id_List
: '变量' | '状态' | '物品' | '独立开关'
/*Id_List ['flag','status','item', 'switch']*/;
: '变量' | '状态' | '物品' | '独立开关' | '全局存储'
/*Id_List ['flag','status','item', 'switch', 'global']*/;
//转blockly后不保留需要加"
EvalString
@ -2532,12 +2554,12 @@ ActionParser.prototype.parseAction = function() {
case "openDoor": // 开一个门, 包括暗墙
data.loc=data.loc||['','']
this.next = MotaActionBlocks['openDoor_s'].xmlText([
data.loc[0],data.loc[1],data.floorId||'',data.needKey||false,this.next]);
data.loc[0],data.loc[1],data.floorId||'',data.needKey||false,data.async||false,this.next]);
break;
case "closeDoor": // 关一个门,需要该点无事件
data.loc=data.loc||['','']
this.next = MotaActionBlocks['closeDoor_s'].xmlText([
data.loc[0],data.loc[1],data.id,this.next]);
data.loc[0],data.loc[1],data.id,data.async||false,this.next]);
break;
case "useItem": // 使用道具
this.next = MotaActionBlocks['useItem_s'].xmlText([
@ -2552,12 +2574,19 @@ ActionParser.prototype.parseAction = function() {
data.id,this.next]);
break;
case "battle": // 强制战斗
this.next = MotaActionBlocks['battle_s'].xmlText([
data.id,this.next]);
if (data.id) {
this.next = MotaActionBlocks['battle_s'].xmlText([
data.id,this.next]);
}
else {
data.loc = data.loc || [];
this.next = MotaActionBlocks['battle_1_s'].xmlText([
data.loc[0],data.loc[1],this.next]);
}
break;
case "trigger": // 触发另一个事件;当前事件会被立刻结束。需要另一个地点的事件是有效的
this.next = MotaActionBlocks['trigger_s'].xmlText([
data.loc[0],data.loc[1],this.next]);
data.loc[0],data.loc[1],data.keep,this.next]);
break;
case "insert": // 强制插入另一个点的事件在当前事件列表执行,当前坐标和楼层不会改变
if (data.args instanceof Array) {
@ -2857,14 +2886,14 @@ MotaActionFunctions.EvalString_pre = function(EvalString){
MotaActionFunctions.IdString_pre = function(IdString){
if (IdString.indexOf('__door__')!==-1) throw new Error('请修改开门变量__door__如door1door2door3等依次向后。请勿存在两个门使用相同的开门变量。');
if (IdString && !(/^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/.test(IdString)) && !(/^[0-9a-zA-Z_][0-9a-zA-Z_\-:]*$/.test(IdString)))
if (IdString && !(MotaActionFunctions.pattern.id.test(IdString)) && !(MotaActionFunctions.pattern.idWithoutFlag.test(IdString)))
throw new Error('id: '+IdString+'中包含了0-9 a-z A-Z _ - :之外的字符');
return IdString;
}
MotaActionFunctions.PosString_pre = function(PosString){
if (!PosString || /^-?\d+$/.test(PosString)) return PosString;
if (!(/^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/.test(PosString)))throw new Error(PosString+'中包含了0-9 a-z A-Z _ 和中文之外的字符,或者是没有以flag: 开头');
if (!(MotaActionFunctions.pattern.id.test(PosString)))throw new Error(PosString+'中包含了0-9 a-z A-Z _ 和中文之外的字符,或者是没有以flag: 开头');
return '"'+PosString+'"';
}
@ -2906,4 +2935,10 @@ MotaActionFunctions.StepString_pre = function(StepString){
return ans;
}
MotaActionFunctions.pattern=MotaActionFunctions.pattern||{};
MotaActionFunctions.pattern.id=/^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/;
MotaActionFunctions.pattern.id2=/^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+),flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/;
MotaActionFunctions.pattern.idWithoutFlag=/^[0-9a-zA-Z_][0-9a-zA-Z_\-:]*$/;
MotaActionFunctions.pattern.colorRe=/^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/;
*/

View File

@ -42,8 +42,6 @@ editor.util.guid()//产生一个可以作为id的长随机字符串
提供了以下函数进行楼层`map`数组相关的操作
```javascript
editor.file.getFloorFileList
editor.file.loadFloorFile
editor.file.saveFloorFile
editor.file.saveFloorFileAs
```

View File

@ -53,6 +53,7 @@ editor.prototype.init = function (callback) {
editor_file_wrapper(editor);
editor_table_wrapper(editor);
editor_unsorted_1_wrapper(editor);
editor.printe=printe;
afterMainInit();
});

View File

@ -112,6 +112,7 @@ editor_blockly = function () {
MotaActionBlocks['unfollow_s'].xmlText(),
],
'地图处理':[
MotaActionBlocks['battle_1_s'].xmlText(),
MotaActionBlocks['openDoor_s'].xmlText(),
MotaActionBlocks['closeDoor_s'].xmlText(),
MotaActionBlocks['show_s'].xmlText(),

View File

@ -3,6 +3,7 @@ editor_file_wrapper = function (editor) {
}
// 这个函数之后挪到editor.table?
editor_file_proto.prototype.loadCommentjs=function(callback){
var commentjs = {
'comment': 'comment',

View File

@ -7,23 +7,6 @@ editor_file = function (editor, callback) {
///////////////////////////////////////////////////////////////////////////
editor.file.getFloorFileList = function (callback) {
checkCallback(callback);
/* var fs = editor.fs;
fs.readdir('project/floors',function(err, data){
callback([data,err]);
}); */
callback([editor.core.floorIds, null]);
}
//callback([Array<String>,err:String])
editor.file.loadFloorFile = function (filename, callback) {
//filename不含'/'不含'.js'
checkCallback(callback);
editor.currentFloorId = editor.core.status.floorId;
editor.currentFloorData = editor.core.floors[editor.currentFloorId];
}
//callback(err:String)
editor.file.saveFloorFile = function (callback) {
checkCallback(callback);
/* if (!isset(editor.currentFloorId) || !isset(editor.currentFloorData)) {
@ -31,31 +14,16 @@ editor_file = function (editor, callback) {
} */
var filename = 'project/floors/' + editor.currentFloorId + '.js';
var datastr = ['main.floors.', editor.currentFloorId, '=\n'];
if (editor.currentFloorData.map == 'new') {
/*
editor.currentFloorData.map = editor.map.map(function (v) {
return v.map(function () {
return 0
for(var ii=0,name;name=['map','bgmap','fgmap'][ii];ii++){
var mapArray=editor[name].map(function (v) {
return v.map(function (v) {
return v.idnum || v || 0
})
});
*/
var width = parseInt(document.getElementById('newMapWidth').value);
var height = parseInt(document.getElementById('newMapHeight').value);
var row = [];
for (var i=0;i<width;i++) row.push(0);
editor.currentFloorData.map = [];
for (var i=0;i<height;i++) editor.currentFloorData.map.push(row);
}
else{
for(var ii=0,name;name=['map','bgmap','fgmap'][ii];ii++){
var mapArray=editor[name].map(function (v) {
return v.map(function (v) {
return v.idnum || v || 0
})
});
editor.currentFloorData[name]=mapArray;
}
editor.currentFloorData[name]=mapArray;
}
// format 更改实现方式以支持undefined删除
var tempJsonObj=Object.assign({},editor.currentFloorData);
var tempMap=[['map',editor.util.guid()],['bgmap',editor.util.guid()],['fgmap',editor.util.guid()]];
@ -87,39 +55,35 @@ editor_file = function (editor, callback) {
name = saveFilename.substring(2);
title = "主塔 "+name+" 层";
}
editor.currentFloorData = {
var width = parseInt(document.getElementById('newMapsWidth').value);
var height = parseInt(document.getElementById('newMapsHeight').value);
var row = [], map = [];
for (var i=0;i<width;i++) row.push(0);
for (var i=0;i<height;i++) map.push(row);
editor.currentFloorData = Object.assign(JSON.parse(JSON.stringify(editor.file.comment._data.floors_template)), {
floorId: saveFilename,
title: title,
name: name,
width: parseInt(document.getElementById('newMapWidth').value),
height: parseInt(document.getElementById('newMapHeight').value),
canFlyTo: saveStatus?currData.canFlyTo:true,
canUseQuickShop: saveStatus?currData.canUseQuickShop:true,
cannotViewMap: saveStatus?currData.cannotViewMap:false,
cannotMoveDirectly: saveStatus?currData.cannotMoveDirectly:false,
images: [],
item_ratio: saveStatus?currData.item_ratio:1,
defaultGround: saveStatus?currData.defaultGround:"ground",
bgm: saveStatus?currData.bgm:null,
upFloor: null,
downFloor: null,
color: saveStatus?currData.color:null,
weather: saveStatus?currData.weather:null,
firstArrive: [],
eachArrive: [],
parallelDo: "",
events: {},
changeFloor: {},
afterBattle: {},
afterGetItem: {},
afterOpenDoor: {},
cannotMove: {}
};
width: width,
height: height,
map: map,
},saveStatus?{
canFlyTo: currData.canFlyTo,
canUseQuickShop: currData.canUseQuickShop,
cannotViewMap: currData.cannotViewMap,
cannotMoveDirectly: currData.cannotMoveDirectly,
item_ratio: currData.item_ratio,
defaultGround: currData.defaultGround,
bgm: currData.bgm,
color: currData.color,
weather: currData.weather,
}:{});
Object.keys(editor.currentFloorData).forEach(function (t) {
if (editor.currentFloorData[t] == null)
delete editor.currentFloorData[t];
})
editor.currentFloorData.map = "new";
editor.currentFloorId = saveFilename;
editor.file.saveFloorFile(callback);
}
@ -145,35 +109,24 @@ editor_file = function (editor, callback) {
var datas = [];
for (var i=from;i<=to;i++) {
var datastr = ['main.floors.', floorIdList[i-from], '=\n{'];
var data = {
var data = Object.assign(JSON.parse(JSON.stringify(editor.file.comment._data.floors_template)), {
floorId: floorIdList[i-from],
title: calValue(document.getElementById('newFloorTitles').value, i),
name: calValue(document.getElementById('newFloorNames').value, i),
width: width,
height: height,
map: map,
canFlyTo: saveStatus?currData.canFlyTo:true,
canUseQuickShop: saveStatus?currData.canUseQuickShop:true,
cannotViewMap: saveStatus?currData.cannotViewMap:false,
cannotMoveDirectly: saveStatus?currData.cannotMoveDirectly:false,
images: [],
item_ratio: saveStatus?currData.item_ratio:1,
defaultGround: saveStatus?currData.defaultGround:"ground",
bgm: saveStatus?currData.bgm:null,
upFloor: null,
downFloor: null,
color: saveStatus?currData.color:null,
weather: saveStatus?currData.weather:null,
firstArrive: [],
eachArrive: [],
parallelDo: "",
events: {},
changeFloor: {},
afterBattle: {},
afterGetItem: {},
afterOpenDoor: {},
cannotMove: {}
};
},saveStatus?{
canFlyTo: currData.canFlyTo,
canUseQuickShop: currData.canUseQuickShop,
cannotViewMap: currData.cannotViewMap,
cannotMoveDirectly: currData.cannotMoveDirectly,
item_ratio: currData.item_ratio,
defaultGround: currData.defaultGround,
bgm: currData.bgm,
color: currData.color,
weather: currData.weather,
}:{});
Object.keys(data).forEach(function (t) {
if (data[t] == null)
delete data[t];
@ -308,70 +261,78 @@ editor_file = function (editor, callback) {
editor.file.changeIdAndIdnum = function (id, idnum, info, callback) {
checkCallback(callback);
//检查maps中是否有重复的idnum或id
var change = -1;
for (var ii in editor.core.maps.blocksInfo) {
if (ii == idnum) {
//暂时只允许创建新的不允许修改已有的
//if (info.idnum==idnum){change=ii;break;}//修改id
callback('idnum重复了');
return;
}
if (editor.core.maps.blocksInfo[ii].id == id) {
//if (info.id==id){change=ii;break;}//修改idnum
callback('id重复了');
return;
}
}
/*
if (change!=-1 && change!=idnum){//修改idnum
editor.core.maps.blocksInfo[idnum] = editor.core.maps.blocksInfo[change];
delete(editor.core.maps.blocksInfo[change]);
} else if (change==idnum) {//修改id
var oldid = editor.core.maps.blocksInfo[idnum].id;
editor.core.maps.blocksInfo[idnum].id = id;
for(var ii in editor.core.icons.icons){
if (ii.hasOwnProperty(oldid)){
ii[id]=ii[oldid];
delete(ii[oldid]);
}
}
} else {//创建新的
editor.core.maps.blocksInfo[idnum]={'cls': info.images, 'id':id};
editor.core.icons.icons[info.images][id]=info.y;
}
*/
var templist = [];
var tempcallback = function (err) {
templist.push(err);
if (templist.length == 2) {
if (templist[0] != null || templist[1] != null)
callback((templist[0] || '') + '\n' + (templist[1] || ''));
//这里如果一个成功一个失败会出严重bug
else
callback(null);
}
}
saveSetting('maps', [["add", "['" + idnum + "']", {'cls': info.images, 'id': id}]], tempcallback);
saveSetting('icons', [["add", "['" + info.images + "']['" + id + "']", info.y]], tempcallback);
if (info.images === 'items') {
saveSetting('items', [["add", "['items']['" + id + "']", editor.file.comment._data.items_template]], function (err) {
if (err) {
printe(err);
throw(err)
var changeOrNew=core.isset(editor_mode.info.id)?'change':'new'
if(changeOrNew=='new'){
//检查maps中是否有重复的idnum或id
for (var ii in editor.core.maps.blocksInfo) {
if (ii == idnum) {
callback('idnum重复了');
return;
}
});
}
if (info.images === 'enemys' || info.images === 'enemy48') {
saveSetting('enemys', [["add", "['" + id + "']", editor.file.comment._data.enemys_template]], function (err) {
if (err) {
printe(err);
throw(err)
if (editor.core.maps.blocksInfo[ii].id == id) {
callback('id重复了');
return;
}
});
}
}
var templist = [];
var tempcallback = function (err) {
templist.push(err);
if (templist.length == 2) {
if (templist[0] != null || templist[1] != null)
callback((templist[0] || '') + '\n' + (templist[1] || ''));
//这里如果一个成功一个失败会出严重bug
else
callback(null);
}
}
saveSetting('maps', [["add", "['" + idnum + "']", {'cls': info.images, 'id': id}]], tempcallback);
saveSetting('icons', [["add", "['" + info.images + "']['" + id + "']", info.y]], tempcallback);
if (info.images === 'items') {
saveSetting('items', [["add", "['items']['" + id + "']", editor.file.comment._data.items_template]], function (err) {
if (err) {
printe(err);
throw(err)
}
});
}
if (info.images === 'enemys' || info.images === 'enemy48') {
saveSetting('enemys', [["add", "['" + id + "']", editor.file.comment._data.enemys_template]], function (err) {
if (err) {
printe(err);
throw(err)
}
});
}
callback(null);
callback(null);
}else{
//检查maps中是否有重复的idnum或id
for (var ii in editor.core.maps.blocksInfo) {
if (editor.core.maps.blocksInfo[ii].id == id) {
callback('id重复了');
return;
}
}
idnum = info.idnum;
maps_90f36752_8815_4be8_b32b_d7fad1d0542e[idnum].id = id;
var arr=[icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1,items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a,{enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80:enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80}]
arr.forEach(function (obj) {
for(var jj in obj){
var ii=obj[jj]
if (ii.hasOwnProperty(info.id)){
ii[id]=ii[info.id];
delete(ii[info.id]);
}
}
});
editor.file.save_icons_maps_items_enemys(callback)
}
}
//callback(err:String)
editor.file.editItem = function (id, actionList, callback) {
@ -770,6 +731,30 @@ editor_file = function (editor, callback) {
}
}
editor.file.save_icons_maps_items_enemys=function(callback){
var check=[]
saveSetting('icons',[],function(err){
if(err){callback(err);return;}
check.push('icons')
if(check.length==4)callback(null);
})
saveSetting('maps',[],function(err){
if(err){callback(err);return;}
check.push('maps')
if(check.length==4)callback(null);
})
saveSetting('items',[],function(err){
if(err){callback(err);return;}
check.push('items')
if(check.length==4)callback(null);
})
saveSetting('enemys',[],function(err){
if(err){callback(err);return;}
check.push('enemys')
if(check.length==4)callback(null);
})
}
var saveSetting = function (file, actionList, callback) {
//console.log(file);
//console.log(actionList);

View File

@ -5,7 +5,10 @@ editor_game_wrapper = function (editor, main, core) {
this.replacerRecord = {}
}
//////////////////// 修改数据相关 ////////////////////
// 三个 replacer 和 replacerRecord 暂时放在此处
editor_game.prototype.replacerForLoading = function (_key, value) {
var rmap = editor.game.replacerRecord;
if (value instanceof Function) {
@ -29,7 +32,7 @@ editor_game_wrapper = function (editor, main, core) {
return value
}
editor_game.prototype.getValue = function(field){
editor_game.prototype.getValue = function (field) {
var rmap = editor.game.replacerRecord;
var value = eval(field)
if (rmap.hasOwnProperty(oldval)) {
@ -39,13 +42,13 @@ editor_game_wrapper = function (editor, main, core) {
}
}
editor_game.prototype.setValue = function(field,value){
editor_game.prototype.setValue = function (field, value) {
var rmap = editor.game.replacerRecord;
var oldval = eval(field)
if (rmap.hasOwnProperty(oldval)) {
rmap[value]=eval(value)
rmap[value] = eval(value)
} else {
eval(field+'='+value)
eval(field + '=' + value)
}
}
@ -62,6 +65,9 @@ editor_game_wrapper = function (editor, main, core) {
data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = JSON.parse(JSON.stringify(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d, rf));
}
//////////////////// 加载游戏数据相关 ////////////////////
// 初始化数字与地图图块的对应
editor_game.prototype.idsInit = function (maps, icons) {
editor.ids = [0];
editor.indexs = [];
@ -125,6 +131,7 @@ editor_game_wrapper = function (editor, main, core) {
}
}
// 获取当前地图
editor_game.prototype.fetchMapFromCore = function () {
var mapArray = core.maps.saveMap(core.status.floorId);
editor.map = mapArray.map(function (v) {
@ -158,6 +165,16 @@ editor_game_wrapper = function (editor, main, core) {
}
}
// 获取地图列表
editor_game.prototype.getFloorFileList = function (callback) {
// callback([Array<String>,err:String])
editor.util.checkCallback(callback);
/* editor.fs.readdir('project/floors',function(err, data){
callback([data,err]);
}); */
callback([editor.core.floorIds, null]);
}
editor.constructor.prototype.game = new editor_game();
}
//editor_game_wrapper(editor);

View File

@ -145,13 +145,15 @@ editor_mode = function (editor) {
if (!core.isset(editor_mode.info.id)) {
// document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML = '';
document.getElementById('enemyItemTable').style.display = 'none';
document.getElementById('newIdIdnum').style.display = 'block';
document.getElementById('enemyItemTable').style.display = 'none';
document.getElementById('changeId').style.display = 'none';
return;
}
document.getElementById('newIdIdnum').style.display = 'none';
document.getElementById('enemyItemTable').style.display = 'block';
document.getElementById('changeId').style.display = 'block';
var objs = [];
if (editor_mode.info.images == 'enemys' || editor_mode.info.images == 'enemy48') {

View File

@ -19,7 +19,7 @@ editor_unsorted_2_wrapper=function(editor_mode){
printe(err);
throw(err)
}
printe('添加ididnum成功,请F5刷新编辑器');
printe('添加ididnum成功,请F5刷新编辑器');
});
} else {
printe('请输入id和idnum');
@ -36,8 +36,28 @@ editor_unsorted_2_wrapper=function(editor_mode){
})
}
var changeId = document.getElementById('changeId');
changeId.children[1].onclick = function () {
var id = changeId.children[0].value;
if (id) {
if (!/^[0-9a-zA-Z_]+$/.test(id)) {
printe('不合法的id请使用字母、数字或下划线')
return;
}
editor.file.changeIdAndIdnum(id, null, editor_mode.info, function (err) {
if (err) {
printe(err);
throw(err);
}
printe('修改id成功,请F5刷新编辑器');
});
} else {
printe('请输入要修改到的ID');
}
}
var selectFloor = document.getElementById('selectFloor');
editor.file.getFloorFileList(function (floors) {
editor.game.getFloorFileList(function (floors) {
var outstr = [];
floors[0].forEach(function (floor) {
outstr.push(["<option value='", floor, "'>", floor, '</option>\n'].join(''));
@ -165,6 +185,41 @@ editor_unsorted_2_wrapper=function(editor_mode){
});
}
var changeFloorId = document.getElementById('changeFloorId');
changeFloorId.children[1].onclick = function () {
var floorId = changeFloorId.children[0].value;
if (floorId) {
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(floorId)) {
printe("楼层名 "+floorId+" 不合法!请使用字母、数字、下划线,且不能以数字开头!");
return;
}
if (main.floorIds.indexOf(floorId)>=0) {
printe("楼层名 "+floorId+" 已存在!");
return;
}
var currentFloorId = editor.currentFloorId;
editor.currentFloorId = floorId;
editor.currentFloorData.floorId = floorId;
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err);
}
core.floorIds[core.floorIds.indexOf(currentFloorId)] = floorId;
editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0])
}
alert("修改floorId成功需要刷新编辑器生效。\n请注意原始的楼层文件没有删除请根据需要手动删除。");
window.location.reload();
});
});
} else {
printe('请输入要修改到的floorId');
}
}
var ratio = 1;
var appendPicCanvas = document.getElementById('appendPicCanvas');
var bg = appendPicCanvas.children[0];

View File

@ -157,6 +157,17 @@ editor_util_wrapper = function (editor) {
}).join(''))
}
editor_util.prototype.isset = function (val) {
return val != null && !(typeof val == 'number' && isNaN(val));
}
editor_util.prototype.checkCallback=function(callback){
if (!editor.util.isset(callback)) {
editor.printe('未设置callback');
throw('未设置callback')
}
}
editor.constructor.prototype.util = new editor_util();
}
//editor_util_wrapper(editor);

View File

@ -1,18 +1,27 @@
# 重构
总体思路
+ 按功能拆分文件
+ 左侧页面模块化, 方便添加
+ 不同的模式的文件操作尽可能模块化
目前主要在重构editor_file, 思路是editor.file负责把editor.game内的游戏数据格式化成字符串以及写入到文件, 由editor.game来修改数据
+ editor.file维护一些标记, 描述哪些数据需要格式化并写入, 在save时写入文件(自动保存的话就是每次修改数据都触发save)
+ editor.game修改数据, 并修改editor.file中的标记
+ 此思路下editor.file的大部分内容会挪到editor.game, editor.game和editor.table可能会再进一步合并拆分
editor_file之后是更改editor.map的储存方式, 现有的存对象的模式要在对象和数字间来回转换, 非常繁琐和奇怪
再之后是把editor_unsorted_*.js整理清晰
## 文件结构
+ [ ] editor_blockly 图块化事件编辑器
+ [ ] editor_multi 多行文本编辑器
+ [x] editor_table 处理表格的生成, 及其响应的事件, 从原editor\_mode中分离
+ [ ] editor_file 调用fs.js编辑文件, 把原editor\_file模块化
+ [ ] editor_game 处理来自core的数据, 导入为editor的数据, 从原editor中分离. **只有此文件允许`\s(main|core)`形式的调用**(以及其初始化`editor_game_wrapper(editor, main, core);`)
+ [x] editor_util 生成guid等函数, 从editor分离
+ [ ] editor_file 调用fs.js编辑文件, 把原editor\_file模块化, 并且只负责文件写入
+ [ ] editor_game 处理游戏数据, 导入为editor的数据, 编辑数据, 从原editor和editor_file中抽离. **只有此文件允许`\s(main|core)`形式的调用**(以及其初始化`editor_game_wrapper(editor, main, core);`)
+ [x] editor_util 生成guid/处理颜色 等函数, 从editor分离
+ [ ] editor 执行初始化流程加组合各组件
+ [ ] 原editor_mode 移除
+ [x] 原vm 移除

View File

@ -81,12 +81,12 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_lint": true,
"_data": "当前能否使用该道具仅对cls为tools或constants有效。"
},
"canEquip": {
"equipCondition": {
"_leaf": true,
"_type": "textarea",
"_string": true,
"_lint": true,
"_data": "当前装备某个装备仅对cls为equips有效。\n与canUseItemEffect不同这里null代表可以装备。"
"_data": "能装备某个装备的条件仅对cls为equips有效。\n与canUseItemEffect不同这里null代表可以装备。"
}
}
},
@ -230,7 +230,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_type": "select",
"_select": {
"values": [
null,
"null",
"openDoor",
"passNet",
"changeLight",
@ -245,9 +245,9 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
"_type": "select",
"_select": {
"values": [
null,
true,
false
"null",
"true",
"false"
]
},
"_data": "该图块是否不可通行true代表不可通行false代表可通行null代表使用系统缺省值"
@ -462,6 +462,35 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = {
}
}
}
},
"floors_template": {
"floorId": "to be covered",
"title": "new floor",
"name": "new floor",
"width": 13,
"height": 13,
"canFlyTo": true,
"canUseQuickShop": true,
"cannotViewMap": false,
"cannotMoveDirectly": false,
"images": [],
"item_ratio": 1,
"defaultGround": "ground",
"bgm": null,
"upFloor": null,
"downFloor": null,
"color": null,
"weather": null,
"firstArrive": [],
"eachArrive": [],
"parallelDo": "",
"events": {},
"changeFloor": {},
"afterBattle": {},
"afterGetItem": {},
"afterOpenDoor": {},
"cannotMove": {}
}
}
}

View File

@ -121,13 +121,6 @@
<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>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('enemyitem')">配置表格</button>
</h3>
<div class="leftTabContent">
<div id='newIdIdnum'><!-- id and idnum -->
<input placeholder="新id唯一标识符"/>
<input placeholder="新idnum10000以内数字"/>
<button>save</button>
<br/>
<button style="margin-top: 10px">自动注册</button>
</div>
<div id="enemyItemTable"><!-- enemy and item -->
<div class='etable'>
<table>
@ -141,6 +134,17 @@
</table>
</div>
</div>
<div id='newIdIdnum'><!-- id and idnum -->
<input placeholder="新id唯一标识符"/>
<input placeholder="新idnum10000以内数字"/>
<button>save</button>
<br/>
<button style="margin-top: 10px">自动注册</button>
</div>
<div id='changeId'><!-- id and idnum -->
<input placeholder="修改图块id为"/>
<button>save</button>
</div>
</div>
</div>
<div id="left4" class='leftTab' style="z-index:-1;opacity: 0;"><!-- floor -->
@ -158,6 +162,10 @@
</tbody>
</table>
</div>
<div id='changeFloorId'><!-- id and idnum -->
<input placeholder="修改floorId为"/>
<button>save</button>
</div>
</div>
</div>
<div id="left5" class='leftTab' style="z-index:-1;opacity: 0;"><!-- tower -->

View File

@ -117,6 +117,19 @@
<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>&nbsp;&nbsp;<button onclick="editor_multi.editCommentJs('enemyitem')">配置表格</button>
</h3>
<div class="leftTabContent">
<div id="enemyItemTable"><!-- enemy and item -->
<div class='etable'>
<table>
<tbody id='table_a3f03d4c_55b8_4ef6_b362_b345783acd72'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
<div id='newIdIdnum'><!-- id and idnum -->
<input placeholder="新id唯一标识符"/>
<input placeholder="新idnum10000以内数字"/>
@ -124,18 +137,9 @@
<br/>
<button style="margin-top: 10px">自动注册</button>
</div>
<div id="enemyItemTable"><!-- enemy and item -->
<div class='etable'>
<table>
<tbody id='table_a3f03d4c_55b8_4ef6_b362_b345783acd72'>
<tr>
<td>条目</td>
<td>注释</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<div id='changeId'><!-- id and idnum -->
<input placeholder="修改图块id为"/>
<button>save</button>
</div>
</div>
</div>
@ -154,6 +158,10 @@
</tbody>
</table>
</div>
<div id='changeFloorId'><!-- id and idnum -->
<input placeholder="修改floorId为"/>
<button>save</button>
</div>
</div>
</div>
<div id="left5" class='leftTab' style="z-index:-1;opacity: 0;"><!-- tower -->

View File

@ -162,19 +162,21 @@ actions.prototype._sys_onkeyUp_replay = function (e) {
core.triggerReplay();
else if (e.keyCode == 65) // A
core.rewindReplay();
else if (e.keyCode == 83)
else if (e.keyCode == 83) // S
core.saveReplay();
else if (e.keyCode == 67)
else if (e.keyCode == 67) // C
core.bookReplay();
else if (e.keyCode == 33 || e.keyCode == 34)
else if (e.keyCode == 33 || e.keyCode == 34) // PgUp/PgDn
core.viewMapReplay();
else if (e.keyCode >= 49 && e.keyCode <= 51)
else if (e.keyCode == 78) // N
core.stepReplay();
else if (e.keyCode >= 49 && e.keyCode <= 51) // 1-3
core.setReplaySpeed(e.keyCode - 48);
else if (e.keyCode == 52)
else if (e.keyCode == 52) // 4
core.setReplaySpeed(6);
else if (e.keyCode == 53)
else if (e.keyCode == 53) // 5
core.setReplaySpeed(12);
else if (e.keyCode == 54)
else if (e.keyCode == 54) // 6
core.setReplaySpeed(24);
return true;
}
@ -249,6 +251,8 @@ actions.prototype._sys_keyDown_lockControl = function (keyCode) {
this._keyDownSL(keyCode);
break;
case 'shop':
this._keyDownShop(keyCode);
break;
case 'selectShop':
case 'switchs':
case 'settings':
@ -758,13 +762,17 @@ actions.prototype._sys_longClick_lockControl = function (x, y) {
return true;
}
}
// 长按SL快速翻页
// 长按SL上下页快速翻页
if (["save","load","replayLoad","replayRemain"].indexOf(core.status.event.id) >= 0) {
if ([this.HSIZE-2, this.HSIZE-3, this.HSIZE+2, this.HSIZE+3].indexOf(x) >= 0 && y == this.LAST) {
this._clickSL(x, y);
return true;
}
}
// 长按商店连续购买
if (core.status.event.id == 'shop' && x >= this.CHOICES_LEFT && x <= this.CHOICES_RIGHT) {
return this._clickShop(x, y);
}
// 长按可以跳过等待事件
if (core.status.event.id == 'action' && core.status.event.data.type == 'sleep'
&& !core.status.event.data.current.noSkip) {
@ -916,7 +924,7 @@ actions.prototype._clickAction = function (x, y) {
core.insertAction(core.status.event.ui.yes);
core.doAction();
}
if ((x == this.HSIZE+2 || x == this.HSIZE+1) && y == this.HSIZE+1) {
else if ((x == this.HSIZE+2 || x == this.HSIZE+1) && y == this.HSIZE+1) {
core.status.route.push("choices:1");
core.insertAction(core.status.event.ui.no);
core.doAction();
@ -1243,13 +1251,25 @@ actions.prototype._clickShop = function (x, y) {
return true;
}
actions.prototype._keyDownShop = function (keycode) {
// 商店界面长按空格连续购买
if (keycode == 32) {
this._selectChoices(core.status.event.data.shop.choices.length + 1, keycode, this._clickShop);
return;
}
this._keyDownChoices(keycode);
}
////// 商店界面时,放开某个键的操作 //////
actions.prototype._keyUpShop = function (keycode) {
if (keycode == 27 || keycode == 88) {
core.events._exitShop();
return;
}
this._selectChoices(core.status.event.data.shop.choices.length + 1, keycode, this._clickShop);
if (keycode != 32) {
this._selectChoices(core.status.event.data.shop.choices.length + 1, keycode, this._clickShop);
return;
}
return;
}

View File

@ -189,7 +189,6 @@ control.prototype._animationFrame_animate = function (timestamp) {
control.prototype._animationFrame_heroMoving = function (timestamp) {
if (core.status.heroMoving <= 0) return;
var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'), direction = core.getHeroLoc('direction');
// 换腿
if (timestamp - core.animateFrame.moveTime > (core.values.moveSpeed||100)) {
core.animateFrame.leftLeg = !core.animateFrame.leftLeg;
@ -777,9 +776,9 @@ control.prototype.drawHero = function (status, offset) {
core.clearMap('hero');
this._drawHero_getDrawObjs(direction, x, y, status, offset).forEach(function (block) {
core.drawImage('hero', block.img, block.heroIcon[block.status]*32,
block.heroIcon.loc * block.height, 32, block.height,
block.posx, block.posy+32-block.height, 32, block.height);
core.drawImage('hero', block.img, block.heroIcon[block.status]*block.width,
block.heroIcon.loc * block.height, block.width, block.height,
block.posx+(32-block.width)/2, block.posy+32-block.height, block.width, block.height);
});
core.control.updateViewport();
@ -789,6 +788,7 @@ control.prototype._drawHero_getDrawObjs = function (direction, x, y, status, off
var heroIconArr = core.material.icons.hero, drawObjs = [], index = 0;
drawObjs.push({
"img": core.material.images.hero,
"width": core.material.icons.hero.width || 32,
"height": core.material.icons.hero.height,
"heroIcon": heroIconArr[direction],
"posx": x * 32 - core.bigmap.offsetX + core.utils.scan[direction].x * offset,
@ -799,6 +799,7 @@ control.prototype._drawHero_getDrawObjs = function (direction, x, y, status, off
(core.status.hero.followers||[]).forEach(function (t) {
drawObjs.push({
"img": core.material.images.images[t.name],
"width": core.material.images.images[t.name].width/4,
"height": core.material.images.images[t.name].height/4,
"heroIcon": heroIconArr[t.direction],
"posx": 32*t.x - core.bigmap.offsetX + (t.stop?0:core.utils.scan[t.direction].x*offset),
@ -1056,7 +1057,7 @@ control.prototype.chooseReplayFile = function () {
control.prototype.startReplay = function (list) {
if (!core.isPlaying()) return;
core.status.replay.replaying=true;
core.status.replay.pausing=false;
core.status.replay.pausing=true;
core.status.replay.speed=1.0;
core.status.replay.toReplay = core.clone(list);
core.status.replay.totalList = core.status.route.concat(list);
@ -1092,16 +1093,24 @@ control.prototype.resumeReplay = function () {
core.replay();
}
////// 单步播放 //////
control.prototype.stepReplay = function () {
if (!core.isPlaying() || !core.isReplaying()) return;
if (!core.status.replay.pausing) return core.drawTip("请先暂停录像");
if (core.isMoving() || core.status.replay.animate || core.status.event.id)
return core.drawTip("请等待当前事件的处理结束");
core.replay(true);
}
////// 加速播放 //////
control.prototype.speedUpReplay = function () {
if (!core.isPlaying() || !core.isReplaying()) return;
if (core.status.replay.speed==12) core.status.replay.speed=24;
else if (core.status.replay.speed==6) core.status.replay.speed=12;
else if (core.status.replay.speed==3) core.status.replay.speed=6;
else if (core.status.replay.speed==2.5) core.status.replay.speed=3;
else if (core.status.replay.speed==2) core.status.replay.speed=2.5;
else if (core.status.replay.speed<2) {
core.status.replay.speed = parseInt(10*core.status.replay.speed + 2)/10;
var speeds = [0.2, 0.5, 1, 2, 3, 6, 12, 24];
for (var i = speeds.length - 2; i >= 0; i--) {
if (speeds[i] <= core.status.replay.speed) {
core.status.replay.speed = speeds[i+1];
break;
}
}
core.drawTip("x"+core.status.replay.speed+"倍");
}
@ -1109,15 +1118,13 @@ control.prototype.speedUpReplay = function () {
////// 减速播放 //////
control.prototype.speedDownReplay = function () {
if (!core.isPlaying() || !core.isReplaying()) return;
if (core.status.replay.speed==24) core.status.replay.speed=12;
else if (core.status.replay.speed==12) core.status.replay.speed=6;
else if (core.status.replay.speed==6) core.status.replay.speed=3;
else if (core.status.replay.speed==3) core.status.replay.speed=2.5;
else if (core.status.replay.speed==2.5) core.status.replay.speed=2;
else {
core.status.replay.speed = parseInt(10*core.status.replay.speed - 2)/10;
var speeds = [0.2, 0.5, 1, 2, 3, 6, 12, 24];
for (var i = 1; i <= speeds.length; i++) {
if (speeds[i] >= core.status.replay.speed) {
core.status.replay.speed = speeds[i-1];
break;
}
}
if (core.status.replay.speed<0.2) core.status.replay.speed=0.2;
core.drawTip("x"+core.status.replay.speed+"倍");
}
@ -1218,9 +1225,10 @@ control.prototype.isReplaying = function () {
}
////// 回放 //////
control.prototype.replay = function () {
control.prototype.replay = function (force) {
if (!core.isPlaying() || !core.isReplaying()
|| core.status.replay.pausing || core.status.replay.animate || core.status.event.id) return;
|| core.status.replay.animate || core.status.event.id) return;
if (core.status.replay.pausing && !force) return;
if (core.status.replay.toReplay.length==0)
return this._replay_finished();
this._replay_save();
@ -1291,6 +1299,7 @@ control.prototype._replay_save = function () {
}
control.prototype._replay_error = function (action) {
core.ui.closePanel();
core.status.replay.replaying = false;
var len = core.status.replay.toReplay.length;
var prevList = core.status.replay.totalList.slice(-len - 11, -len - 1);
@ -1412,14 +1421,13 @@ control.prototype._replayAction_shop = function (action) {
return true;
}
var choices = shop.choices;
var topIndex = core.__HALF_SIZE__ - parseInt(choices.length / 2);
core.status.event.selection = parseInt(selections.shift());
core.events.openShop(shopId, false);
var topIndex = core.__HALF_SIZE__ - parseInt(choices.length / 2) + (core.status.event.ui.offset || 0);
var shopInterval = setInterval(function () {
if (!core.actions._clickShop(core.__HALF_SIZE__, topIndex+core.status.event.selection)) {
clearInterval(shopInterval);
core.stopReplay();
core.drawTip("录像文件出错");
core.control._replay_error(action);
return;
}
if (selections.length==0) {
@ -2065,6 +2073,7 @@ control.prototype.setCurtain = function(color, time, callback) {
}
control.prototype._setCurtain_animate = function (nowColor, color, time, callback) {
time /= Math.max(core.status.replay.speed, 1)
var per_time = 10, step = parseInt(time / per_time);
var animate = setInterval(function() {
nowColor = [
@ -2337,14 +2346,15 @@ control.prototype.updateHeroIcon = function (name) {
var image = core.material.images.hero;
// 全身图
var height = core.material.icons.hero.height;
var ratio = 32 / height, width = 32 * ratio, left = 16-width/2;
var w = core.material.icons.hero.width || 32;
var h = core.material.icons.hero.height || 48;
var ratio = Math.max(w / h, 1), width = 32 * ratio, left = 16 - width/2;
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
canvas.width = 32;
canvas.height = 32;
context.drawImage(image, 0, 0, 32, height, left, 0, width, 32);
context.drawImage(image, 0, 0, w, h, left, 0, width, 32);
core.statusBar.image.name.src = canvas.toDataURL("image/png");
}

View File

@ -241,6 +241,11 @@ enemys.prototype._nextCriticals_useBinarySearch = function (enemy, info, number,
enemys.prototype._nextCriticals_useTurn = function (enemy, info, number, x, y, floorId) {
var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, turn = info.turn;
// ------ 超大回合数强制使用二分算临界
// 以避免1攻10e回合2攻5e回合导致下述循环卡死问题
if (turn >= 1e6) { // 100w回合以上强制二分计算临界
return this._nextCriticals_useBinarySearch(enemy, info, number, x, y, floorId);
}
var list = [], pre = null;
for (var t = turn - 1; t >= 1; t--) {
var nextAtk = Math.ceil(mon_hp / t) + mon_def;

View File

@ -419,20 +419,23 @@ events.prototype._openDoor_animate = function (id, x, y, callback) {
var locked = core.status.lockControl;
core.lockControl();
core.status.replay.animate = true;
core.removeBlock(x, y);
core.drawImage('event', core.material.images.animates, 0, 32 * door, 32, 32, 32 * x, 32 * y, 32, 32);
var state = 0;
var animate = window.setInterval(function () {
core.clearMap('event', 32 * x, 32 * y, 32, 32);
state++;
if (state == 4) {
clearInterval(animate);
core.removeBlock(x, y);
delete core.animateFrame.asyncId[animate];
if (!locked) core.unLockControl();
core.status.replay.animate = false;
core.events.afterOpenDoor(id, x, y, callback);
return;
}
core.clearMap('event', 32 * x, 32 * y, 32, 32);
core.drawImage('event', core.material.images.animates, 32 * state, 32 * door, 32, 32, 32 * x, 32 * y, 32, 32);
}, speed / core.status.replay.speed);
}, speed / Math.max(core.status.replay.speed, 1));
core.animateFrame.asyncId[animate] = true;
}
////// 开一个门后触发的事件 //////
@ -840,7 +843,10 @@ events.prototype.insertAction = function (action, x, y, callback, addToLast) {
// ------ 判定commonEvent
var commonEvent = this.getCommonEvent(action);
if (commonEvent instanceof Array) action = commonEvent;
if (commonEvent instanceof Array) {
// 将公共事件视为一个do-while事件插入执行可被break跳出
action = [{"type": "dowhile", "condition": "false", "data": commonEvent}];
}
if (!action) return;
if (core.status.event.id != 'action') {
@ -1133,7 +1139,7 @@ events.prototype._action_openDoor = function (data, x, y, prefix) {
var loc = this.__action_getLoc(data.loc, x, y, prefix);
var floorId = data.floorId || core.status.floorId;
if (floorId == core.status.floorId) {
core.openDoor(loc[0], loc[1], data.needKey, core.doAction);
this.__action_doAsyncFunc(data.async, core.openDoor, loc[0], loc[1], data.needKey);
}
else {
core.removeBlock(loc[0], loc[1], floorId);
@ -1143,7 +1149,7 @@ events.prototype._action_openDoor = function (data, x, y, prefix) {
events.prototype._action_closeDoor = function (data, x, y, prefix) {
var loc = this.__action_getLoc(data.loc, x, y, prefix);
core.closeDoor(loc[0], loc[1], data.id, core.doAction);
this.__action_doAsyncFunc(data.async, core.closeDoor, loc[0], loc[1], data.id);
}
events.prototype._action_useItem = function (data, x, y, prefix) {
@ -1172,7 +1178,13 @@ events.prototype._action_disableShop = function (data, x, y, prefix) {
}
events.prototype._action_battle = function (data, x, y, prefix) {
this.battle(data.id, null, null, true, core.doAction);
if (data.id) {
this.battle(data.id, null, null, true, core.doAction);
}
else {
var loc = this.__action_getLoc(data.loc, x, y, prefix);
this.battle(null, loc[0], loc[1], true, core.doAction);
}
}
events.prototype._action_trigger = function (data, x, y, prefix) {
@ -1180,9 +1192,9 @@ events.prototype._action_trigger = function (data, x, y, prefix) {
var block = core.getBlock(loc[0], loc[1]);
if (block != null && block.block.event.trigger) {
block = block.block;
this.setEvents([], block.x, block.y);
this.setEvents(data.keep ? null : [], block.x, block.y);
if (block.event.trigger == 'action')
this.setEvents(block.event.data);
this.insertAction(block.event.data);
else {
core.doSystemEvent(block.event.trigger, block, core.doAction);
return;
@ -1327,10 +1339,8 @@ events.prototype.__action_getInput = function (hint, isText, callback) {
callback(value);
}
catch (e) {
main.log(e);
core.stopReplay();
core.insertAction(["录像文件出错,请在控制台查看报错信息。", {"type": "exit"}]);
core.doAction();
core.control._replay_error(action);
return;
}
}
else {
@ -1375,10 +1385,7 @@ events.prototype._action_choices = function (data, x, y, prefix) {
}, 750 / Math.max(1, core.status.replay.speed))
}
else {
main.log("录像文件出错!当前需要一个 choices: 项,实际为 " + action);
core.stopReplay();
core.insertAction(["录像文件出错,请在控制台查看报错信息。", {"type": "exit"}]);
core.doAction();
core.control._replay_error(action);
return;
}
}
@ -1401,10 +1408,7 @@ events.prototype._action_confirm = function (data, x, y, prefix) {
}, 750 / Math.max(1, core.status.replay.speed))
}
else {
main.log("录像文件出错!当前需要一个 choices: 项,实际为 " + action);
core.stopReplay();
core.insertAction(["录像文件出错,请在控制台查看报错信息。", {"type": "exit"}]);
core.doAction();
core.control._replay_error(action);
return;
}
}
@ -1749,8 +1753,7 @@ events.prototype.hasAsync = function () {
events.prototype.follow = function (name) {
core.status.hero.followers = core.status.hero.followers || [];
name = core.getMappedName(name);
if (core.material.images.images[name]
&& core.material.images.images[name].width == 128) {
if (core.material.images.images[name]) {
core.status.hero.followers.push({"name": name});
core.gatherFollowers();
core.clearMap('hero');
@ -1786,6 +1789,7 @@ events.prototype.setValue = function (name, value, prefix, add) {
this._setValue_setItem(name, value);
this._setValue_setFlag(name, value);
this._setValue_setSwitch(name, value, prefix);
this._setValue_setGlobal(name, value);
core.updateStatusBar();
}
@ -1816,6 +1820,11 @@ events.prototype._setValue_setSwitch = function (name, value, prefix) {
core.setFlag((prefix || ":f@x@y") + "@" + name.substring(7), value);
}
events.prototype._setValue_setGlobal = function (name, value) {
if (name.indexOf("global:") !== 0) return;
core.setGlobal(name.substring(7), value);
}
////// 数值增减 //////
events.prototype.addValue = function (name, value, prefix) {
this.setValue(name, value, prefix, true);
@ -1884,7 +1893,7 @@ events.prototype.closeDoor = function (x, y, id, callback) {
}
core.clearMap('event', 32 * x, 32 * y, 32, 32);
core.drawImage('event', core.material.images.animates, 32 * (4-state), 32 * door, 32, 32, 32 * x, 32 * y, 32, 32);
}, speed / core.status.replay.speed);
}, speed / Math.max(core.status.replay.speed, 1));
core.animateFrame.asyncId[animate] = true;
}
@ -1958,7 +1967,8 @@ events.prototype.moveImage = function (code, to, opacityVal, time, callback) {
var opacity = parseFloat(canvas.style.opacity), toOpacity = getOrDefault(opacityVal, opacity);
this._moveImage_moving(name, {
fromX: fromX, fromY: fromY, toX: toX, toY: toY, opacity: opacity, toOpacity: toOpacity, time: time
fromX: fromX, fromY: fromY, toX: toX, toY: toY, opacity: opacity, toOpacity: toOpacity,
time: time / Math.max(core.status.replay.speed, 1)
}, callback)
}
@ -2016,6 +2026,7 @@ events.prototype.setVolume = function (value, time, callback) {
return;
}
var currVolume = core.musicStatus.volume;
time /= Math.max(core.status.replay.speed, 1);
var per_time = 10, step = 0, steps = parseInt(time / per_time);
var fade = setInterval(function () {
step++;
@ -2037,6 +2048,7 @@ events.prototype.vibrate = function (time, callback) {
}
if (!time || time < 1000) time = 1000;
// --- 将time调整为500的倍数上整不然会出错
time /= Math.max(core.status.replay.speed, 1)
time = Math.ceil(time / 500) * 500;
var shakeInfo = {duration: time * 3 / 50, speed: 5, power: 5, direction: 1, shake: 0};
var animate = setInterval(function () {
@ -2127,6 +2139,7 @@ events.prototype.jumpHero = function (ex, ey, time, callback) {
core.playSound('jump.mp3');
var jumpInfo = core.maps.__generateJumpInfo(sx, sy, ex, ey, time || 500);
jumpInfo.icon = core.material.icons.hero[core.getHeroLoc('direction')];
jumpInfo.width = core.material.icons.hero.width || 32;
jumpInfo.height = core.material.icons.hero.height;
this._jumpHero_doJump(jumpInfo, callback);
@ -2146,12 +2159,12 @@ events.prototype._jumpHero_doJump = function (jumpInfo, callback) {
events.prototype._jumpHero_jumping = function (jumpInfo) {
core.clearMap('hero');
core.maps.__updateJumpInfo(jumpInfo);
var nowx = jumpInfo.px, nowy = jumpInfo.py, height = jumpInfo.height;
var nowx = jumpInfo.px, nowy = jumpInfo.py, width = jumpInfo.width || 32, height = jumpInfo.height;
core.bigmap.offsetX = core.clamp(nowx - 32*core.__HALF_SIZE__, 0, 32*core.bigmap.width-core.__PIXELS__);
core.bigmap.offsetY = core.clamp(nowy - 32*core.__HALF_SIZE__, 0, 32*core.bigmap.height-core.__PIXELS__);
core.control.updateViewport();
core.drawImage('hero', core.material.images.hero, jumpInfo.icon.stop, jumpInfo.icon.loc * height, 32, height,
nowx - core.bigmap.offsetX, nowy + 32-height - core.bigmap.offsetY, 32, height);
core.drawImage('hero', core.material.images.hero, jumpInfo.icon.stop, jumpInfo.icon.loc * height, width, height,
nowx + (32 - width) / 2 - core.bigmap.offsetX, nowy + 32-height - core.bigmap.offsetY, width, height);
}
events.prototype._jumpHero_finished = function (animate, ex, ey, callback) {
@ -2239,14 +2252,13 @@ events.prototype.canUseQuickShop = function (shopId) {
events.prototype.setHeroIcon = function (name, noDraw) {
name = core.getMappedName(name);
var img = core.material.images.images[name];
if (!img || img.width != 128) return;
if (!img) return;
core.setFlag("heroIcon", name);
core.material.images.hero.onload = function () {
core.material.icons.hero.height = img.height / 4;
core.control.updateHeroIcon(name);
if (!noDraw) core.drawHero();
}
core.material.images.hero.src = img.src;
core.material.images.hero = img;
core.material.icons.hero.width = img.width / 4;
core.material.icons.hero.height = img.height / 4;
core.control.updateHeroIcon(name);
if (!noDraw) core.drawHero();
}
////// 检查升级事件 //////

View File

@ -11,9 +11,9 @@ items.prototype._init = function () {
this.itemEffectTip = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.itemEffectTip;
this.useItemEffect = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.useItemEffect;
this.canUseItemEffect = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canUseItemEffect;
if (!items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip)
items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip = {};
this.equipCondition = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.canEquip;
if (!items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.equipCondition)
items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.equipCondition = {};
this.equipCondition = items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a.equipCondition;
}
////// 获得所有道具 //////
@ -35,7 +35,7 @@ items.prototype._resetItems = function () {
if (core.flags.bombFourDirections)
core.material.items.bomb.text = "可以炸掉勇士四周的怪物";
if (core.flags.snowFourDirections)
core.material.items.bomb.text = "可以将四周的熔岩变成平地";
core.material.items.snow.text = "可以将四周的熔岩变成平地";
if (core.flags.equipment) {
core.material.items.sword1.cls = 'equips';
core.material.items.sword2.cls = 'equips';

View File

@ -91,6 +91,9 @@ maps.prototype.initBlock = function (x, y, id, addInfo, eventFloor) {
else if (core.icons.getTilesetOffset(id)) block.event = {"cls": "tileset", "id": "X" + id, "noPass": true};
else block.event = {'cls': 'terrains', 'id': 'none', 'noPass': false};
if (typeof block.event.noPass === 'string')
block.event.noPass = JSON.parse(block.event.noPass);
if (addInfo) this._addInfo(block);
if (eventFloor) {
this._addEvent(block, x, y, (eventFloor.events || {})[x + "," + y]);
@ -238,7 +241,8 @@ maps.prototype.saveMap = function (floorId) {
if (!floorId) {
var map = {};
for (var id in maps) {
map[id] = this.saveMap(id);
var obj = this.saveMap(id);
if (Object.keys(obj).length > 0) map[id] = obj;
}
return map;
}
@ -1446,8 +1450,13 @@ maps.prototype.setBlock = function (number, x, y, floorId) {
else number = core.getNumberById(number);
}
var originBlock = core.getBlock(x, y, floorId, true);
var block = this.initBlock(x, y, number, true, core.floors[floorId]);
if (block.id == 0 && !block.event.trigger) {
// 转变图块为0且该点无事件视为隐藏
core.removeBlock(x, y, floorId);
return;
}
var originBlock = core.getBlock(x, y, floorId, true);
if (floorId == core.status.floorId) {
core.removeGlobalAnimate(x, y);
core.clearMap('event', x * 32, y * 32, 32, 32);
@ -1614,13 +1623,13 @@ maps.prototype.moveBlock = function (x, y, steps, time, keep, callback) {
}
var block = blockArr[0], blockInfo = blockArr[1];
var moveSteps = (steps||[]).filter(function (t) {
return ['up','down','left','right'].indexOf(t)>=0;
return ['up','down','left','right','forward','backward'].indexOf(t)>=0;
});
var canvases = this._initDetachedBlock(blockInfo, x, y, block.event.animate !== false);
this._moveDetachedBlock(blockInfo, 32 * x, 32 * y, 1, canvases);
var moveInfo = {
x: x, y: y, px: 32 * x, py: 32 * y, opacity: 1, keep: keep,
x: x, y: y, px: 32 * x, py: 32 * y, opacity: 1, keep: keep, lastDirection: null, offset: 1,
moveSteps: moveSteps, step: 0, per_time: time / 16 / core.status.replay.speed
}
this._moveBlock_doMove(blockInfo, canvases, moveInfo, callback);
@ -1645,21 +1654,46 @@ maps.prototype._moveBlock_doMove = function (blockInfo, canvases, moveInfo, call
core.animateFrame.asyncId[animate] = true;
}
maps.prototype._moveBlock_moving = function (blockInfo, canvases, moveInfo) {
maps.prototype._moveBlock_updateDirection = function (blockInfo, moveInfo) {
moveInfo.offset = 1;
var direction = moveInfo.moveSteps[0];
if (moveInfo.step == 0) {
moveInfo.x += core.utils.scan[direction].x;
moveInfo.y += core.utils.scan[direction].y;
// 根据faceIds修改朝向
var currid = blockInfo.faceIds[direction];
if (currid) {
var posY = core.material.icons[blockInfo.cls][currid];
if (posY != null) blockInfo.posY = posY;
if (moveInfo.lastDirection == null) {
for (var d in blockInfo.faceIds) {
if (blockInfo.faceIds[d] == blockInfo.id) {
moveInfo.lastDirection = d;
break;
}
}
}
if (direction == 'forward' || direction == 'backward') {
if (moveInfo.lastDirection == null) {
moveInfo.moveSteps.shift();
return false;
}
if (direction == 'backward')
moveInfo.offset = -1;
direction = moveInfo.lastDirection;
}
moveInfo.lastDirection = moveInfo.moveSteps[0] = direction;
moveInfo.x += core.utils.scan[direction].x * moveInfo.offset;
moveInfo.y += core.utils.scan[direction].y * moveInfo.offset;
// 根据faceIds修改朝向
var currid = blockInfo.faceIds[direction];
if (currid) {
var posY = core.material.icons[blockInfo.cls][currid];
if (posY != null) blockInfo.posY = posY;
}
return true;
}
maps.prototype._moveBlock_moving = function (blockInfo, canvases, moveInfo) {
if (moveInfo.step == 0) {
if (!this._moveBlock_updateDirection(blockInfo, moveInfo)) return;
}
var direction = moveInfo.moveSteps[0];
moveInfo.step++;
moveInfo.px += core.utils.scan[direction].x * 2;
moveInfo.py += core.utils.scan[direction].y * 2;
moveInfo.px += core.utils.scan[direction].x * 2 * moveInfo.offset;
moveInfo.py += core.utils.scan[direction].y * 2 * moveInfo.offset;
this._moveDetachedBlock(blockInfo, moveInfo.px, moveInfo.py, moveInfo.opacity, canvases);
if (moveInfo.step == 16) {
moveInfo.step = 0;
@ -1688,6 +1722,7 @@ maps.prototype.jumpBlock = function (sx, sy, ex, ey, time, keep, callback) {
maps.prototype.__generateJumpInfo = function (sx, sy, ex, ey, time) {
var dx = ex - sx, dy = ey - sy, distance = Math.round(Math.sqrt(dx * dx + dy * dy));
var jump_peak = 6 + distance, jump_count = jump_peak * 2;
time /= Math.max(core.status.replay.speed, 1)
return {
x: sx, y: sy, ex: ex, ey: ey, px: 32 * sx, py: 32 * sy, opacity: 1,
jump_peak: jump_peak, jump_count: jump_count,
@ -1751,6 +1786,7 @@ maps.prototype.animateBlock = function (loc, type, time, callback) {
return;
}
this._animateBlock_drawList(list, isHide ? 1 : 0);
time /= Math.max(core.status.replay.speed, 1)
this._animateBlock_doAnimate(loc, list, isHide, 10 / time, callback);
}

View File

@ -373,7 +373,8 @@ ui.prototype._getTitleAndIcon = function (content) {
title = core.status.hero.name;
image = core.material.images.hero;
icon = 0;
height = core.material.icons.hero.height;
var w = core.material.icons.hero.width || 32;
height = 32 * core.material.icons.hero.height / w;
}
else if (s4.endsWith(".png")) {
s4 = core.getMappedName(s4);
@ -383,7 +384,6 @@ ui.prototype._getTitleAndIcon = function (content) {
var blockInfo = core.getBlockInfo(s4);
if (blockInfo != null) {
if (core.material.enemys[s4]) title = core.material.enemys[s4].name;
else title = s4;
image = blockInfo.image;
icon = blockInfo.posY;
height = blockInfo.height;
@ -467,6 +467,11 @@ ui.prototype.drawWindowSelector = function(background, x, y, w, h) {
////// 绘制 WindowSkin
ui.prototype.drawWindowSkin = function(background, ctx, x, y, w, h, direction, px, py) {
background = background || core.status.textAttribute.background;
if (typeof background == 'string') {
background = core.getMappedName(background);
background = core.material.images.images[background];
}
// 仿RM窗口皮肤 ↓
var dstImage = core.getContextByName(ctx);
if (!dstImage) return;
@ -874,8 +879,10 @@ ui.prototype._drawTextBox_getVerticalPosition = function (content, titleInfo, po
var realContent = this._getRealContent(content);
var height = 30 + lineHeight * core.splitLines("ui", realContent, validWidth, this._buildFont()).length;
if (titleInfo.title) height += textAttribute.titlefont + 5;
if (titleInfo.icon != null)
height = Math.max(height, titleInfo.height+50);
if (titleInfo.icon != null) {
if (titleInfo.title) height = Math.max(height, titleInfo.height+50);
else height = Math.max(height, titleInfo.height + 30);
}
else if (titleInfo.image)
height = Math.max(height, 90);
@ -904,9 +911,11 @@ ui.prototype._drawTextBox_drawTitleAndIcon = function (titleInfo, hPos, vPos, al
core.setTextAlign('ui', 'left');
var textAttribute = core.status.textAttribute;
var content_top = vPos.top + 15;
var image_top = vPos.top + 15;
if (titleInfo.title != null) {
var titlefont = textAttribute.titlefont;
content_top += titlefont + 5;
image_top = vPos.top + 40;
core.setFillStyle('ui', core.arrayToRGB(textAttribute.title));
core.setStrokeStyle('ui', core.arrayToRGB(textAttribute.title));
@ -919,19 +928,27 @@ ui.prototype._drawTextBox_drawTitleAndIcon = function (titleInfo, hPos, vPos, al
title_left = hPos.right - title_width - 12;
core.fillText('ui', titleInfo.title, title_left, vPos.top + 8 + titlefont);
if (titleInfo.icon != null) {
core.setAlpha('ui', alpha);
core.strokeRect('ui', hPos.left + 15 - 1, vPos.top + 40-1, 34, titleInfo.height + 2, null, 2);
core.setAlpha('ui', 1);
core.status.boxAnimateObjs = [];
}
if (titleInfo.icon != null) {
core.setAlpha('ui', alpha);
core.strokeRect('ui', hPos.left + 15 - 1, image_top-1, 34, titleInfo.height + 2, null, 2);
core.setAlpha('ui', 1);
core.status.boxAnimateObjs = [];
// --- 勇士
if (titleInfo.image == core.material.images.hero) {
core.clearMap('ui', hPos.left + 15, image_top, 32, titleInfo.height);
core.fillRect('ui', hPos.left + 15, image_top, 32, titleInfo.height, core.material.groundPattern);
core.drawImage('ui', titleInfo.image, 0, 0, core.material.icons.hero.width || 32, core.material.icons.hero.height,
hPos.left + 15, image_top, 32, titleInfo.height);
}
else {
core.status.boxAnimateObjs.push({
'bgx': hPos.left + 15, 'bgy': vPos.top + 40, 'bgWidth': 32, 'bgHeight': titleInfo.height,
'x': hPos.left + 15, 'y': vPos.top + 40, 'height': titleInfo.height, 'animate': titleInfo.animate,
'bgx': hPos.left + 15, 'bgy': image_top, 'bgWidth': 32, 'bgHeight': titleInfo.height,
'x': hPos.left + 15, 'y': image_top, 'height': titleInfo.height, 'animate': titleInfo.animate,
'image': titleInfo.image, 'pos': titleInfo.icon * titleInfo.height
});
core.drawBoxAnimate();
}
core.drawBoxAnimate();
}
if (titleInfo.image != null && titleInfo.icon == null) { // 头像图
core.drawImage('ui', titleInfo.image, 0, 0, titleInfo.image.width, titleInfo.image.height,
@ -969,6 +986,7 @@ ui.prototype.drawScrollText = function (content, time, lineHeight, callback) {
ui.prototype._drawScrollText_animate = function (ctx, time, callback) {
// 开始绘制到UI上
time /= Math.max(core.status.replay.speed, 1)
var per_pixel = 1, height = ctx.canvas.height, per_time = time * per_pixel / (this.PIXEL+height);
var currH = this.PIXEL;
core.drawImage('ui', ctx.canvas, 0, currH);

View File

@ -67,6 +67,7 @@ utils.prototype.calValue = function (value, prefix, need, times) {
value = value.replace(/item:([a-zA-Z0-9_]+)/g, "core.itemCount('$1')");
value = value.replace(/flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getFlag('$1', 0)");
value = value.replace(/switch:([a-zA-Z0-9_]+)/g, "core.getFlag('" + (prefix || ":f@x@y") + "@$1', 0)");
value = value.replace(/global:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, "core.getGlobal('$1', 0)");
return eval(value);
}
if (value instanceof Function) {
@ -246,6 +247,31 @@ utils.prototype.removeLocalForage = function (key, successCallback, errorCallbac
})
}
utils.prototype.setGlobal = function (key, value) {
if (core.isReplaying()) return;
core.setLocalStorage(key, value);
}
utils.prototype.getGlobal = function (key, defaultValue) {
var value;
if (core.isReplaying()) {
// 不考虑key不一致的情况
var action = core.status.replay.toReplay.shift();
if (action.indexOf("input2:") == 0) {
value = JSON.parse(core.decodeBase64(action.substring(7)));
}
else {
core.control._replay_error(action);
return core.getLocalStorage(key, defaultValue);
}
}
else {
value = core.getLocalStorage(key, defaultValue);
}
core.status.route.push("input2:" + core.encodeBase64(JSON.stringify(value)));
return value;
}
////// 深拷贝一个对象 //////
utils.prototype.clone = function (data, filter, recursion) {
if (!core.isset(data)) return null;
@ -686,9 +712,8 @@ utils.prototype.rand2 = function (num) {
value = parseInt(action.substring(7));
}
else {
core.stopReplay();
core.drawTip("录像文件出错");
return;
core.control._replay_error(action);
return 0;
}
}
else {

View File

@ -2,7 +2,7 @@ function main() {
//------------------------ 用户修改内容 ------------------------//
this.version = "2.6"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.version = "2.6.1"; // 游戏版本号如果更改了游戏内容建议修改此version以免造成缓存问题。
this.useCompress = false; // 是否使用压缩文件
// 当你即将发布你的塔时请使用“JS代码压缩工具”将所有js代码进行压缩然后将这里的useCompress改为true。
@ -188,8 +188,8 @@ function main() {
this.floors = {}
this.canvas = {};
this.__VERSION__ = "2.6";
this.__VERSION_CODE__ = 30;
this.__VERSION__ = "2.6.1";
this.__VERSION_CODE__ = 36;
}
main.prototype.init = function (mode, callback) {

View File

@ -77,7 +77,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
"firstData": {
"title": "魔塔样板",
"name": "template",
"version": "Ver 2.6",
"version": "Ver 2.6.1",
"floorId": "sample0",
"hero": {
"name": "阳光",

View File

@ -465,7 +465,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
[12, "中毒", "战斗后,勇士陷入中毒状态,每一步损失生命" + core.values.poisonDamage + "点"],
[13, "衰弱", "战斗后,勇士陷入衰弱状态,攻防暂时下降" + (core.values.weakValue >= 1 ? core.values.weakValue + "点" : parseInt(core.values.weakValue * 100) + "%")],
[14, "诅咒", "战斗后,勇士陷入诅咒状态,战斗无法获得金币和经验"],
[15, "领域", function (enemy) { return "经过怪物周围" + (enemy.range || 1) + "格时自动减生命" + (enemy.value || 0) + "点"; }],
[15, "领域", function (enemy) { return "经过怪物周围" + (enemy.zoneSquare ? "九宫格" : "十字") + "范围内" + (enemy.range || 1) + "格时自动减生命" + (enemy.value || 0) + "点"; }],
[16, "夹击", "经过两只相同的怪物中间,勇士生命值变成一半"],
[17, "仇恨", "战斗前,怪物附加之前积累的仇恨值作为伤害" + (core.flags.hatredDecrease ? ";战斗后,释放一半的仇恨值" : "") + "。(每杀死一个怪物获得" + (core.values.hatred || 0) + "点仇恨值)"],
[18, "阻击", function (enemy) { return "经过怪物的十字领域时自动减生命" + (enemy.value || 0) + "点,同时怪物后退一格"; }],
@ -973,6 +973,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
icon = core.getMappedName(icon);
if (core.material.images.images[icon]) {
core.material.images.hero.src = core.material.images.images[icon].src;
core.material.icons.hero.width = core.material.images.images[icon].width / 4;
core.material.icons.hero.height = core.material.images.images[icon].height / 4;
}
// 刷新怪物数据

View File

@ -25,6 +25,7 @@ var icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 =
"leftFoot": 1,
"rightFoot": 3
},
"width": 32,
"height": 48
},
"terrains": {

View File

@ -416,5 +416,5 @@ var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a =
"yellowJewel": "true",
"skill1": "true"
},
"canEquip": {}
"equipCondition": {}
}

View File

@ -1,4 +1,25 @@
HTML5魔塔样板V2.6
HTML5魔塔样板V2.6.1
区域优化的录像播放功能R键使用
强制战斗可以指定怪物坐标,将自动隐藏并执行该点战后事件
flag:xxx也支持中文例如 flag:2楼机关门
增加文件名映射可以用中文映射到某个图片或bgm文件并使用
勇士宽度可以超过32例如48x48的勇士行走图
现在允许修改floorId和图块ID了在表格下方
增加事件:自动存档,返回标题界面;部分事件优化
商店长按空格可以连续加点
增设global:xxx使用全局存储可被录像支持
支持\b[hero]和\b[null,x,y]来自动调整上下方向
支持\t[yellowKey]等只显示图标而没有标题
编辑器中前景层对于有事件的点半透明显示
存档改成1000页长按上下页可快速翻页
录像播放初始默认暂停N键可以单步执行
增设本地API文档部分API和事件的优化
所有已知的bug修复大量细节优化
-----------------------------------------------------------------------
HTML5魔塔样板V2.6
拆分整个项目大幅重构代码新增大量API
重写文档尤其是脚本和API列表