Merge remote-tracking branch 'refs/remotes/ckcz123/master'
This commit is contained in:
commit
922ba10c82
29
README.md
29
README.md
@ -16,6 +16,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏!
|
||||
``` bash
|
||||
├── /_server/ # 为可视化地图编辑器提供一些支持的目录
|
||||
├── /docs/ # 文档目录
|
||||
├── /animates/ # 动画目录
|
||||
├── /images/ # 所有图片素材目录
|
||||
│ ├─ /常用素材/ # 可以被直接替换的素材
|
||||
│ └─ *.png # 对应的某个具体的图片素材
|
||||
@ -32,6 +33,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏!
|
||||
│ └─ ui.js # UI绘制信息,主要负责绘制各个UI窗口。
|
||||
├── /sounds/ # 音效目录
|
||||
├── /常用工具/ # 一些常用工具,可以辅助造塔
|
||||
│ ├─ RM动画导出器.exe # 能从RMXP中导出动画,以供H5使用。 http://github.com/ckcz123/animate_export/
|
||||
│ ├─ JS代码压缩工具.exe # 能对Javascript代码进行压缩和整合,从而减少IO请求量。 http://github.com/ckcz123/JSCompressor/
|
||||
│ ├─ 便捷PS工具.exe # 能只用复制和粘贴来快速对素材进行PS操作。 http://github.com/ckcz123/ps/
|
||||
│ ├─ 地图生成器.exe # 能从一张截图识别出来具体的数字数组,方便复刻已有的塔。 http://github.com/ckcz123/map_generator/
|
||||
@ -45,6 +47,33 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏!
|
||||
|
||||
## 更新说明
|
||||
|
||||
### 2018.2.9 V1.4.1
|
||||
|
||||
* [x] 改变图块(setBlock事件)。
|
||||
* [x] 同一个点的多事件处理(做法详见文档)。
|
||||
* [x] 地图中每个块的可通行方向控制(悬崖效果)。
|
||||
* [x] 动画支持带旋转和翻转的帧。
|
||||
* [x] 现在可以允许用户丢弃道具了(例如不会再使用的装备)。
|
||||
* [x] 修复行走时按键会发生动画抖动问题。
|
||||
* [x] 修复无法打开战斗动画的Bug。
|
||||
|
||||
### 2018.2.6 V1.4
|
||||
|
||||
* [x] 支持动画。
|
||||
* [x] 瞬间移动。
|
||||
* [x] 支持天气系统,可以在剧本中设置默认天气。
|
||||
* [x] 新增自定义事件-图片显示。
|
||||
* [x] 同时可以在剧本中设定多个背景素材。
|
||||
* [x] 剧情文本特性控制,人物的对话框效果。
|
||||
* [x] 单存档同步到服务器,下载到文件和读取。
|
||||
* [x] 键盘支持自动寻路操作。
|
||||
* [x] 浏览地图模式下可以查看怪物数据。
|
||||
* [x] 未成功打怪和开门则不自动存档。
|
||||
* [x] 重新支持楼梯穿透。
|
||||
* [x] 支持多结局,成绩将分开统计。
|
||||
* [x] 重构全局动画、行走动画和行走检测,大幅提升性能。
|
||||
* [x] 修复所有已知Bug。
|
||||
|
||||
### 2018.1.21 V1.3.2
|
||||
|
||||
* [x] 增加录像和回放功能。
|
||||
|
||||
1
animates/hand.animate
Normal file
1
animates/hand.animate
Normal file
File diff suppressed because one or more lines are too long
1
animates/jianji.animate
Normal file
1
animates/jianji.animate
Normal file
File diff suppressed because one or more lines are too long
1
animates/sword.animate
Normal file
1
animates/sword.animate
Normal file
@ -0,0 +1 @@
|
||||
{"ratio":2,"bitmaps":["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAD6SURBVHhe7dQ9SsVAFAXg+MNTeAhaWCrWLsHGUlCwsHMXgo2NjZ31a1yBVtaCrSvQ1i24hSSegbuEBAS/Dw7M3JnqZEgHAAAAAAAAAAAAAP/NOI5rySI5GobhNDlJ9uuYqaXo9RR83Pf9U/KevGV/kxwkW+2D1FWmkmKXKfYuZf8k38lrZpeZHSaLusaU2ktOyRcp+zP5Sl6yv858t53VNaaWcrdT9mPSXvpHskrxO3XMnNpvJYW3F/+Q9XmNmVv7raT055R+n/VejZlbyt5M6VfJbdYbNWZureyUvkzOagQAAAAAAAAAAAAAAAAAAAAAAAAAAADwd3XdL135q9NaPZ6+AAAAAElFTkSuQmCC","data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJ4SURBVHhe7de7alRRFMbx3DSIgqiNIBJsBUUESyutBAsLO9/CWtL4BtorlgFBRGIEEQwxMSBiMWouGo2TCyaTC0lmJjM5ey+/HVfeYPZB8P+DNefsS/WdxZ5zugAAAAAAAAAAAAAAAAAAAID/lZkdVnX7ELmkkA+C1rU3xngthHBf1xsa9+1vQmcdhK7qUdAXFPh4URSjur+r6vdt6DQP/ZDqkkL/ZlZs6jqh8WnfghzU1UcOQlclmop3fBk5KPA+hXxRYb9LiWtsujR0Oe5b0Gke+hUF/TaFLtHrh29BDgr9jEJOoReqeur2RPfTvgWdpnzTG8yAQm6oYgq8uWfWLvaD1y+vkNko3G6FPJ9CT7ZbZpVVs9m1/Ydw3bchB3X9+dTxqVLwk4tmH1T1VnjlW5CDGj11/XDq+HTgfFwye/rVbKpmNjzDx1N2Cn8jhb+qF8mRObOX381m1sPww4od8y3IQZn3KPzdogjNyorZ8xmzaXX9cjOe8y3IxcNvNtq2OV41ezFrttYMv30ZOSn8dOavqBrjC3+PnfVGvOfLyE0P4HH6qhr9Zfbmp7p/Lg74EnJT+LdbeyGk4F/PhfhgMp7yJeSm9/yTavza2HyIYwuhPTRkvb6E3NT5fQr/2cRS2HhfDfVB/Qn7EnJLf7rq/pvTq6H9uRa2fBplSOGrTixvhdrUWqj7NMqi8HsV/shsLez5FMq004qXq+th14cok879/upO+FKp2GGfQll09PSsNOLVxXq85VMoUzr7F7fDIx+iTOnNR8fP2UGOnvKl8NPx8+RTPOpTKFt6CH4LAAAAAAAAAAAAAAAAAAAAAAAAAACAf1RX1x9x4x3SPdhnTAAAAABJRU5ErkJggg==","","","","","","","","","","","","","","","","","",""],"frame_max":5,"frames":[[[0,8,32,30,100]],[[0,-16,32,50,130]],[[0,-24,40,80,150]],[[0,-48,24,90,180],[1,-8,40,100,255]],[[0,-56,24,100,200],[1,-8,24,100,255]]]}
|
||||
1
animates/thunder.animate
Normal file
1
animates/thunder.animate
Normal file
File diff suppressed because one or more lines are too long
1
animates/yongchang.animate
Normal file
1
animates/yongchang.animate
Normal file
File diff suppressed because one or more lines are too long
1
animates/zone.animate
Normal file
1
animates/zone.animate
Normal file
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
# 附录:API列表
|
||||
|
||||
?> 上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
所有系统支持的API都列在了这里。所有可能被用到的API都在前面用\*标记。
|
||||
|
||||
@ -148,7 +148,6 @@ core.addGlobalAnimate // 添加一个全局动画
|
||||
core.removeGlobalAnimate // 删除一个或所有全局动画
|
||||
core.setGlobalAnimate // 设置全局动画的显示效果
|
||||
core.syncGlobalAnimate // 同步所有的全局动画效果
|
||||
core.setBoxAnimate // 显示UI层某个box的动画(如怪物手册中怪物的动画)
|
||||
core.drawBoxAnimate // 绘制UI层的box动画
|
||||
core.updateCheckBlock // 更新领域、夹击、阻击的伤害地图
|
||||
core.checkBlock // 检查并执行领域、夹击、阻击事件
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 元件说明
|
||||
|
||||
?> 上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。
|
||||
|
||||
@ -149,6 +149,42 @@ floorId指定的是目标楼层的唯一标识符(ID)。
|
||||
|
||||
可以指定time,指定后切换动画时长为指定的数值。
|
||||
|
||||
## 动画和天气系统
|
||||
|
||||
现在我们的H5魔塔支持播放动画,也支持天气系统了。
|
||||
|
||||
要播放动画,你需要先使用“RM动画导出器”将动画导出,放在animates目录下,然后在main.js中定义。
|
||||
|
||||
``` js
|
||||
this.animates = [// 在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名
|
||||
// 动画必须放在animates目录下;文件名不能使用中文,不能带空格或特殊字符
|
||||
"hand", "sword", "zone", "yongchang", "thunder" // 根据需求自行添加
|
||||
]
|
||||
```
|
||||
|
||||
!> 动画必须是animate格式,名称不能使用中文,不能带空格或特殊字符。
|
||||
|
||||
目前暂时不支持带旋转和翻转的帧。
|
||||
|
||||
导出动画时可能会进行一些压缩以节省流量,因此清晰度可能不如原版。
|
||||
|
||||
动画播放时,是按照每秒20帧的速度(即50ms/帧)。
|
||||
|
||||
定义完毕后,我们可以调用`animate`事件来播放该动画,有关事件的详细介绍请参见[事件](event)。
|
||||
|
||||
!> 播放录像时,将默认忽略所有动画。
|
||||
|
||||
目前天气系统只支持雨和雪两种天气。
|
||||
|
||||
在每层楼的剧本文件里存在一个weather选项,表示该层楼的默认天气。
|
||||
|
||||
``` js
|
||||
// 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪,第二项为1-10之间的数代表强度。
|
||||
"weather": ["snow",5]
|
||||
```
|
||||
|
||||
我们也可以使用`setWeather`事件来设置当前天气,有关事件的详细介绍请参见[事件](event)。
|
||||
|
||||
## 背景音乐
|
||||
|
||||
本塔支持BGM和SE的播放。
|
||||
|
||||
209
docs/event.md
209
docs/event.md
@ -1,6 +1,6 @@
|
||||
# 事件
|
||||
|
||||
?> 上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
本章内将对样板所支持的事件进行介绍。
|
||||
|
||||
@ -214,6 +214,25 @@
|
||||
]
|
||||
```
|
||||
|
||||
除此以外,我们还能实现“对话框效果”,只要有`\b[...]`就可以。
|
||||
|
||||
- `\b[up]` 直接显示在当前点上方。同样把这里的up换成down则为下方。
|
||||
- 如果不存在当前点(如在firstArrive中调用),则显示在屏幕最上方(最下方)
|
||||
- `\b[up,hero]` 显示在勇士上方。同样把这里的up换成down则为下方。
|
||||
- `\b[up,x,y]` 显示在(x,y)点的上方(下方);x和y都为整数且在0到12之间。
|
||||
|
||||
``` js
|
||||
"x,y": [ // 实际执行的事件列表
|
||||
"\b[up]这段文字显示在当前点上方",
|
||||
"\b[down]这段文字显示在当前点上方",
|
||||
"\t[hero]\b[up,hero]这是一段勇士说的话,会显示在勇士上方",
|
||||
"\t[小妖精,fairy]\b[down,2,2]这是一段小妖精说的话,会显示在(2,2)点下方",
|
||||
]
|
||||
```
|
||||
|
||||
!> `\t[...]`必须在`\b[...]`前面!不然两者都无法正常显示。
|
||||
|
||||
|
||||
另外值得一提的是,我们是可以在文字中计算一个表达式的值的。只需要将表达式用 `${ }`整个括起来就可以。
|
||||
|
||||
``` js
|
||||
@ -242,6 +261,25 @@
|
||||
|
||||

|
||||
|
||||
### setText:设置剧情文本的属性
|
||||
|
||||
使用`{"type": "setText"}`可以设置剧情文本的各项属性。
|
||||
|
||||
``` js
|
||||
"x,y": [ // 实际执行的事件列表
|
||||
{"type": "setText", "position": "up", "title": [255,0,0], "text": [255,255,0], "background": [0,0,255,0.3]},
|
||||
"这段话将显示在上方,标题为红色,正文为黄色,背景为透明度0.3的蓝色"
|
||||
]
|
||||
```
|
||||
|
||||
position为可选项,表示设置文字显示位置。只能为up(上),center(中)和down(下)三者。
|
||||
|
||||
title为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示标题(名字)颜色。
|
||||
|
||||
text为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示正文颜色。
|
||||
|
||||
background为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示背景色。
|
||||
|
||||
### tip:显示一段提示文字
|
||||
|
||||
`{"type": "tip"}`可以在左上角显示一段提示文字。
|
||||
@ -381,13 +419,40 @@ revisit常常使用在一些商人之类的地方,当用户购买物品后不
|
||||
]
|
||||
```
|
||||
|
||||
### setBlock:设置某个图块
|
||||
|
||||
我们可以采用 `{"type": "setBlock"}` 来改变某个地图块。
|
||||
|
||||
``` js
|
||||
"x,y": [ // 实际执行的事件列表
|
||||
{"type": "setBlock", "floorId": "MT1", "loc": [3,3], "number": 233}, // 将MT1层的(3,3)点变成数字233
|
||||
{"type": "setBlock", "loc": [2,1], "number": 121}, // 省略floorId则默认为本层
|
||||
{"type": "setBlock", "number": 57}, // loc也可省略,默认为当前点
|
||||
]
|
||||
```
|
||||
|
||||
floorId为可选的,表示要更改的目标楼层。如果忽略此项,则默认为当前楼层。
|
||||
|
||||
loc为可选的,表示要更改地图块的坐标。如果忽略此项,则默认为当前事件点。
|
||||
|
||||
number为**要更改到的数字**,有关“数字”的定义详见参见[素材的机制](personalization#素材的机制)。
|
||||
|
||||
图块更改后:
|
||||
|
||||
- 其启用/禁用状态不会发生任何改变。原来是启用还是启用,原来是禁用还是禁用。
|
||||
- 可通行状态遵循覆盖原则,即**首先取该图块的默认noPass属性,如果剧本的events中定义该点的noPass则覆盖**。
|
||||
- 触发器(trigger)亦采用覆盖原则,即**首先取该图块的默认触发器(例如怪物是battle,道具是getItem,门是openDoor),如果剧本的events中定义了该点的trigger则覆盖**。
|
||||
|
||||
图块更改往往与[同一个点的多事件处理](#同一个点的多事件处理)相关。
|
||||
|
||||
### update: 立刻更新状态栏和地图显伤
|
||||
|
||||
当我们在上面调用show事件,显示一个怪物后,该怪物将不会有显伤显示。如果你需要刷新状态栏和地图显伤,只需要简单地调用 `{"type": "update"}` 即可。
|
||||
如果你需要刷新状态栏和地图显伤,只需要简单地调用 `{"type": "update"}` 即可。
|
||||
|
||||
### sleep: 等待多少毫秒
|
||||
|
||||
等价于RMXP中的"等待x帧",不过是以毫秒来计算。
|
||||
|
||||
基本写法:`{"type": "sleep", "time": xxx}` ,其中xxx为指定的毫秒数。
|
||||
|
||||
``` js
|
||||
@ -492,6 +557,48 @@ time为可选的,指定的话将作为楼层切换动画的时间。
|
||||
|
||||
使用disableShop可以永久禁用全局商店直到再次被openShop打开为止。有关全局商店的说明可参见[全局商店](#全局商店)。
|
||||
|
||||
### animate:显示动画
|
||||
|
||||
我们可以使用 `{"type": "animate"}` 来显示一段动画。
|
||||
|
||||
有关动画的详细介绍可参见[动画和天气系统](element#动画和天气系统)。
|
||||
|
||||
``` js
|
||||
"x,y": [ // 实际执行的事件列表
|
||||
{"type": "animate", "name": "yongchang", "loc": [1,3]}, // 在(1,3)显示“咏唱魔法”动画
|
||||
{"type": "animate", "name": "zone", "loc": "hero"}, // 在勇士位置显示“领域”动画
|
||||
{"type": "animate", "name": "hand"} // 可以不指定loc,则默认为当前事件点
|
||||
]
|
||||
```
|
||||
|
||||
name为动画名,**请确保动画在main.js中的this.animates中被定义过。**
|
||||
|
||||
loc为动画的位置,可以是`[x,y]`表示在(x,y)点显示,也可以是字符串`"hero"`表示在勇士点显示。
|
||||
|
||||
loc可忽略,如果忽略则显示为事件当前点。
|
||||
|
||||
在动画播放结束后才会继续执行下一个事件。
|
||||
|
||||
### showImage:显示图片
|
||||
|
||||
我们可以使用 `{"type": "showImage"}` 来显示一张图片。
|
||||
|
||||
``` js
|
||||
"x,y": [ // 实际执行的事件列表
|
||||
{"type": "showImage", "name": "bg", "loc": [231,297]}, // 在(231,297)显示bg.png
|
||||
{"type": "showImage", "name": "1", "loc": [109,167]}, // 在(109,167)显示1.png
|
||||
{"type": "showImage"} // 如果不指定name则清除所有图片。
|
||||
]
|
||||
```
|
||||
|
||||
name为图片名。**请确保图片在main.js中的this.pngs中被定义过。**
|
||||
|
||||
loc为图片左上角坐标,以像素为单位进行计算。
|
||||
|
||||
如果不指定name则清除所有显示的图片。
|
||||
|
||||
调用show/hide/move/animate等几个事件同样会清除所有显示的图片。
|
||||
|
||||
### setFg: 更改画面色调
|
||||
|
||||
我们可以使用 `{"type": "setFg"}` 来更改画面色调。
|
||||
@ -512,6 +619,26 @@ color为需要更改画面色调的颜色。它是一个数组,分别指定目
|
||||
|
||||
time为可选的,如果指定,则会作为更改画面色调的时间。
|
||||
|
||||
### setWeather:更改天气
|
||||
|
||||
我们可以使用 `{"type": "setWeather"}` 来更改天气。
|
||||
|
||||
``` js
|
||||
"x,y": [ // 实际执行的事件列表
|
||||
{"type": "setWeather", "name": "rain", "level": 6}, // 更改为雨天,强度为6级
|
||||
{"type": "setWeather", "name": "snow", "level": 3}, // 更改为雪天,强度为3级
|
||||
{"type": "setWeather"} // 更改回晴天
|
||||
]
|
||||
```
|
||||
|
||||
name为天气选项。目前只支持`rain`和`snow`,即雨天和雪天。
|
||||
|
||||
level为天气的强度等级,在1-10之间。1级为最弱,10级为最强。
|
||||
|
||||
如果想改回晴天则直接不加任何参数。
|
||||
|
||||
!> 使用setWeather更改的天气在切换地图后会被目标地图的默认天气覆盖。
|
||||
|
||||
### move: 让某个NPC/怪物移动
|
||||
|
||||
如果我们需要移动某个NPC或怪物,可以使用`{"type": "move"}`。
|
||||
@ -801,6 +928,84 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用
|
||||
// ……
|
||||
```
|
||||
|
||||
## 同一个点的多事件处理
|
||||
|
||||
我们可以发现,就目前而且,每个点的事件是和该点进行绑定,并以该点坐标作为唯一索引来查询。
|
||||
|
||||
而有时候,我们往往需要在同一个点存在多个不同的事件。这涉及到同一个点的多事件处理。
|
||||
|
||||
我们可以依靠两来实现。**`setBlock`事件**和**if+flag的条件判断**。
|
||||
|
||||
下面以几个具体例子来进行详细说明。
|
||||
|
||||
### 打怪掉宝(怪物->道具)
|
||||
|
||||
我们注意到怪物和道具都是系统默认事件,因此无需写events,而是直接在afterBattle中setBlock即可。
|
||||
|
||||
``` js
|
||||
"afterBattle": {
|
||||
"x,y": [
|
||||
{"type": "setBlock", "number": 21} // 变成黄钥匙。注意是当前点因此可省略floorId和loc
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 打怪变成可对话的NPC(怪物->NPC)
|
||||
|
||||
由于NPC是自定义事件,因此我们需要写events。注意到events中不覆盖trigger,则还是怪物时,存在系统trigger因此会战斗;变成NPC后没有系统trigger因此会触发自定义事件。
|
||||
|
||||
请注意打死怪物时默认会禁用该点,因此替换后需要手动进行show来启用。
|
||||
|
||||
``` js
|
||||
"events": {
|
||||
"x,y": [
|
||||
"可对话的NPC"
|
||||
]
|
||||
},
|
||||
"afterBattle": {
|
||||
"x,y": [
|
||||
{"type": "setBlock", "number": 121}, // 变成老人
|
||||
{"type": "show", "loc": [x,y]} // 启用该点
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 获得圣水后变成墙
|
||||
|
||||
这个例子要求获得圣水时不前进(也就是不能走到圣水地方),然后把圣水位置变成墙。
|
||||
|
||||
因此需要我们需要覆盖系统trigger(getItem),并覆盖noPass。
|
||||
|
||||
通过if来判断有没有获得圣水,没有则触发圣水(生命x2)然后变成墙,否则不执行。
|
||||
|
||||
``` js
|
||||
"events": {
|
||||
"x,y": {
|
||||
"trigger": "action", // 覆盖系统trigger,默认的getItem不会执行
|
||||
"noPass": true, // 覆盖可通行状态,不允许走到该点
|
||||
"data": [
|
||||
{"type": "if", "condition": "flag:hasSuperPotion", // 条件判断:是否喝过圣水
|
||||
"true": [], // 喝过了,不执行
|
||||
"false": [
|
||||
{"type":"setValue", "name":"status:hp", "value":"status:hp*2"}, // 生命翻倍
|
||||
{"type":"setBlock", "number": 1}, // 将该点变成墙
|
||||
{"type":"setValue", "name":"flag:hasSuperPotion", "value": "true"} // 标记已经喝过了
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
总之,记住如下两点:
|
||||
|
||||
- 可以使用setBlock来更改一个图块。
|
||||
- 可通行状态遵循覆盖原则,即**首先取该图块的默认noPass属性,如果剧本的events中定义该点的noPass则覆盖**。
|
||||
- 触发器(trigger)亦采用覆盖原则,即**首先取该图块的默认触发器(例如怪物是battle,道具是getItem,门是openDoor),如果剧本的events中定义了该点的trigger则覆盖**。
|
||||
- 可以通过if语句和flag来控制自定义事件具体走向哪个分支。
|
||||
- 如果弄不清楚系统trigger和自定义事件等的区别,也可以全部覆盖为自定义事件,然后通过type:battle,type:openDoor等来具体进行控制。
|
||||
|
||||
## 加点事件
|
||||
|
||||
打败怪物后可以进行加点。
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# HTML5 魔塔样板说明文档
|
||||
|
||||
?> 上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
众所周知,魔塔的趋势是向移动端发展,贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中,NekoRPG有着比较大的局限性,游戏感较差,更是完全没法在iOS上运行。而一些APP的魔塔虽然可用,但是必须要下载安装,对于Android和iOS还必须开发不同的版本,非常麻烦。
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 个性化
|
||||
|
||||
?> 上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。
|
||||
|
||||
@ -27,27 +27,35 @@
|
||||
|
||||
由于HTML5功能(素材)有限,导致了对很多比较复杂的素材(比如房子内)等无法有着较好的绘图方式。
|
||||
|
||||
为了解决这个问题,我们允许用户自己放置一张图片作为某一层的背景素材。
|
||||
为了解决这个问题,我们允许用户自己放置一张或多张图片作为某一层的背景素材。
|
||||
|
||||
要启用这个功能,我们首先需要在`main.js`中将可能的图片进行加载。
|
||||
|
||||
``` js
|
||||
this.pngs = [ // 在此存放所有可能的背景图片;背景图片最好是416*416像素,其他分辨率会被强制缩放成416*416
|
||||
// 建议对于较大的图片,在网上使用在线的“图片压缩工具”来进行压缩,以节省流量
|
||||
"bg.png", // "yewai.png",
|
||||
this.pngs = [ // 在此存放所有可能使用的图片,只能是png格式,可以不写后缀名
|
||||
// 图片可以被作为背景图(的一部分),也可以直接用自定义事件进行显示。
|
||||
// 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
|
||||
// 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量
|
||||
"bg", // 依次向后添加
|
||||
];
|
||||
```
|
||||
|
||||
!> 背景素材只支持png格式,且会被强制缩放到416*416。
|
||||
!> 背景素材只支持png格式。
|
||||
|
||||
!> 请使用网上的一些[在线图片压缩工具](http://www.asqql.com/gifzip/)对png图片进行压缩,以节省流量。一张500KB的png图片可以被压缩到20-30KB,显示效果不会有太大差异。
|
||||
!> 请使用网上的一些[在线图片压缩工具](http://compresspng.com/zh/)对png图片进行压缩,以节省流量。一张500KB的png图片可以被压缩到20-30KB,显示效果不会有太大差异。
|
||||
|
||||
之后,我们可以在每层剧本的`"png": "xxx"`里来定义该层的默认背景图片素材。
|
||||
之后,我们可以在每层剧本的`"png"`里来定义该层的默认背景图片素材。
|
||||
|
||||
``` js
|
||||
"png": "bg.png", // 背景图;你可以选择一张png图片来作为背景素材。
|
||||
"png": [[x,y,"bg"]], // 背景图;你可以选择一张或多张png图片来作为背景素材。
|
||||
"png": [], // 无任何背景图
|
||||
"png": [[1,1,"house"], [6,7,"house2"]] // 在(1,1)放一个house.png,且(6,7)放house2.png
|
||||
```
|
||||
|
||||
png为一个数组,代表当前层所有作为背景素材的图片信息。
|
||||
|
||||
每一项为一个三元组,分别为该背景素材的x,y和图片名。其中x和y分别为横纵坐标,在0-12之间;图片名则必须在上面的this.pngs中定义过。
|
||||
|
||||
你的图片背景素材将会覆盖原来本身的背景层。
|
||||
|
||||
**如果你需要让某些点不可通行(比如你建了个房子,墙壁和家具等位置不让通行),则需在`events`中指定`{"noPass": false}`,参见[自定义事件](event#自定义事件)的写法。
|
||||
@ -213,15 +221,23 @@ if (itemId === 'shield5') {
|
||||
core.setFlag("shield5", true); // 增加一个自定义Flag:已经拿到神圣盾
|
||||
}
|
||||
```
|
||||
2. 免疫吸血效果:在`enemys.js`的getExtraDamage函数中,编辑成如果存在神圣盾标记,额外伤害为0。
|
||||
2. 免疫吸血效果:在`enemys.js`的伤害计算中,编辑成如果存在神圣盾标记,吸血伤害为0。
|
||||
``` js
|
||||
enemys.prototype.getExtraDamage = function (monster) {
|
||||
var extra_damage = 0;
|
||||
if (this.hasSpecial(monster.special, 11)) { // 吸血
|
||||
// 吸血的比例
|
||||
extra_damage = core.status.hero.hp * monster.value;
|
||||
if (core.hasFlag("shield5")) extra_damage = 0; // 如果存在神圣盾,则免疫吸血
|
||||
extra_damage = parseInt(extra_damage);
|
||||
enemys.prototype.calDamage = function (monster, hero_hp, hero_atk, hero_def, hero_mdef) {
|
||||
// ... 上略
|
||||
// 吸血
|
||||
if (this.hasSpecial(mon_special, 11)) {
|
||||
var vampireDamage = hero_hp * monster.value;
|
||||
|
||||
// 如果有神圣盾免疫吸血等可以在这里写
|
||||
if (core.hasFlag("shield5")) vampireDamage = 0; // 存在神圣盾,吸血伤害为0
|
||||
|
||||
vampireDamage = parseInt(vampireDamage);
|
||||
// 加到自身
|
||||
if (monster.add) // 如果加到自身
|
||||
mon_hp += vampireDamage;
|
||||
|
||||
initDamage += vampireDamage;
|
||||
}
|
||||
// ... 下略
|
||||
```
|
||||
@ -255,8 +271,6 @@ core.prototype.checkBlock = function () {
|
||||
|
||||
如果要修改伤害计算公式,请修改下面的calDamage函数。请注意,如果无法战斗,该函数必须返回`999999999`。
|
||||
|
||||
对于吸血怪的额外伤害计算在getExtraDamage中。
|
||||
|
||||
对于毒衰弱怪物的战斗后结算在`events.js`中的afterBattle函数中。
|
||||
|
||||
对于领域、夹击、阻击怪物的检查在`events.js`中的checkBlock函数中。
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# 快速上手
|
||||
|
||||
?> 上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!
|
||||
|
||||
|
||||
BIN
images/forward.png
Normal file
BIN
images/forward.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 662 B |
BIN
images/pause.png
Normal file
BIN
images/pause.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 269 B |
BIN
images/play.png
Normal file
BIN
images/play.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 340 B |
BIN
images/rewind.png
Normal file
BIN
images/rewind.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 689 B |
BIN
images/stop.png
Normal file
BIN
images/stop.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 239 B |
@ -109,10 +109,12 @@
|
||||
<canvas class='gameCanvas' id='event' width='416' height='416'></canvas>
|
||||
<canvas class='gameCanvas' id='fg' width='416' height='416'></canvas>
|
||||
<canvas class='gameCanvas' id='hero' width='416' height='416'></canvas>
|
||||
<canvas class='gameCanvas' id='animate' width='416' height='416'></canvas>
|
||||
<canvas class='gameCanvas' id='weather' width='416' height='416'></canvas>
|
||||
<canvas class='gameCanvas' id='ui' width='416' height='416'></canvas>
|
||||
<canvas class='gameCanvas' id='data' width='416' height='416'>此浏览器不支持HTML5</canvas>
|
||||
</div>
|
||||
<script id='mainScript' src='main.js'></script>
|
||||
<script src='libs/thirdparty/mid.js'></script>
|
||||
<script src='libs/thirdparty/mid.min.js'></script>
|
||||
</body>
|
||||
</html>
|
||||
1376
libs/core.js
1376
libs/core.js
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@ data.prototype.init = function() {
|
||||
this.firstData = {
|
||||
"title": "魔塔样板", // 游戏名,将显示在标题页面以及切换楼层的界面中
|
||||
"name": "template", // 游戏的唯一英文标识符。由英文、数字、下划线组成,不能超过20个字符。
|
||||
"version": "Ver 1.3.2", // 当前游戏版本;版本不一致的存档不能通用。
|
||||
"version": "Ver 1.4.1", // 当前游戏版本;版本不一致的存档不能通用。
|
||||
"floorId": "sample0", // 初始楼层ID
|
||||
"hero": { // 勇士初始数据
|
||||
"name": "阳光", // 勇士名;可以改成喜欢的
|
||||
@ -159,6 +159,7 @@ data.prototype.init = function() {
|
||||
"bombFourDirections": true, // 使用炸弹是否四个方向都会炸;如果false则只炸面前的怪物(即和圣锤等价)
|
||||
"bigKeyIsBox": false, // 如果此项为true,则视为钥匙盒,红黄蓝钥匙+1;若为false,则视为大黄门钥匙
|
||||
"equipment": false, // 剑和盾是否直接作为装备。如果此项为true,则作为装备,需要在道具栏使用,否则将直接加属性。
|
||||
"enableDeleteItem": true, // 是否允许删除(丢弃)道具
|
||||
/****** 怪物相关 ******/
|
||||
"enableNegativeDamage": true, // 是否支持负伤害(回血)
|
||||
"hatredDecrease": true, // 是否在和仇恨怪战斗后减一半的仇恨值,此项为false则和仇恨怪不会扣减仇恨值。
|
||||
@ -173,6 +174,8 @@ data.prototype.init = function() {
|
||||
"enableGentleClick": true, // 是否允许轻触(获得面前物品)
|
||||
"potionWhileRouting": false, // 寻路算法是否经过血瓶;如果该项为false,则寻路算法会自动尽量绕过血瓶
|
||||
"enableViewMaps": true, // 是否支持在菜单栏中查看所有楼层的地图
|
||||
"portalWithoutTrigger": true, // 是否支持穿透。所谓穿透,即当自动寻路经过楼梯时,不触发楼层转换事件而是穿过它。
|
||||
"enableMoveDirectly": true, // 是否允许瞬间移动
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -289,10 +289,11 @@ enemys.prototype.calDamage = function (monster, hero_hp, hero_atk, hero_def, her
|
||||
}
|
||||
|
||||
////// 获得当前楼层的怪物列表 //////
|
||||
enemys.prototype.getCurrentEnemys = function () {
|
||||
enemys.prototype.getCurrentEnemys = function (floorId) {
|
||||
floorId=floorId||core.status.floorId;
|
||||
var enemys = [];
|
||||
var used = {};
|
||||
var mapBlocks = core.status.thisMap.blocks;
|
||||
var mapBlocks = core.status.maps[floorId].blocks;
|
||||
for (var b = 0; b < mapBlocks.length; b++) {
|
||||
if (core.isset(mapBlocks[b].event) && !(core.isset(mapBlocks[b].enable) && !mapBlocks[b].enable) && mapBlocks[b].event.cls == 'enemys') {
|
||||
var monsterId = mapBlocks[b].event.id;
|
||||
|
||||
448
libs/events.js
448
libs/events.js
@ -6,7 +6,7 @@ function events() {
|
||||
events.prototype.init = function () {
|
||||
this.events = {
|
||||
'battle': function (data, core, callback) {
|
||||
core.autosave(true);
|
||||
//core.autosave(true);
|
||||
core.battle(data.event.id, data.x, data.y);
|
||||
if (core.isset(callback))
|
||||
callback();
|
||||
@ -17,7 +17,7 @@ events.prototype.init = function () {
|
||||
callback();
|
||||
},
|
||||
'openDoor': function (data, core, callback) {
|
||||
core.autosave(true);
|
||||
//core.autosave(true);
|
||||
core.openDoor(data.event.id, data.x, data.y, true, function () {
|
||||
if (core.isset(callback)) callback();
|
||||
core.replay();
|
||||
@ -115,14 +115,14 @@ events.prototype.setInitData = function (hard) {
|
||||
events.prototype.win = function(reason) {
|
||||
core.ui.closePanel();
|
||||
var replaying = core.status.replay.replaying;
|
||||
core.status.replay.replaying=false;
|
||||
core.stopReplay();
|
||||
core.waitHeroToStop(function() {
|
||||
core.removeGlobalAnimate(0,0,true);
|
||||
core.clearMap('all'); // 清空全地图
|
||||
core.drawText([
|
||||
"\t[恭喜通关]你的分数是${status:hp}。"
|
||||
], function () {
|
||||
core.events.gameOver(true, replaying);
|
||||
core.events.gameOver('', replaying);
|
||||
})
|
||||
});
|
||||
}
|
||||
@ -131,24 +131,23 @@ events.prototype.win = function(reason) {
|
||||
events.prototype.lose = function(reason) {
|
||||
core.ui.closePanel();
|
||||
var replaying = core.status.replay.replaying;
|
||||
core.status.replay.replaying=false;
|
||||
core.stopReplay();
|
||||
core.waitHeroToStop(function() {
|
||||
core.status.replay.replaying=false;
|
||||
core.drawText([
|
||||
"\t[结局1]你死了。\n如题。"
|
||||
], function () {
|
||||
core.events.gameOver(false, replaying);
|
||||
core.events.gameOver(null, replaying);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
////// 游戏结束 //////
|
||||
events.prototype.gameOver = function (success, fromReplay) {
|
||||
events.prototype.gameOver = function (ending, fromReplay) {
|
||||
|
||||
// 上传成绩
|
||||
var confirmUpload = function () {
|
||||
|
||||
if (!success) {
|
||||
if (!core.isset(ending)) {
|
||||
core.restart();
|
||||
return;
|
||||
}
|
||||
@ -164,6 +163,7 @@ events.prototype.gameOver = function (success, fromReplay) {
|
||||
formData.append('platform', core.platform.isPC?"PC":core.platform.isAndroid?"Android":core.platform.isIOS?"iOS":"");
|
||||
formData.append('hard', core.status.hard);
|
||||
formData.append('username', username);
|
||||
formData.append('ending', ending);
|
||||
formData.append('lv', core.status.hero.lv);
|
||||
formData.append('hp', core.status.hero.hp);
|
||||
formData.append('atk', core.status.hero.atk);
|
||||
@ -224,14 +224,14 @@ events.prototype.afterChangeFloor = function (floorId) {
|
||||
|
||||
if (!core.hasFlag("visited_"+floorId)) {
|
||||
this.doEvents(core.floors[floorId].firstArrive, null, null, function () {
|
||||
core.autosave();
|
||||
//core.autosave();
|
||||
});
|
||||
core.setFlag("visited_"+floorId, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// 自动存档
|
||||
core.autosave();
|
||||
//core.autosave();
|
||||
}
|
||||
|
||||
////// 开始执行一系列自定义事件 //////
|
||||
@ -254,7 +254,7 @@ events.prototype.doEvents = function (list, x, y, callback) {
|
||||
////// 执行当前自定义事件列表中的下一个事件 //////
|
||||
events.prototype.doAction = function() {
|
||||
// 清空boxAnimate和UI层
|
||||
clearInterval(core.interval.boxAnimate);
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.clearMap('ui', 0, 0, 416, 416);
|
||||
core.setAlpha('ui', 1.0);
|
||||
|
||||
@ -287,11 +287,23 @@ events.prototype.doAction = function() {
|
||||
core.status.event.data.type=data.type;
|
||||
switch (data.type) {
|
||||
case "text": // 文字/对话
|
||||
if (core.status.replay.isreplaying)
|
||||
if (core.status.replay.replaying)
|
||||
core.events.doAction();
|
||||
else
|
||||
core.ui.drawTextBox(data.data);
|
||||
break;
|
||||
case "setText": // 设置文本状态
|
||||
if (data.position=='up'||data.position=='down'||data.position=='center') {
|
||||
core.status.textAttribute.position=data.position;
|
||||
}
|
||||
["background", "title", "text"].forEach(function (t) {
|
||||
if (core.isset(data[t]) && (data[t] instanceof Array) && data[t].length>=3) {
|
||||
if (data[t].length==3) data[t].push(1);
|
||||
core.status.textAttribute[t]=data[t];
|
||||
}
|
||||
})
|
||||
core.events.doAction();
|
||||
break;
|
||||
case "tip":
|
||||
core.drawTip(core.replaceText(data.text));
|
||||
core.events.doAction();
|
||||
@ -322,6 +334,48 @@ events.prototype.doAction = function() {
|
||||
}
|
||||
else this.doAction();
|
||||
break;
|
||||
case "setBlock": // 设置某图块
|
||||
{
|
||||
if (core.isset(data.loc)) {
|
||||
x=data.loc[0];
|
||||
y=data.loc[1];
|
||||
}
|
||||
var floorId = data.floorId||core.status.floorId;
|
||||
var originBlock=core.getBlock(x,y,toId,false);
|
||||
var block = core.maps.getBlock(x,y,data.number);
|
||||
core.maps.addInfo(block);
|
||||
core.maps.addEvent(block,x,y,core.floors[floorId].events[x+","+y]);
|
||||
core.maps.addChangeFloor(block,x,y,core.floors[floorId].changeFloor[x+","+y]);
|
||||
if (core.isset(block.event)) {
|
||||
if (originBlock==null) {
|
||||
core.status.maps[floorId].blocks.push(block);
|
||||
}
|
||||
else {
|
||||
originBlock.block.id = data.number;
|
||||
originBlock.block.event = block.event;
|
||||
}
|
||||
core.drawMap(floorId);
|
||||
core.drawHero(core.getHeroLoc('direction'), core.getHeroLoc('x'), core.getHeroLoc('y'), 'stop');
|
||||
core.updateStatusBar();
|
||||
}
|
||||
this.doAction();
|
||||
break;
|
||||
}
|
||||
case "animate": // 显示动画
|
||||
if (core.isset(data.loc)) {
|
||||
if (data.loc == 'hero') {
|
||||
x=core.getHeroLoc('x');
|
||||
y=core.getHeroLoc('y');
|
||||
}
|
||||
else if (data.loc instanceof Array) {
|
||||
x=data.loc[0];
|
||||
y=data.loc[1];
|
||||
}
|
||||
}
|
||||
core.drawAnimate(data.name, x, y, function () {
|
||||
core.events.doAction();
|
||||
})
|
||||
break;
|
||||
case "move": // 移动事件
|
||||
if (core.isset(data.loc)) {
|
||||
x=data.loc[0];
|
||||
@ -354,11 +408,22 @@ events.prototype.doAction = function() {
|
||||
core.drawHero(core.getHeroLoc('direction'), core.getHeroLoc('x'), core.getHeroLoc('y'), 'stop');
|
||||
this.doAction();
|
||||
break;
|
||||
case "showImage": // 显示图片
|
||||
if (core.isset(data.loc) && core.isset(core.material.images.pngs[data.name])) {
|
||||
core.canvas.animate.drawImage(core.material.images.pngs[data.name], data.loc[0], data.loc[1]);
|
||||
}
|
||||
else core.clearMap('animate', 0, 0, 416, 416);
|
||||
this.doAction();
|
||||
break;
|
||||
case "setFg": // 颜色渐变
|
||||
core.setFg(data.color, data.time, function() {
|
||||
core.events.doAction();
|
||||
});
|
||||
break;
|
||||
case "setWeather": // 更改天气
|
||||
core.setWeather(data.name, data.level);
|
||||
this.doAction();
|
||||
break;
|
||||
case "openDoor": // 开一个门,包括暗墙
|
||||
var floorId=data.floorId || core.status.floorId;
|
||||
var block=core.getBlock(data.loc[0], data.loc[1], floorId);
|
||||
@ -378,6 +443,7 @@ events.prototype.doAction = function() {
|
||||
case "openShop": // 打开一个全局商店
|
||||
if (core.status.replay.replaying) { // 正在播放录像,简单将visited置为true
|
||||
core.status.shops[data.id].visited=true;
|
||||
core.status.event.data.list = [];
|
||||
this.doAction();
|
||||
}
|
||||
else
|
||||
@ -470,18 +536,15 @@ events.prototype.doAction = function() {
|
||||
else {
|
||||
var action = core.status.replay.toReplay.shift(), index;
|
||||
if (action.indexOf("choices:")==0 && ((index=parseInt(action.substring(8)))>=0) && index<data.choices.length) {
|
||||
//core.status.route.push("choices:"+index);
|
||||
//this.insertAction(data.choices[index].action);
|
||||
//this.doAction();
|
||||
core.status.event.selection=index;
|
||||
setTimeout(function () {
|
||||
core.status.route.push("choices:"+index);
|
||||
core.events.insertAction(data.choices[index].action);
|
||||
core.events.doAction();
|
||||
}, 500)
|
||||
}, 750)
|
||||
}
|
||||
else {
|
||||
core.status.replay.replaying=false;
|
||||
core.stopReplay();
|
||||
core.drawTip("录像文件出错");
|
||||
}
|
||||
}
|
||||
@ -568,12 +631,15 @@ events.prototype.openShop = function(shopId, needVisited) {
|
||||
var actions = [];
|
||||
if (core.isset(core.status.event.data) && core.isset(core.status.event.data.actions))
|
||||
actions=core.status.event.data.actions;
|
||||
var fromList;
|
||||
if (core.isset(core.status.event.data) && core.isset(core.status.event.data.fromList))
|
||||
fromList = core.status.event.data.fromList;
|
||||
|
||||
core.ui.closePanel();
|
||||
core.lockControl();
|
||||
// core.status.event = {'id': 'shop', 'data': {'id': shopId, 'shop': shop}};
|
||||
core.status.event.id = 'shop';
|
||||
core.status.event.data = {'id': shopId, 'shop': shop, 'actions': actions};
|
||||
core.status.event.data = {'id': shopId, 'shop': shop, 'actions': actions, 'fromList': fromList};
|
||||
core.status.event.selection = selection;
|
||||
|
||||
// 拼词
|
||||
@ -605,7 +671,7 @@ events.prototype.disableQuickShop = function (shopId) {
|
||||
|
||||
////// 能否使用快捷商店 //////
|
||||
events.prototype.canUseQuickShop = function(shopId) {
|
||||
if (core.isset(core.floors[core.status.floorId].canUseQuickShop) && !core.isset(core.floors[core.status.floorId].canUseQuickShop))
|
||||
if (core.isset(core.floors[core.status.floorId].canUseQuickShop) && !core.floors[core.status.floorId].canUseQuickShop)
|
||||
return '当前不能使用快捷商店。';
|
||||
|
||||
return null;
|
||||
@ -745,13 +811,16 @@ events.prototype.afterBattle = function(enemyId,x,y,callback) {
|
||||
|
||||
// 如果事件不为空,将其插入
|
||||
if (todo.length>0) {
|
||||
this.insertAction(todo);
|
||||
this.insertAction(todo,x,y);
|
||||
}
|
||||
|
||||
// 如果已有事件正在处理中
|
||||
if (core.status.event.id == null) {
|
||||
core.continueAutomaticRoute();
|
||||
}
|
||||
else {
|
||||
core.clearContinueAutomaticRoute();
|
||||
}
|
||||
if (core.isset(callback)) callback();
|
||||
|
||||
}
|
||||
@ -768,12 +837,15 @@ events.prototype.afterOpenDoor = function(doorId,x,y,callback) {
|
||||
}
|
||||
|
||||
if (todo.length>0) {
|
||||
this.insertAction(todo);
|
||||
this.insertAction(todo,x,y);
|
||||
}
|
||||
|
||||
if (core.status.event.id == null) {
|
||||
core.continueAutomaticRoute();
|
||||
}
|
||||
else {
|
||||
core.clearContinueAutomaticRoute();
|
||||
}
|
||||
if (core.isset(callback)) callback();
|
||||
}
|
||||
|
||||
@ -989,7 +1061,12 @@ events.prototype.clickBook = function(x,y) {
|
||||
}
|
||||
// 返回
|
||||
if (x>=10 && x<=12 && y==12) {
|
||||
core.ui.closePanel();
|
||||
if (core.status.event.selection==null)
|
||||
core.ui.closePanel();
|
||||
else {
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.ui.drawMaps(core.status.event.selection);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 怪物信息
|
||||
@ -1017,7 +1094,12 @@ events.prototype.keyDownBook = function (keycode) {
|
||||
////// 怪物手册界面时,放开某个键的操作 //////
|
||||
events.prototype.keyUpBook = function (keycode) {
|
||||
if (keycode==27 || keycode==88) {
|
||||
core.ui.closePanel();
|
||||
if (core.status.event.selection==null)
|
||||
core.ui.closePanel();
|
||||
else {
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.ui.drawMaps(core.status.event.selection);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
@ -1044,9 +1126,10 @@ events.prototype.clickFly = function(x,y) {
|
||||
var index=core.status.hero.flyRange.indexOf(core.status.floorId);
|
||||
var stair=core.status.event.data<index?"upFloor":"downFloor";
|
||||
var floorId=core.status.event.data;
|
||||
core.status.route.push("fly:"+core.status.hero.flyRange[floorId]);
|
||||
core.changeFloor(core.status.hero.flyRange[floorId], stair);
|
||||
var toFloor = core.status.hero.flyRange[floorId];
|
||||
core.status.route.push("fly:"+toFloor);
|
||||
core.ui.closePanel();
|
||||
core.changeFloor(toFloor, stair);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1091,11 +1174,14 @@ events.prototype.keyDownViewMaps = function (keycode) {
|
||||
|
||||
////// 查看地图界面时,放开某个键的操作 //////
|
||||
events.prototype.keyUpViewMaps = function (keycode) {
|
||||
if (keycode==27 || keycode==88 || keycode==13 || keycode==32 || keycode==67) {
|
||||
if (keycode==27 || keycode==13 || keycode==32 || keycode==67) {
|
||||
core.clearMap('data', 0, 0, 416, 416);
|
||||
core.setOpacity('data', 1);
|
||||
core.ui.closePanel();
|
||||
}
|
||||
if (keycode==88) {
|
||||
core.openBook(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1109,8 +1195,6 @@ events.prototype.clickShop = function(x,y) {
|
||||
|
||||
core.status.event.selection=y-topIndex;
|
||||
|
||||
//this.insertAction(choices[y-topIndex].action);
|
||||
//this.doAction();
|
||||
var money = core.getStatus('money'), experience = core.getStatus('experience');
|
||||
var times = shop.times, need = eval(shop.need);
|
||||
var use = shop.use;
|
||||
@ -1145,8 +1229,8 @@ events.prototype.clickShop = function(x,y) {
|
||||
core.status.route.push("shop:"+core.status.event.data.id+":"+core.status.event.data.actions.join(""));
|
||||
}
|
||||
|
||||
core.status.event.data.actions = [];
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.setBoxAnimate();
|
||||
if (core.status.event.data.fromList)
|
||||
core.ui.drawQuickShop();
|
||||
else core.ui.closePanel();
|
||||
@ -1171,11 +1255,16 @@ events.prototype.keyDownShop = function (keycode) {
|
||||
////// 商店界面时,放开某个键的操作 //////
|
||||
events.prototype.keyUpShop = function (keycode) {
|
||||
if (keycode==27 || keycode==88) {
|
||||
if (core.status.event.data.fromList) {
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.setBoxAnimate();
|
||||
core.ui.drawQuickShop();
|
||||
if (core.status.event.data.actions.length>0) {
|
||||
core.status.route.push("shop:"+core.status.event.data.id+":"+core.status.event.data.actions.join(""));
|
||||
}
|
||||
|
||||
core.status.event.data.actions = [];
|
||||
|
||||
core.status.boxAnimateObjs = [];
|
||||
|
||||
if (core.status.event.data.fromList)
|
||||
core.ui.drawQuickShop();
|
||||
else
|
||||
core.ui.closePanel();
|
||||
return;
|
||||
@ -1243,6 +1332,18 @@ events.prototype.clickToolbox = function(x,y) {
|
||||
core.ui.closePanel();
|
||||
return;
|
||||
}
|
||||
if (x>=10 && x<=12 && y<=1) {
|
||||
if (!core.isset(core.status.event.data)) return;
|
||||
if (!core.flags.enableDeleteItem) {
|
||||
core.drawTip("不支持删除道具!");
|
||||
return;
|
||||
}
|
||||
core.removeItem(core.status.event.data);
|
||||
core.status.event.data = null;
|
||||
core.ui.drawToolbox();
|
||||
return;
|
||||
}
|
||||
|
||||
var index=0;
|
||||
if (y==4||y==5||y==9||y==10) index=parseInt(x/2);
|
||||
else index=6+parseInt(x/2);
|
||||
@ -1347,6 +1448,19 @@ events.prototype.keyUpToolbox = function (keycode) {
|
||||
this.clickToolboxIndex(core.status.event.selection);
|
||||
return;
|
||||
}
|
||||
|
||||
if (keycode==46) { // delete
|
||||
if (!core.isset(core.status.event.data)) return;
|
||||
if (!core.flags.enableDeleteItem) {
|
||||
core.drawTip("不支持删除道具!");
|
||||
return;
|
||||
}
|
||||
core.removeItem(core.status.event.data);
|
||||
core.status.event.data = null;
|
||||
core.ui.drawToolbox();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////// 存读档界面时的点击操作 //////
|
||||
@ -1464,9 +1578,7 @@ events.prototype.keyUpSL = function (keycode) {
|
||||
////// 系统设置界面时的点击操作 //////
|
||||
events.prototype.clickSwitchs = function (x,y) {
|
||||
if (x<5 || x>7) return;
|
||||
var choices = [
|
||||
"背景音乐", "背景音效", "战斗动画", "怪物显伤", "领域显伤", "下载离线版本", "返回主菜单"
|
||||
];
|
||||
var choices = core.status.event.ui.choices;
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
var selection = y-topIndex;
|
||||
@ -1537,9 +1649,7 @@ events.prototype.keyUpSwitchs = function (keycode) {
|
||||
core.ui.drawSettings();
|
||||
return;
|
||||
}
|
||||
var choices = [
|
||||
"背景音乐", "背景音效", "战斗动画", "怪物显伤", "领域显伤", "下载离线版本", "返回主菜单"
|
||||
];
|
||||
var choices = core.status.event.ui.choices;
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
this.clickSwitchs(6, topIndex+core.status.event.selection);
|
||||
@ -1550,9 +1660,7 @@ events.prototype.keyUpSwitchs = function (keycode) {
|
||||
////// 系统菜单栏界面时的点击事件 //////
|
||||
events.prototype.clickSettings = function (x,y) {
|
||||
if (x<5 || x>7) return;
|
||||
var choices = [
|
||||
"系统设置", "快捷商店", "浏览地图", "同步存档", "重新开始", "数据统计", "操作帮助", "关于本塔", "返回游戏"
|
||||
];
|
||||
var choices = core.status.event.ui.choices;
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
var selection = y-topIndex;
|
||||
@ -1571,7 +1679,7 @@ events.prototype.clickSettings = function (x,y) {
|
||||
core.drawTip("本塔不允许浏览地图!");
|
||||
}
|
||||
else {
|
||||
core.drawText("\t[系统提示]即将进入浏览地图模式。\n\n点击地图上半部分,或按[↑]键可查看前一张地图\n点击地图下半部分,或按[↓]键可查看后一张地图\n点击地图中间,或按[ESC]键可离开浏览地图模式", function () {
|
||||
core.drawText("\t[系统提示]即将进入浏览地图模式。\n\n点击地图上半部分,或按[↑]键可查看前一张地图\n点击地图下半部分,或按[↓]键可查看后一张地图\n点击地图中间,或按[ESC]键可离开浏览地图模式\n此模式下可以打开怪物手册以查看某层楼的怪物属性", function () {
|
||||
core.ui.drawMaps(core.floorIds.indexOf(core.status.floorId));
|
||||
})
|
||||
}
|
||||
@ -1594,7 +1702,7 @@ events.prototype.clickSettings = function (x,y) {
|
||||
core.ui.drawWaiting("正在拉取统计信息,请稍后...");
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('type', 'getinfo');
|
||||
formData.append('type', 'statistics');
|
||||
formData.append('name', core.firstData.name);
|
||||
formData.append('version', core.firstData.version);
|
||||
|
||||
@ -1615,9 +1723,14 @@ events.prototype.clickSettings = function (x,y) {
|
||||
toAdd=true;
|
||||
if (t.hard!='') text+=t.hard+"难度: "
|
||||
text+="已有"+t.people+"人次游戏,"+t.score+"人次通关。";
|
||||
if (core.isset(t.max) && t.max>0) {
|
||||
text+="\n当前MAX为"+t.max+",最早由 "+(t.username||"匿名")+" 于"+core.formatDate(new Date(1000*t.timestamp))+"打出。";
|
||||
}
|
||||
t.info.forEach(function(ending) {
|
||||
if (ending.ending!='') {
|
||||
text+="\n"+ending.ending+": 已有"+ending.score+"人次通关。";
|
||||
}
|
||||
if (core.isset(ending.max) && ending.max>0) {
|
||||
text+="\n当前MAX为"+ending.max+",最早由 "+(ending.username||"匿名")+" 于"+core.formatDate(new Date(1000*ending.timestamp))+"打出。";
|
||||
}
|
||||
})
|
||||
})
|
||||
core.drawText(text);
|
||||
}
|
||||
@ -1666,9 +1779,7 @@ events.prototype.keyUpSettings = function (keycode) {
|
||||
core.ui.closePanel();
|
||||
return;
|
||||
}
|
||||
var choices = [
|
||||
"系统设置", "快捷商店", "浏览地图", "同步存档", "重新开始", "数据统计", "操作帮助", "关于本塔", "返回游戏"
|
||||
];
|
||||
var choices = core.status.event.ui.choices;
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
this.clickSettings(6, topIndex+core.status.event.selection);
|
||||
@ -1678,20 +1789,21 @@ events.prototype.keyUpSettings = function (keycode) {
|
||||
////// 同步存档界面时的点击操作 //////
|
||||
events.prototype.clickSyncSave = function (x,y) {
|
||||
if (x<5 || x>7) return;
|
||||
var choices = [
|
||||
"同步存档到服务器", "从服务器加载存档", "存档至本地文件", "从本地文件读档", "清空所有存档", "返回主菜单"
|
||||
];
|
||||
var choices = core.status.event.ui.choices;
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
var selection = y-topIndex;
|
||||
switch (selection) {
|
||||
case 0:
|
||||
core.syncSave("save");
|
||||
// core.syncSave("save");
|
||||
core.status.event.selection=0;
|
||||
core.ui.drawSyncSelect();
|
||||
break;
|
||||
case 1:
|
||||
core.syncSave("load");
|
||||
core.syncLoad();
|
||||
break;
|
||||
case 2:
|
||||
/*
|
||||
var saves = [];
|
||||
for (var i=1;i<=150;i++) {
|
||||
var data = core.getLocalStorage("save"+i, null);
|
||||
@ -1705,6 +1817,9 @@ events.prototype.clickSyncSave = function (x,y) {
|
||||
"data": saves
|
||||
}
|
||||
core.download(core.firstData.name+"_"+core.formatDate2(new Date())+".h5save", JSON.stringify(content));
|
||||
*/
|
||||
core.status.event.selection=0;
|
||||
core.ui.drawLocalSaveSelect();
|
||||
break;
|
||||
case 3:
|
||||
core.readFile(function (obj) {
|
||||
@ -1721,30 +1836,55 @@ events.prototype.clickSyncSave = function (x,y) {
|
||||
return;
|
||||
}
|
||||
var data=obj.data;
|
||||
for (var i=1;i<=150;i++) {
|
||||
if (i<=data.length) {
|
||||
core.setLocalStorage("save"+i, data[i-1]);
|
||||
}
|
||||
else {
|
||||
core.removeLocalStorage("save"+i);
|
||||
}
|
||||
|
||||
if (data instanceof Array) {
|
||||
core.ui.drawConfirmBox("所有本地存档都将被覆盖,确认?", function () {
|
||||
for (var i=1;i<=150;i++) {
|
||||
if (i<=data.length) {
|
||||
core.setLocalStorage("save"+i, data[i-1]);
|
||||
}
|
||||
else {
|
||||
core.removeLocalStorage("save"+i);
|
||||
}
|
||||
}
|
||||
core.drawText("读取成功!\n你的本地所有存档均已被覆盖。");
|
||||
}, function () {
|
||||
core.status.event.selection=0;
|
||||
core.ui.drawSyncSave();
|
||||
})
|
||||
}
|
||||
else {
|
||||
var index=150;
|
||||
for (var i=150;i>=1;i--) {
|
||||
if (core.getLocalStorage("save"+i, null)==null)
|
||||
index=i;
|
||||
else break;
|
||||
}
|
||||
core.setLocalStorage("save"+index, data);
|
||||
core.drawText("同步成功!\n单存档已覆盖至存档"+index);
|
||||
}
|
||||
core.drawText("读取成功!\n你的本地所有存档均已被覆盖。");
|
||||
}, function () {
|
||||
|
||||
});
|
||||
break;
|
||||
case 4:
|
||||
core.download(core.firstData.name+"_"+core.formatDate2(new Date())+".h5route", JSON.stringify({
|
||||
'name': core.firstData.name,
|
||||
'hard': core.status.hard,
|
||||
'route': core.encodeRoute(core.status.route)
|
||||
}));
|
||||
break;
|
||||
case 5:
|
||||
core.status.event.selection=1;
|
||||
core.ui.drawConfirmBox("你确定要清空所有存档吗?", function() {
|
||||
localStorage.clear();
|
||||
core.drawText("\t[操作成功]你的所有存档已被清空。");
|
||||
}, function() {
|
||||
core.status.event.selection=2;
|
||||
core.ui.drawSyncSave(false);
|
||||
core.status.event.selection=5;
|
||||
core.ui.drawSyncSave();
|
||||
})
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
core.status.event.selection=3;
|
||||
core.ui.drawSettings();
|
||||
break;
|
||||
@ -1773,15 +1913,133 @@ events.prototype.keyUpSyncSave = function (keycode) {
|
||||
core.ui.drawSettings();
|
||||
return;
|
||||
}
|
||||
var choices = [
|
||||
"同步存档到服务器", "从服务器加载存档", "存档至本地文件", "从本地文件读档", "清空所有存档", "返回主菜单"
|
||||
];
|
||||
var choices = core.status.event.ui.choices;
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
this.clickSyncSave(6, topIndex+core.status.event.selection);
|
||||
}
|
||||
}
|
||||
|
||||
////// 同步存档选择界面时的点击操作 //////
|
||||
events.prototype.clickSyncSelect = function (x, y) {
|
||||
if (x<5 || x>7) return;
|
||||
var choices = core.status.event.ui.choices;
|
||||
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
var selection = y - topIndex;
|
||||
switch (selection) {
|
||||
case 0:
|
||||
core.syncSave('all');
|
||||
break;
|
||||
case 1:
|
||||
core.syncSave();
|
||||
break;
|
||||
case 2:
|
||||
core.status.event.selection=0;
|
||||
core.ui.drawSyncSave();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////// 同步存档选择界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownSyncSelect = function (keycode) {
|
||||
if (keycode==38) {
|
||||
core.status.event.selection--;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
if (keycode==40) {
|
||||
core.status.event.selection++;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
}
|
||||
|
||||
////// 同步存档选择界面时,放开某个键的操作 //////
|
||||
events.prototype.keyUpSyncSelect = function (keycode) {
|
||||
if (keycode==27 || keycode==88) {
|
||||
core.status.event.selection=0;
|
||||
core.ui.drawSettings();
|
||||
return;
|
||||
}
|
||||
var choices = core.status.event.ui.choices;
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
this.clickSyncSelect(6, topIndex+core.status.event.selection);
|
||||
}
|
||||
}
|
||||
|
||||
////// 存档下载界面时的点击操作 //////
|
||||
events.prototype.clickLocalSaveSelect = function (x,y) {
|
||||
if (x<5 || x>7) return;
|
||||
var choices = core.status.event.ui.choices;
|
||||
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
|
||||
var saves=null;
|
||||
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
var selection = y - topIndex;
|
||||
switch (selection) {
|
||||
case 0:
|
||||
saves=[];
|
||||
for (var i=1;i<=150;i++) {
|
||||
var data = core.getLocalStorage("save"+i, null);
|
||||
if (core.isset(data)) {
|
||||
saves.push(data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for (var i=150;i>=1;i--) {
|
||||
saves=core.getLocalStorage("save"+i, null);
|
||||
if (core.isset(saves)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (core.isset(saves)) {
|
||||
var content = {
|
||||
"name": core.firstData.name,
|
||||
"version": core.firstData.version,
|
||||
"data": saves
|
||||
}
|
||||
core.download(core.firstData.name+"_"+core.formatDate2(new Date())+".h5save", JSON.stringify(content));
|
||||
}
|
||||
core.status.event.selection=2;
|
||||
core.ui.drawSyncSave();
|
||||
}
|
||||
|
||||
////// 存档下载界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownLocalSaveSelect = function (keycode) {
|
||||
if (keycode==38) {
|
||||
core.status.event.selection--;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
if (keycode==40) {
|
||||
core.status.event.selection++;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
}
|
||||
|
||||
////// 存档下载界面时,放开某个键的操作 //////
|
||||
events.prototype.keyUpLocalSaveSelect = function (keycode) {
|
||||
if (keycode==27 || keycode==88) {
|
||||
core.status.event.selection=0;
|
||||
core.ui.drawSettings();
|
||||
return;
|
||||
}
|
||||
var choices = core.status.event.ui.choices;
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
this.clickLocalSaveSelect(6, topIndex+core.status.event.selection);
|
||||
}
|
||||
}
|
||||
|
||||
////// “虚拟键盘”界面时的点击操作 //////
|
||||
events.prototype.clickKeyBoard = function (x, y) {
|
||||
if (y==3 && x>=1 && x<=11) {
|
||||
@ -1841,6 +2099,56 @@ events.prototype.clickKeyBoard = function (x, y) {
|
||||
core.ui.closePanel();
|
||||
}
|
||||
|
||||
////// 光标界面时的点击操作 //////
|
||||
events.prototype.clickCursor = function (x,y) {
|
||||
|
||||
if (x==core.status.automaticRoute.cursorX && y==core.status.automaticRoute.cursorY) {
|
||||
core.ui.closePanel();
|
||||
core.onclick(x,y,[]);
|
||||
return;
|
||||
}
|
||||
core.status.automaticRoute.cursorX=x;
|
||||
core.status.automaticRoute.cursorY=y;
|
||||
core.ui.drawCursor();
|
||||
}
|
||||
|
||||
////// 光标界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownCursor = function (keycode) {
|
||||
if (keycode==37) { // left
|
||||
core.status.automaticRoute.cursorX--;
|
||||
core.ui.drawCursor();
|
||||
return;
|
||||
}
|
||||
if (keycode==38) { // up
|
||||
core.status.automaticRoute.cursorY--;
|
||||
core.ui.drawCursor();
|
||||
return;
|
||||
}
|
||||
if (keycode==39) { // right
|
||||
core.status.automaticRoute.cursorX++;
|
||||
core.ui.drawCursor();
|
||||
return;
|
||||
}
|
||||
if (keycode==40) { // down
|
||||
core.status.automaticRoute.cursorY++;
|
||||
core.ui.drawCursor();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
////// 光标界面时,放开某个键的操作 //////
|
||||
events.prototype.keyUpCursor = function (keycode) {
|
||||
if (keycode==27 || keycode==88) {
|
||||
core.ui.closePanel();
|
||||
return;
|
||||
}
|
||||
if (keycode==13 || keycode==32 || keycode==67 || keycode==69) {
|
||||
core.ui.closePanel();
|
||||
core.onclick(core.status.automaticRoute.cursorX, core.status.automaticRoute.cursorY, []);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
////// “关于”界面时的点击操作 //////
|
||||
events.prototype.clickAbout = function () {
|
||||
if (core.isPlaying())
|
||||
|
||||
@ -8,8 +8,9 @@ main.floors.MT0 = {
|
||||
"canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
|
||||
"canUseQuickShop": true, // 该层是否允许使用快捷商店
|
||||
"defaultGround": "ground", // 默认地面的图块ID(terrains中)
|
||||
// "png": "bg.png", // 背景图;你可以选择一张png图片来作为背景素材。详细用法请参见文档“自定义素材”中的说明。
|
||||
"png": [], // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。
|
||||
// "color": [0,0,0,0.3], // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。
|
||||
// "weather": ["snow",5], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪,第二项为1-10之间的数代表强度。
|
||||
// "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。
|
||||
"map": [ // 地图数据,需要是13x13,建议使用地图生成器来生成
|
||||
|
||||
@ -31,6 +32,11 @@ main.floors.MT0 = {
|
||||
},
|
||||
"afterOpenDoor": { // 开完门后可能触发的事件列表
|
||||
|
||||
}
|
||||
},
|
||||
"cannotMove": { // 每个图块不可通行的方向
|
||||
// 可以在这里定义每个点不能前往哪个方向,例如悬崖边不能跳下去
|
||||
// "x,y": ["up", "left"], // (x,y)点不能往上和左走
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -8,8 +8,9 @@ main.floors.sample0 = {
|
||||
"canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
|
||||
"canUseQuickShop": true, // 该层是否允许使用快捷商店
|
||||
"defaultGround": "ground", // 默认地面的图块ID(terrains中)
|
||||
// "png": "bg.png", // 背景图;你可以选择一张png图片来作为背景素材。详细用法请参见文档“自定义素材”中的说明。
|
||||
"png": [], // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。
|
||||
// "color": [0,0,0,0.3] // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。
|
||||
// "weather": ["snow",5], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪,第二项为1-10之间的数代表强度。
|
||||
"bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。
|
||||
"map": [ // 地图数据,需要是13x13,建议使用地图生成器来生成
|
||||
[0, 0, 220, 0, 0, 20, 87, 3, 65, 64, 44, 43, 42],
|
||||
@ -28,17 +29,16 @@ main.floors.sample0 = {
|
||||
],
|
||||
"firstArrive": [ // 第一次到该楼层触发的事件
|
||||
"\t[样板提示]首次到达某层可以触发 firstArrive 事件,该事件可类似于RMXP中的“自动执行脚本”。\n\n本事件支持一切的事件类型,常常用来触发对话,例如:",
|
||||
"\t[hero]我是谁?我从哪来?我又要到哪去?",
|
||||
"\t[hero]\b[up,hero]我是谁?我从哪来?我又要到哪去?",
|
||||
"\t[仙子,fairy]你问我...?我也不知道啊...",
|
||||
"本层主要对道具、门、怪物等进行介绍,有关事件的各种信息在下一层会有更为详细的说明。",
|
||||
],
|
||||
"events": { // 该楼的所有可能事件列表
|
||||
|
||||
"10,9": [ // 守着道具的老人
|
||||
"\t[老人,man]这些是本样板支持的所有的道具。\n\n道具分为三类:items, constants, tools。\nitems 为即捡即用类道具,例如宝石、血瓶、剑盾等。\nconstants 为永久道具,例如怪物手册、楼层传送器、幸运金币等。\ntools 为消耗类道具,例如破墙镐、炸弹、中心对称飞行器等。\n\n后两类道具在工具栏中可以看到并使用。",
|
||||
"\t[老人,man]有关道具效果,定义在items.js中。\n目前大多数道具已有默认行为,如有自定义的需求则需在items.js中修改代码。",
|
||||
"\t[老人,man]\b[up]有关道具效果,定义在items.js中。\n目前大多数道具已有默认行为,如有自定义的需求则需在items.js中修改代码。",
|
||||
"\t[老人,man]constants 和 tools 各最多只允许12种,多了会导致图标溢出。",
|
||||
"\t[老人,man]拾取道具结束后可触发 afterGetItem 事件。\n\n有关事件的各种信息在下一层会有更为详细的说明。",
|
||||
"\t[老人,man]\b[up]拾取道具结束后可触发 afterGetItem 事件。\n\n有关事件的各种信息在下一层会有更为详细的说明。",
|
||||
{"type": "hide", "time": 500} // 消失
|
||||
],
|
||||
"10,11": [ // 守着门的老人
|
||||
@ -76,6 +76,7 @@ main.floors.sample0 = {
|
||||
},
|
||||
},
|
||||
"changeFloor": { // 楼层转换事件;该事件不能和上面的events有冲突(同位置点),否则会被覆盖
|
||||
"7,9": {"floorId": "sample1", "stair": "downFloor"},
|
||||
"6,0": {"floorId": "sample1", "stair": "downFloor"}, // 目标点:sample1层的下楼梯位置
|
||||
"0,11": {"floorId": "sample0", "loc": [0,12]}, // 目标点:sample0层的x=0,y=12位置
|
||||
"0,12": {"floorId": "sample0", "stair": "upFloor"}, // 注意,目标层有多个楼梯的话,写stair可能会导致到达位置不确定。这时候推荐写loc指明目标点位置。
|
||||
@ -83,11 +84,11 @@ main.floors.sample0 = {
|
||||
"2,12": {"floorId": "sample0", "loc": [2,12]},
|
||||
"3,12": {"floorId": "sample0", "loc": [6,1], "direction": "up"}, // 切换楼层后勇士面对上方
|
||||
"4,12": {"floorId": "sample0", "loc": [0,9], "direction": "left", "time": 1000}, // 切换楼层后勇士面对左边,切换动画1000ms
|
||||
"5,12": {"floorId": "sample0", "loc": [6,10], "time": 0}, // time=0表示无切换时间
|
||||
"5,12": {"floorId": "sample0", "loc": [6,10], "time": 0, "portalWithoutTrigger": false}, // time=0表示无切换时间
|
||||
"6,12": {"floorId": "sample0", "loc": [10,10], "direction": "left", "time": 1000},
|
||||
},
|
||||
"afterBattle": { // 战斗后可能触发的事件列表
|
||||
"2,6": ["\t[ghostSkeleton]不可能,你怎么可能打败我!\n(一个打败怪物触发的事件)"]
|
||||
"2,6": ["\t[ghostSkeleton]不可能,你怎么可能打败我!\n(一个打败怪物触发的事件)"],
|
||||
},
|
||||
"afterGetItem": { // 获得道具后可能触发的事件列表
|
||||
"11,8": ["由于状态栏放不下,绿钥匙和铁门钥匙均视为tools,放入工具栏中。\n碰到绿门和铁门仍然会自动使用开门。"],
|
||||
@ -108,7 +109,12 @@ main.floors.sample0 = {
|
||||
},
|
||||
"afterOpenDoor": { // 开完门后可能触发的事件列表
|
||||
"11,12": ["你开了一个绿门,触发了一个afterOpenDoor事件"]
|
||||
}
|
||||
},
|
||||
"cannotMove": { // 每个图块不可通行的方向
|
||||
// 可以在这里定义每个点不能前往哪个方向,例如悬崖边不能跳下去
|
||||
// "x,y": ["up", "left"], // (x,y)点不能往上和左走
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -8,8 +8,9 @@ main.floors.sample1 = {
|
||||
"canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
|
||||
"canUseQuickShop": true, // 该层是否允许使用快捷商店
|
||||
"defaultGround": "grass", // 默认地面的图块ID(terrains中)
|
||||
"png": "bg.png", // 背景图;你可以选择一张png图片来作为背景素材。详细用法请参见文档“自定义素材”中的说明。
|
||||
"png": [[0,0,"bg"]], // // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。
|
||||
// "color": [0,0,0,0.3] // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。
|
||||
"weather": ["snow",6], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪,第二项为1-10之间的数代表强度。
|
||||
// "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。
|
||||
"map": [ // 地图数据,需要是13x13,建议使用地图生成器来生成
|
||||
[7, 131, 8, 152, 9, 130, 10, 152, 166, 165, 132, 165, 166],
|
||||
@ -34,8 +35,8 @@ main.floors.sample1 = {
|
||||
"4,10": [ // 走到中间时的提示
|
||||
"\t[样板提示]本层楼将会对各类事件进行介绍。",
|
||||
"左边是一个仿50层的陷阱做法,上方是商店、快捷商店的使用方法,右上是一个典型的杀怪开门的例子,右下是各类可能的NPC事件。",
|
||||
"本样板目前支持的事件列表大致有:\ntext: 显示一段文字(比如你现在正在看到的)\ntip: 左上角显示提示\nshow: 使一个事件有效(可见、可被交互)\nhide: 使一个事件失效(不可见、不可被交互)\ntrigger: 触发另一个地点的事件\nbattle: 强制和某怪物战斗\nopenDoor: 无需钥匙开门(例如机关门、暗墙)",
|
||||
"openShop: 打开一个全局商店\ndisableShop: 禁用一个全局商店\nchangeFloor: 传送勇士到某层某位置\nchangePos: 传送勇士到当层某位置;转向\nsetFg: 更改画面色调\nmove: 移动事件效果\nmoveHero: 移动勇士效果\nplayBgm: 播放某个背景音乐\npauseBgm: 暂停背景音乐\nresumeBgm: 恢复背景音乐的播放\nplaySound: 播放某个音频",
|
||||
"本样板目前支持的事件列表大致有:\ntext: 显示一段文字(比如你现在正在看到的)\ntip: 左上角显示提示\nshow: 使一个事件有效(可见、可被交互)\nhide: 使一个事件失效(不可见、不可被交互)\ntrigger: 触发另一个地点的事件\nanimate: 显示动画\nbattle: 强制和某怪物战斗\nopenDoor: 无需钥匙开门(例如机关门、暗墙)",
|
||||
"openShop: 打开一个全局商店\ndisableShop: 禁用一个全局商店\nchangeFloor: 传送勇士到某层某位置\nchangePos: 传送勇士到当层某位置;转向\nshowImage: 显示图片\nsetFg: 更改画面色调\nsetWeather: 更改天气\nmove: 移动事件效果\nmoveHero: 移动勇士效果\nplayBgm: 播放某个背景音乐\npauseBgm: 暂停背景音乐\nresumeBgm: 恢复背景音乐的播放\nplaySound: 播放某个音频",
|
||||
"if: 条件判断\nchoices: 提供选项\nsetValue: 设置勇士属性道具,或某个变量/flag\nupdate: 更新状态栏和地图显伤\nwin: 获得胜利(游戏通关)\nlose: 游戏失败\nsleep: 等待多少毫秒\nexit: 立刻结束当前事件\nrevisit: 立刻结束事件并重新触发\nfunction: 自定义JS脚本\n\n更多支持的事件还在编写中,欢迎您宝贵的意见。",
|
||||
"有关各事件的样例,可参见本层一些NPC的写法。\n所有事件样例本层都有介绍。\n\n一个自定义事件处理完后,需要调用{\"type\": \"hide\"}该事件才不会再次出现。",
|
||||
{"type": "hide"}
|
||||
@ -267,7 +268,7 @@ main.floors.sample1 = {
|
||||
value=parseInt(action.substring(6));
|
||||
}
|
||||
else {
|
||||
core.status.replay.replaying=false;
|
||||
core.stopReplay();
|
||||
core.drawTip("录像文件出错");
|
||||
return;
|
||||
}
|
||||
@ -320,6 +321,11 @@ main.floors.sample1 = {
|
||||
},
|
||||
"afterOpenDoor": { // 开完门后可能触发的事件列表
|
||||
|
||||
}
|
||||
},
|
||||
"cannotMove": { // 每个图块不可通行的方向
|
||||
// 可以在这里定义每个点不能前往哪个方向,例如悬崖边不能跳下去
|
||||
// "x,y": ["up", "left"], // (x,y)点不能往上和左走
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -8,8 +8,9 @@ main.floors.sample2 = {
|
||||
"canFlyTo": false, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
|
||||
"canUseQuickShop": true, // 该层是否允许使用快捷商店
|
||||
"defaultGround": "snowGround", // 默认地面的图块ID(terrains中)
|
||||
// "png": "bg.png", // 背景图;你可以选择一张png图片来作为背景素材。详细用法请参见文档“自定义素材”中的说明。
|
||||
"png": [], // // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。
|
||||
"color": [255,0,0,0.3], // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。
|
||||
"weather": ["rain",10], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪,第二项为1-10之间的数代表强度。
|
||||
"bgm": "qianjin.mid", // 到达该层后默认播放的BGM。本项可忽略。
|
||||
"map": [ // 地图数据,需要是13x13,建议使用地图生成器来生成
|
||||
[5, 5, 5, 5, 5, 5, 87, 5, 5, 5, 5, 5, 5],
|
||||
@ -27,8 +28,7 @@ main.floors.sample2 = {
|
||||
[5, 5, 5, 5, 5, 5, 88, 5, 5, 5, 5, 5, 5],
|
||||
],
|
||||
"firstArrive": [ // 第一次到该楼层触发的事件
|
||||
"\t[实战!]本楼将尝试复刻《宿命的旋律》40F剧情。",
|
||||
"由于暂不支持一些动画效果,例如雷电、振动、天气渲染等等,因此做出来的效果远远比不上原版。\n\n不过作为抛砖引玉,还是能展示一下H5的能力。\n(开音效食用更加)"
|
||||
"\t[实战!]本楼将尝试复刻《宿命的旋律》40F剧情。"
|
||||
],
|
||||
"events": { // 该楼的所有可能事件列表
|
||||
|
||||
@ -181,6 +181,7 @@ main.floors.sample2 = {
|
||||
{"type": "show", "loc": [8,3], "time": 500}, // 依次显示四个角的法师
|
||||
{"type": "sleep", "time": 500},
|
||||
"\t[blackMagician]感受绝望吧!冥顽不化的蠢货!",
|
||||
/*
|
||||
{"type": "hide", "loc": [4,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
|
||||
{"type": "show", "loc": [4,3], "time": 150},
|
||||
{"type": "hide", "loc": [4,6], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
|
||||
@ -189,8 +190,14 @@ main.floors.sample2 = {
|
||||
{"type": "show", "loc": [8,6], "time": 150},
|
||||
{"type": "hide", "loc": [8,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
|
||||
{"type": "show", "loc": [8,3], "time": 150},
|
||||
*/
|
||||
{"type": "animate", "name": "yongchang", "loc": [4,3]},
|
||||
{"type": "animate", "name": "yongchang", "loc": [4,6]},
|
||||
{"type": "animate", "name": "yongchang", "loc": [8,6]},
|
||||
{"type": "animate", "name": "yongchang", "loc": [8,3]},
|
||||
{"type": "sleep", "time": 200},
|
||||
{"type": "playSound", "name": "attack.ogg"}, // 播放攻击音效
|
||||
{"type": "animate", "name": "thunder", "loc": "hero"},
|
||||
{"type": "sleep", "time": 200},
|
||||
"\t[hero]唔……!!(吐血)",
|
||||
{"type": "playSound", "name": "item.ogg"},
|
||||
@ -266,6 +273,7 @@ main.floors.sample2 = {
|
||||
"\t[小妖精,fairy]别小瞧咱!咱好歹也是妖精族里实力数一数二的存在!",
|
||||
{"type": "playSound", "name": "item.ogg"},
|
||||
"\t[blackMagician]只会耍嘴皮子的恼人苍蝇!我倒要看看一块焦炭会不会说话!\n——招雷弹!!",
|
||||
/*
|
||||
{"type": "hide", "loc": [4,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
|
||||
{"type": "show", "loc": [4,3], "time": 150},
|
||||
{"type": "hide", "loc": [4,6], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
|
||||
@ -274,9 +282,17 @@ main.floors.sample2 = {
|
||||
{"type": "show", "loc": [8,6], "time": 150},
|
||||
{"type": "hide", "loc": [8,3], "time": 150}, // 由于没有动画效果,暂时使用“闪一下”表示
|
||||
{"type": "show", "loc": [8,3], "time": 150},
|
||||
*/
|
||||
{"type": "animate", "name": "yongchang", "loc": [4,3]},
|
||||
{"type": "animate", "name": "yongchang", "loc": [4,6]},
|
||||
{"type": "animate", "name": "yongchang", "loc": [8,6]},
|
||||
{"type": "animate", "name": "yongchang", "loc": [8,3]},
|
||||
{"type": "playSound", "name": "attack.ogg"}, // 播放攻击音效
|
||||
/*
|
||||
{"type": "hide", "loc": [6,6], "time": 150}, // 妖精也闪一下表示收到了伤害
|
||||
{"type": "show", "loc": [6,6], "time": 150}, // 妖精也闪一下表示收到了伤害
|
||||
*/
|
||||
{"type": "animate", "name": "thunder", "loc": [6,6]},
|
||||
{"type": "sleep", "time": 500}, // 等待500毫秒
|
||||
"\t[小妖精,fairy]切,这点伤痛跟他刚才经历的身心地狱相比根本就不算什么。",
|
||||
{"type": "playSound", "name": "item.ogg"},
|
||||
@ -385,6 +401,11 @@ main.floors.sample2 = {
|
||||
},
|
||||
"afterOpenDoor": { // 开完门后可能触发的事件列表
|
||||
|
||||
}
|
||||
},
|
||||
"cannotMove": { // 每个图块不可通行的方向
|
||||
// 可以在这里定义每个点不能前往哪个方向,例如悬崖边不能跳下去
|
||||
// "x,y": ["up", "left"], // (x,y)点不能往上和左走
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
47
libs/maps.js
47
libs/maps.js
@ -14,27 +14,7 @@ maps.prototype.loadFloor = function (floorId, map) {
|
||||
for (var i = 0; i < 13; i++) {
|
||||
for (var j = 0; j < 13; j++) {
|
||||
var block = this.getBlock(j, i, map[i][j]);
|
||||
if (core.isset(block.event)) {
|
||||
if (block.event.cls == 'enemys' && block.event.trigger==undefined) {
|
||||
block.event.trigger = 'battle';
|
||||
}
|
||||
if (block.event.cls == 'items' && block.event.trigger==undefined) {
|
||||
block.event.trigger = 'getItem';
|
||||
}
|
||||
if (block.event.noPass == undefined) {
|
||||
if (block.event.cls=='enemys' || block.event.cls=='terrains' || block.event.cls=='npcs') {
|
||||
block.event.noPass = true;
|
||||
}
|
||||
}
|
||||
if (block.event.animate == undefined) {
|
||||
if (block.event.cls=='enemys' || block.event.cls=='npcs') {
|
||||
block.event.animate = 2;
|
||||
}
|
||||
if (block.event.cls == 'animates') {
|
||||
block.event.animate = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.addInfo(block);
|
||||
this.addEvent(block,j,i,floor.events[j+","+i])
|
||||
this.addChangeFloor(block,j,i,floor.changeFloor[j+","+i]);
|
||||
if (core.isset(block.event)) blocks.push(block);
|
||||
@ -257,6 +237,31 @@ maps.prototype.getBlock = function (x, y, id) {
|
||||
return tmp;
|
||||
}
|
||||
|
||||
////// 添加一些信息到block上 //////
|
||||
maps.prototype.addInfo = function (block) {
|
||||
if (core.isset(block.event)) {
|
||||
if (block.event.cls == 'enemys' && block.event.trigger==undefined) {
|
||||
block.event.trigger = 'battle';
|
||||
}
|
||||
if (block.event.cls == 'items' && block.event.trigger==undefined) {
|
||||
block.event.trigger = 'getItem';
|
||||
}
|
||||
if (block.event.noPass == undefined) {
|
||||
if (block.event.cls=='enemys' || block.event.cls=='terrains' || block.event.cls=='npcs') {
|
||||
block.event.noPass = true;
|
||||
}
|
||||
}
|
||||
if (block.event.animate == undefined) {
|
||||
if (block.event.cls=='enemys' || block.event.cls=='npcs') {
|
||||
block.event.animate = 2;
|
||||
}
|
||||
if (block.event.cls == 'animates') {
|
||||
block.event.animate = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////// 向该楼层添加剧本的自定义事件 //////
|
||||
maps.prototype.addEvent = function (block, x, y, event) {
|
||||
if (!core.isset(event)) return;
|
||||
|
||||
1
libs/thirdparty/mid.min.js
vendored
Normal file
1
libs/thirdparty/mid.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
253
libs/ui.js
253
libs/ui.js
@ -15,7 +15,6 @@ main.instance.ui = new ui();
|
||||
////// 结束一切事件和绘制,关闭UI窗口,返回游戏进程 //////
|
||||
ui.prototype.closePanel = function () {
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.setBoxAnimate();
|
||||
core.clearMap('ui', 0, 0, 416, 416);
|
||||
core.setAlpha('ui', 1.0);
|
||||
core.unLockControl();
|
||||
@ -30,10 +29,11 @@ ui.prototype.drawTextBox = function(content) {
|
||||
|
||||
// 获得name, image, icon
|
||||
var id=null, name=null, image=null, icon=null;
|
||||
if (content.indexOf("\t[")==0) {
|
||||
if (content.indexOf("\t[")==0 || content.indexOf("\\t[")==0) {
|
||||
var index = content.indexOf("]");
|
||||
if (index>=0) {
|
||||
var str=content.substring(2, index);
|
||||
if (content.indexOf("\\t[")==0) str=content.substring(3, index);
|
||||
content=content.substring(index+1);
|
||||
var ss=str.split(",");
|
||||
if (ss.length==1) {
|
||||
@ -64,10 +64,55 @@ ui.prototype.drawTextBox = function(content) {
|
||||
}
|
||||
}
|
||||
|
||||
// 获得位置信息
|
||||
|
||||
var textAttribute = core.status.textAttribute || core.initStatus.textAttribute;
|
||||
|
||||
var position = textAttribute.position, px=null, py=null, ydelta=0;
|
||||
if (content.indexOf("\b[")==0 || content.indexOf("\\b[")==0) {
|
||||
var index = content.indexOf("]");
|
||||
if (index>=0) {
|
||||
var str = content.substring(2, index);
|
||||
if (content.indexOf("\\b[")==0) str = content.substring(3, index);
|
||||
content = content.substring(index + 1);
|
||||
|
||||
var ss=str.split(",");
|
||||
|
||||
if (ss[0]=='up' || ss[0]=='center' || ss[0]=='down') {
|
||||
position=ss[0];
|
||||
if (core.status.event.id=='action') {
|
||||
px = core.status.event.data.x;
|
||||
py = core.status.event.data.y;
|
||||
}
|
||||
|
||||
if (ss.length>=2) {
|
||||
if (ss[1]=='hero') {
|
||||
px=core.getHeroLoc('x');
|
||||
py=core.getHeroLoc('y');
|
||||
ydelta = core.material.icons.hero.height-32;
|
||||
}
|
||||
else if (ss.length>=3) {
|
||||
px=parseInt(ss[1]);
|
||||
py=parseInt(ss[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (ss.length==3) {
|
||||
px=parseInt(ss[1]);
|
||||
py=parseInt(ss[2]);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
content = core.replaceText(content);
|
||||
|
||||
var background = core.canvas.ui.createPattern(core.material.ground, "repeat");
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.clearMap('ui', 0, 0, 416, 416);
|
||||
|
||||
// var contents = content.split('\n');
|
||||
// var contents = core.splitLines('ui', content, );
|
||||
var left=10, right=416-2*left;
|
||||
@ -77,16 +122,74 @@ ui.prototype.drawTextBox = function(content) {
|
||||
var validWidth = right-(content_left-left)-13;
|
||||
var contents = core.splitLines("ui", content, validWidth, '16px Verdana');
|
||||
|
||||
var height = 416 - 10 - Math.min(416-24*(contents.length+1)-65, 250);
|
||||
var top = (416-height)/2, bottom = height;
|
||||
var height = 20 + 21*(contents.length+1) + (id=='hero'?core.material.icons.hero.height-10:core.isset(name)?32-10:0);
|
||||
|
||||
|
||||
var xoffset = 6, yoffset = 22;
|
||||
|
||||
var top;
|
||||
if (position=='center') {
|
||||
top = (416 - height) / 2;
|
||||
}
|
||||
else if (position=='up') {
|
||||
if (px==null || py==null) {
|
||||
top = 5;
|
||||
}
|
||||
else {
|
||||
top = 32 * py - height - ydelta - yoffset;
|
||||
}
|
||||
}
|
||||
else if (position=='down') {
|
||||
if (px==null || py==null) {
|
||||
top = 416 - height - 5;
|
||||
}
|
||||
else {
|
||||
top = 32 * py + 32 + yoffset;
|
||||
}
|
||||
}
|
||||
|
||||
// var left = 97, top = 64, right = 416 - 2 * left, bottom = 416 - 2 * top;
|
||||
core.setAlpha('ui', 0.85);
|
||||
core.fillRect('ui', left, top, right, bottom, '#000000');
|
||||
core.setAlpha('ui', 1);
|
||||
core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2);
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.setBoxAnimate();
|
||||
//core.setAlpha('ui', 0.85);
|
||||
core.setAlpha('ui', textAttribute.background[3]);
|
||||
core.setFillStyle('ui', core.arrayToRGB(textAttribute.background));
|
||||
core.setStrokeStyle('ui', '#FFFFFF');
|
||||
|
||||
|
||||
core.fillRect('ui', left, top, right, height);
|
||||
core.strokeRect('ui', left - 1, top - 1, right + 1, height + 1, '#FFFFFF', 2);
|
||||
|
||||
var xoffset = 6;
|
||||
|
||||
// draw triangle
|
||||
if (position=='up' && core.isset(px) && core.isset(py)) {
|
||||
core.canvas.ui.clearRect(32*px+xoffset, top+height-1, 32-2*xoffset, 2);
|
||||
core.canvas.ui.beginPath();
|
||||
core.canvas.ui.moveTo(32*px+xoffset-1, top+height-1);
|
||||
core.canvas.ui.lineTo(32*px+16, top+height+yoffset-2);
|
||||
core.canvas.ui.lineTo(32*px+32-xoffset+1, top+height-1);
|
||||
core.canvas.ui.moveTo(32*px+xoffset-1, top+height-1);
|
||||
core.canvas.ui.closePath();
|
||||
core.canvas.ui.fill();
|
||||
// core.canvas.ui.stroke();
|
||||
// core.drawLine('ui', 32*px+4+1, top+height+1, 32*px + 28-1, top+height+1, core.arrayToRGB(textAttribute.background), 3);
|
||||
core.drawLine('ui', 32*px+xoffset, top+height, 32*px+16, top+height+yoffset-2);
|
||||
core.drawLine('ui', 32*px+32-xoffset, top+height, 32*px+16, top+height+yoffset-2);
|
||||
}
|
||||
if (position=='down' && core.isset(px) && core.isset(py)) {
|
||||
core.canvas.ui.clearRect(32*px+xoffset, top-2, 32-2*xoffset, 3);
|
||||
core.canvas.ui.beginPath();
|
||||
core.canvas.ui.moveTo(32*px+xoffset-1, top+1);
|
||||
core.canvas.ui.lineTo(32*px+16-1, top-yoffset+2);
|
||||
core.canvas.ui.lineTo(32*px+32-xoffset-1, top+1);
|
||||
core.canvas.ui.moveTo(32*px+xoffset-1, top+1);
|
||||
core.canvas.ui.closePath();
|
||||
core.canvas.ui.fill();
|
||||
// core.canvas.ui.stroke();
|
||||
// core.drawLine('ui', 32*px+4+1, top+height+1, 32*px + 28-1, top+height+1, core.arrayToRGB(textAttribute.background), 3);
|
||||
core.drawLine('ui', 32*px+xoffset, top, 32*px+16, top-yoffset+2);
|
||||
core.drawLine('ui', 32*px+32-xoffset, top, 32*px+16, top-yoffset+2);
|
||||
}
|
||||
|
||||
|
||||
// 名称
|
||||
core.canvas.ui.textAlign = "left";
|
||||
@ -95,36 +198,42 @@ ui.prototype.drawTextBox = function(content) {
|
||||
if (core.isset(id)) {
|
||||
|
||||
content_top = top+57;
|
||||
core.setAlpha('ui', textAttribute.title[3]);
|
||||
core.setFillStyle('ui', core.arrayToRGB(textAttribute.title));
|
||||
core.setStrokeStyle('ui', core.arrayToRGB(textAttribute.title));
|
||||
|
||||
if (id == 'hero') {
|
||||
var heroHeight=core.material.icons.hero.height;
|
||||
core.strokeRect('ui', left + 15 - 1, top + 40 - 1, 34, heroHeight+2, '#FFD700', 2);
|
||||
core.fillText('ui', core.status.hero.name, content_left, top + 30, '#FFD700', 'bold 22px Verdana');
|
||||
core.strokeRect('ui', left + 15 - 1, top + 40 - 1, 34, heroHeight+2, null, 2);
|
||||
core.fillText('ui', core.status.hero.name, content_left, top + 30, null, 'bold 22px Verdana');
|
||||
core.clearMap('ui', left + 15, top + 40, 32, heroHeight);
|
||||
core.fillRect('ui', left + 15, top + 40, 32, heroHeight, background);
|
||||
var heroIcon = core.material.icons.hero['down'];
|
||||
core.canvas.ui.drawImage(core.material.images.hero, heroIcon.stop * 32, heroIcon.loc * heroHeight, 32, heroHeight, left+15, top+40, 32, heroHeight);
|
||||
}
|
||||
else {
|
||||
core.fillText('ui', name, content_left, top + 30, '#FFD700', 'bold 22px Verdana');
|
||||
core.fillText('ui', name, content_left, top + 30, null, 'bold 22px Verdana');
|
||||
if (core.isset(icon)) {
|
||||
core.strokeRect('ui', left + 15 - 1, top + 40 - 1, 34, 34, '#FFD700', 2);
|
||||
core.strokeRect('ui', left + 15 - 1, top + 40 - 1, 34, 34, null, 2);
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.status.boxAnimateObjs.push({
|
||||
'bgx': left + 15, 'bgy': top + 40, 'bgsize': 32,
|
||||
'image': image, 'x': left + 15, 'y': top + 40, 'icon': icon
|
||||
});
|
||||
core.setBoxAnimate();
|
||||
core.drawBoxAnimate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.setAlpha('ui', textAttribute.text[3]);
|
||||
core.setFillStyle('ui', core.arrayToRGB(textAttribute.text));
|
||||
|
||||
for (var i=0;i<contents.length;i++) {
|
||||
core.fillText('ui', contents[i], content_left, content_top, '#FFFFFF', '16px Verdana');
|
||||
content_top+=24;
|
||||
core.fillText('ui', contents[i], content_left, content_top, null, '16px Verdana');
|
||||
content_top+=21;
|
||||
}
|
||||
|
||||
core.fillText('ui', '<点击任意位置继续>', 270, top+height-13, '#CCCCCC', '13px Verdana');
|
||||
// core.fillText('ui', '<点击任意位置继续>', 270, top+height-13, '#CCCCCC', '13px Verdana');
|
||||
}
|
||||
|
||||
////// 绘制一个选项界面 //////
|
||||
@ -237,7 +346,7 @@ ui.prototype.drawChoices = function(content, choices) {
|
||||
'bgx': left + 15, 'bgy': top + 30, 'bgsize': 32,
|
||||
'image': image, 'x': left + 15, 'y': top + 30, 'icon': icon
|
||||
});
|
||||
core.setBoxAnimate();
|
||||
core.drawBoxAnimate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -369,6 +478,22 @@ ui.prototype.drawBattleAnimate = function(monsterId, callback) {
|
||||
var monster = core.material.enemys[monsterId];
|
||||
var mon_hp = monster.hp, mon_atk = monster.atk, mon_def = monster.def, mon_money=monster.money, mon_exp = monster.experience, mon_special=monster.special;
|
||||
|
||||
var initDamage = 0; // 战前伤害
|
||||
|
||||
// 吸血
|
||||
if (core.enemys.hasSpecial(mon_special, 11)) {
|
||||
var vampireDamage = hero_hp * monster.value;
|
||||
|
||||
// 如果有神圣盾免疫吸血等可以在这里写
|
||||
|
||||
vampireDamage = parseInt(vampireDamage);
|
||||
// 加到自身
|
||||
if (monster.add) // 如果加到自身
|
||||
mon_hp += vampireDamage;
|
||||
|
||||
initDamage += vampireDamage;
|
||||
}
|
||||
|
||||
hero_hp -= core.enemys.getExtraDamage(monster);
|
||||
|
||||
if (core.enemys.hasSpecial(mon_special, 10)) { // 模仿
|
||||
@ -388,16 +513,9 @@ ui.prototype.drawBattleAnimate = function(monsterId, callback) {
|
||||
if (core.enemys.hasSpecial(mon_special, 5)) turns=4;
|
||||
if (core.enemys.hasSpecial(mon_special, 6)) turns=1+(monster.n||4);
|
||||
|
||||
|
||||
// 初始伤害
|
||||
var initDamage = 0;
|
||||
if (core.enemys.hasSpecial(mon_special, 7)) initDamage+=parseInt(core.values.breakArmor * hero_def);
|
||||
if (core.enemys.hasSpecial(mon_special, 9)) initDamage+=parseInt(core.values.purify * hero_mdef);
|
||||
if (core.enemys.hasSpecial(mon_special, 11)) { // 吸血
|
||||
var extraDamage = monster.value * hero_hp;
|
||||
initDamage+=parseInt(extraDamage);
|
||||
}
|
||||
if (core.enemys.hasSpecial(mon_special, 17)) initDamage+=core.getFlag('hatred', 0);
|
||||
hero_mdef-=initDamage;
|
||||
if (hero_mdef<0) {
|
||||
hero_hp+=hero_mdef;
|
||||
@ -433,7 +551,6 @@ ui.prototype.drawBattleAnimate = function(monsterId, callback) {
|
||||
core.setAlpha('data', 1);
|
||||
core.setOpacity('data', 1);
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.setBoxAnimate();
|
||||
|
||||
var margin = 35;
|
||||
var boxWidth = 40;
|
||||
@ -464,7 +581,7 @@ ui.prototype.drawBattleAnimate = function(monsterId, callback) {
|
||||
'bgx': left + right - margin - 40, 'bgy': top+margin, 'bgsize': boxWidth,
|
||||
'image': core.material.images.enemys, 'x': left + right - margin - 40 + (boxWidth-32)/2, 'y': top + margin + (boxWidth-32)/2, 'icon': core.material.icons.enemys[monsterId]
|
||||
});
|
||||
core.setBoxAnimate();
|
||||
core.drawBoxAnimate();
|
||||
|
||||
var lineWidth = 80;
|
||||
|
||||
@ -627,7 +744,6 @@ ui.prototype.drawBattleAnimate = function(monsterId, callback) {
|
||||
// 战斗结束
|
||||
clearInterval(battleInterval);
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.setBoxAnimate();
|
||||
core.clearMap('ui', 0, 0, 416, 416);
|
||||
core.setAlpha('ui', 1.0);
|
||||
core.clearMap('data', 0, 0, 416, 416);
|
||||
@ -674,11 +790,27 @@ ui.prototype.drawSyncSave = function () {
|
||||
core.status.event.id = 'syncSave';
|
||||
|
||||
this.drawChoices(null, [
|
||||
"同步存档到服务器", "从服务器加载存档", "存档至本地文件", "从本地文件读档", "清空所有存档", "返回主菜单"
|
||||
"同步存档到服务器", "从服务器加载存档", "存档至本地文件", "从本地文件读档", "下载当前录像", "清空本地存档", "返回主菜单"
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
////// 绘制存档同步选择页面 //////
|
||||
ui.prototype.drawSyncSelect = function () {
|
||||
core.status.event.id = 'syncSelect';
|
||||
this.drawChoices(null, [
|
||||
"同步本地所有存档", "只同步最新单存档", "返回上级菜单"
|
||||
]);
|
||||
}
|
||||
|
||||
////// 绘制单存档界面 //////
|
||||
ui.prototype.drawLocalSaveSelect = function () {
|
||||
core.status.event.id = 'localSaveSelect';
|
||||
this.drawChoices(null, [
|
||||
"下载所有存档", "只下载最新单存档", "返回上级菜单"
|
||||
]);
|
||||
}
|
||||
|
||||
////// 绘制分页 //////
|
||||
ui.prototype.drawPagination = function (page, totalPage) {
|
||||
|
||||
@ -701,10 +833,34 @@ ui.prototype.drawPagination = function (page, totalPage) {
|
||||
|
||||
}
|
||||
|
||||
////// 绘制键盘光标 //////
|
||||
ui.prototype.drawCursor = function () {
|
||||
|
||||
if (!core.isset(core.status.automaticRoute.cursorX))
|
||||
core.status.automaticRoute.cursorX=core.getHeroLoc('x');
|
||||
if (core.status.automaticRoute.cursorX<0) core.status.automaticRoute.cursorX=0;
|
||||
if (core.status.automaticRoute.cursorX>12) core.status.automaticRoute.cursorX=12;
|
||||
if (!core.isset(core.status.automaticRoute.cursorY))
|
||||
core.status.automaticRoute.cursorY=core.getHeroLoc('y');
|
||||
if (core.status.automaticRoute.cursorY<0) core.status.automaticRoute.cursorY=0;
|
||||
if (core.status.automaticRoute.cursorY>12) core.status.automaticRoute.cursorY=12;
|
||||
|
||||
core.status.event.id = 'cursor';
|
||||
core.lockControl();
|
||||
|
||||
core.clearMap('ui', 0, 0, 416, 416);
|
||||
core.setAlpha('ui', 1);
|
||||
|
||||
var width = 4;
|
||||
core.strokeRect('ui', 32*core.status.automaticRoute.cursorX+width/2, 32*core.status.automaticRoute.cursorY+width/2,
|
||||
32-width, 32-width, '#FFD700', width);
|
||||
|
||||
}
|
||||
|
||||
////// 绘制怪物手册 //////
|
||||
ui.prototype.drawBook = function (index) {
|
||||
|
||||
var enemys = core.enemys.getCurrentEnemys();
|
||||
var enemys = core.enemys.getCurrentEnemys(core.floorIds[core.status.event.selection]);
|
||||
var background = core.canvas.ui.createPattern(core.material.ground, "repeat");
|
||||
|
||||
clearInterval(core.interval.tipAnimate);
|
||||
@ -814,13 +970,13 @@ ui.prototype.drawBook = function (index) {
|
||||
}
|
||||
|
||||
}
|
||||
core.setBoxAnimate();
|
||||
core.drawBoxAnimate();
|
||||
this.drawPagination(page, totalPage);
|
||||
}
|
||||
|
||||
////// 绘制怪物属性的详细信息 //////
|
||||
ui.prototype.drawBookDetail = function (index) {
|
||||
var enemys = core.enemys.getCurrentEnemys();
|
||||
var enemys = core.enemys.getCurrentEnemys(core.floorIds[core.status.event.selection]);
|
||||
if (enemys.length==0) return;
|
||||
if (index<0) index=0;
|
||||
if (index>=enemys.length) index=enemys.length-1;
|
||||
@ -1051,6 +1207,7 @@ ui.prototype.drawToolbox = function(index) {
|
||||
|
||||
// 退出
|
||||
core.canvas.ui.textAlign = 'center';
|
||||
core.fillText('ui', '删除道具', 370, 32,'#DDDDDD', 'bold 15px Verdana');
|
||||
core.fillText('ui', '返回游戏', 370, 403,'#DDDDDD', 'bold 15px Verdana');
|
||||
}
|
||||
|
||||
@ -1121,9 +1278,31 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, heroL
|
||||
|
||||
if (core.isset(core.floors[floorId].png)) {
|
||||
var png = core.floors[floorId].png;
|
||||
/*
|
||||
if (core.isset(core.material.images.pngs[png])) {
|
||||
core.canvas.ui.drawImage(core.material.images.pngs[png], x, y, size, size);
|
||||
}
|
||||
*/
|
||||
|
||||
var ratio = size/416;
|
||||
|
||||
if (typeof png == 'string') {
|
||||
if (core.isset(core.material.images.pngs[png])) {
|
||||
core.canvas.ui.drawImage(core.material.images.pngs[png], x, y, size, size);
|
||||
}
|
||||
}
|
||||
else if (png instanceof Array) {
|
||||
png.forEach(function (t) {
|
||||
if (t.length!=3) return;
|
||||
var dx=parseInt(t[0]), dy=parseInt(t[1]), p=t[2];
|
||||
if (core.isset(dx) && core.isset(dy) && core.isset(core.material.images.pngs[p])) {
|
||||
dx*=32; dy*=32;
|
||||
var image = core.material.images.pngs[p];
|
||||
core.canvas.ui.drawImage(image, x+dx*ratio, y+dy*ratio, Math.min(size-dx*ratio, ratio*image.width), Math.min(size-dy*ratio, ratio*image.height));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var mapArray = core.maps.getMapArray(blocks);
|
||||
@ -1212,9 +1391,10 @@ ui.prototype.drawAbout = function() {
|
||||
// 名称
|
||||
core.canvas.ui.textAlign = "left";
|
||||
core.fillText('ui', "HTML5 魔塔样板", text_start, top+35, "#FFD700", "bold 22px Verdana");
|
||||
core.fillText('ui', "作者: 艾之葵", text_start, top + 80, "#FFFFFF", "bold 17px Verdana");
|
||||
core.fillText('ui', 'HTML5魔塔交流群:539113091', text_start, top+112);
|
||||
// TODO: 写自己的“关于”页面
|
||||
core.fillText('ui', "版本: "+core.firstData.version, text_start, top + 80, "#FFFFFF", "bold 17px Verdana");
|
||||
core.fillText('ui', "作者: 艾之葵", text_start, top + 112);
|
||||
core.fillText('ui', 'HTML5魔塔交流群:539113091', text_start, top+112+32);
|
||||
// TODO: 写自己的“关于”页面,每次增加32像素即可
|
||||
}
|
||||
|
||||
////// 绘制帮助页面 //////
|
||||
@ -1229,6 +1409,7 @@ ui.prototype.drawHelp = function () {
|
||||
"[K] 打开/关闭快捷商店选择列表\n" +
|
||||
"[T] 打开/关闭工具栏\n" +
|
||||
"[ESC] 打开/关闭系统菜单\n" +
|
||||
"[E] 显示光标\n" +
|
||||
"[H] 打开帮助页面\n"+
|
||||
"[R] 回放\n"+
|
||||
"[SPACE] 轻按(仅在轻按开关打开时有效)\n" +
|
||||
|
||||
70
main.js
70
main.js
@ -2,7 +2,7 @@ function main() {
|
||||
|
||||
//------------------------ 用户修改内容 ------------------------//
|
||||
|
||||
this.version = "1.3.2"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。
|
||||
this.version = "1.4.1"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。
|
||||
|
||||
this.useCompress = false; // 是否使用压缩文件
|
||||
// 当你即将发布你的塔时,请使用“JS代码压缩工具”将所有js代码进行压缩,然后将这里的useCompress改为true。
|
||||
@ -12,10 +12,15 @@ function main() {
|
||||
this.floorIds = [ // 在这里按顺序放所有的楼层;其顺序直接影响到楼层传送器的顺序和上楼器/下楼器的顺序
|
||||
"sample0", "sample1", "sample2"
|
||||
];
|
||||
this.pngs = [ // 在此存放所有可能的背景图片;背景图片最好是416*416像素,其他分辨率会被强制缩放成416*416
|
||||
// 建议对于较大的图片,在网上使用在线的“图片压缩工具”来进行压缩,以节省流量
|
||||
// 有关使用自定义背景图,请参见文档的“自定义素材”说明
|
||||
"bg.png", // 依次向后添加
|
||||
this.pngs = [ // 在此存放所有可能使用的图片,只能是png格式,可以不写后缀名
|
||||
// 图片可以被作为背景图(的一部分),也可以直接用自定义事件进行显示。
|
||||
// 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
|
||||
// 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量
|
||||
"bg", // 依次向后添加
|
||||
];
|
||||
this.animates = [ // 在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名
|
||||
// 动画必须放在animates目录下;文件名不能使用中文,不能带空格或特殊字符
|
||||
"hand", "sword", "zone", "yongchang", // "jianji", "thunder" // 根据需求自行添加
|
||||
];
|
||||
this.bgms = [ // 在此存放所有的bgm,和文件名一致。第一项为默认播放项
|
||||
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
|
||||
@ -23,7 +28,7 @@ function main() {
|
||||
];
|
||||
this.sounds = [ // 在此存放所有的SE,和文件名一致
|
||||
// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好
|
||||
'floor.mp3', 'attack.ogg', 'door.ogg', 'item.ogg',
|
||||
'floor.mp3', 'attack.ogg', 'door.ogg', 'item.ogg', 'zone.ogg'
|
||||
];
|
||||
|
||||
//------------------------ 用户修改内容 END ------------------------//
|
||||
@ -95,6 +100,19 @@ function main() {
|
||||
'load': document.getElementById("img-load"),
|
||||
'settings': document.getElementById("img-settings")
|
||||
},
|
||||
'icons': {
|
||||
'book': null,
|
||||
'fly': null,
|
||||
'toolbox': null,
|
||||
'save': null,
|
||||
'load': null,
|
||||
'settings': null,
|
||||
'rewind': null, // 减速
|
||||
'forward': null, // 加速
|
||||
'play': null, // 播放
|
||||
'pause': null, // 暂停
|
||||
'stop': null, // 停止
|
||||
},
|
||||
'floor': document.getElementById('floor'),
|
||||
'lv': document.getElementById('lv'),
|
||||
'hp': document.getElementById('hp'),
|
||||
@ -122,6 +140,11 @@ main.prototype.init = function () {
|
||||
for (var i = 0; i < main.dom.gameCanvas.length; i++) {
|
||||
main.canvas[main.dom.gameCanvas[i].id] = main.dom.gameCanvas[i].getContext('2d');
|
||||
}
|
||||
Object.keys(this.statusBar.icons).forEach(function (t) {
|
||||
var image=new Image();
|
||||
image.src="images/"+t+".png";
|
||||
main.statusBar.icons[t] = image;
|
||||
})
|
||||
main.loaderJs(function () {
|
||||
var coreData = {};
|
||||
for (i = 0; i < main.loadList.length; i++) {
|
||||
@ -131,7 +154,11 @@ main.prototype.init = function () {
|
||||
coreData[name] = main[name];
|
||||
}
|
||||
main.loaderFloors(function() {
|
||||
main.core.init(main.dom, main.statusBar, main.canvas, main.images, main.pngs, main.bgms, main.sounds, main.floorIds, main.floors, coreData);
|
||||
["dom", "statusBar", "canvas", "images", "pngs",
|
||||
"animates", "bgms", "sounds", "floorIds", "floors"].forEach(function (t) {
|
||||
coreData[t] = main[t];
|
||||
})
|
||||
main.core.init(coreData);
|
||||
main.core.resize(main.dom.body.clientWidth, main.dom.body.clientHeight);
|
||||
})
|
||||
});
|
||||
@ -319,12 +346,23 @@ main.dom.data.ontouchend = function () {
|
||||
|
||||
////// 点击状态栏中的怪物手册时 //////
|
||||
main.statusBar.image.book.onclick = function () {
|
||||
if (core.isset(core.status.replay) && core.status.replay.replaying) {
|
||||
core.triggerReplay();
|
||||
return;
|
||||
}
|
||||
|
||||
if (main.core.isPlaying())
|
||||
main.core.openBook(true);
|
||||
}
|
||||
|
||||
////// 点击状态栏中的楼层传送器时 //////
|
||||
main.statusBar.image.fly.onclick = function () {
|
||||
|
||||
if (core.isset(core.status.replay) && core.status.replay.replaying) {
|
||||
core.stopReplay();
|
||||
return;
|
||||
}
|
||||
|
||||
if (main.core.isPlaying())
|
||||
main.core.useFly(true);
|
||||
}
|
||||
@ -343,12 +381,24 @@ main.statusBar.image.shop.onclick = function () {
|
||||
|
||||
////// 点击状态栏中的存档按钮时 //////
|
||||
main.statusBar.image.save.onclick = function () {
|
||||
|
||||
if (core.isset(core.status.replay) && core.status.replay.replaying) {
|
||||
core.rewindReplay();
|
||||
return;
|
||||
}
|
||||
|
||||
if (main.core.isPlaying())
|
||||
main.core.save(true);
|
||||
}
|
||||
|
||||
////// 点击状态栏中的读档按钮时 //////
|
||||
main.statusBar.image.load.onclick = function () {
|
||||
|
||||
if (core.isset(core.status.replay) && core.status.replay.replaying) {
|
||||
core.forwardReplay();
|
||||
return;
|
||||
}
|
||||
|
||||
if (main.core.isPlaying())
|
||||
main.core.load(true);
|
||||
}
|
||||
@ -384,7 +434,7 @@ main.dom.replayGame.onclick = function () {
|
||||
alert("存档和游戏不一致!");
|
||||
return;
|
||||
}
|
||||
if (obj.version!=core.firstData.version) {
|
||||
if (core.isset(obj.version) && obj.version!=core.firstData.version) {
|
||||
alert("游戏版本不一致!");
|
||||
return;
|
||||
}
|
||||
@ -397,8 +447,8 @@ main.dom.replayGame.onclick = function () {
|
||||
core.resetStatus(core.firstData.hero, obj.hard, core.firstData.floorId, null, core.initStatus.maps);
|
||||
core.events.setInitData(obj.hard);
|
||||
core.changeFloor(core.status.floorId, null, core.firstData.hero.loc, null, function() {
|
||||
core.setHeroMoveTriggerInterval();
|
||||
core.replay(core.decodeRoute(obj.route));
|
||||
//core.setHeroMoveTriggerInterval();
|
||||
core.startReplay(core.decodeRoute(obj.route));
|
||||
});
|
||||
}, function () {
|
||||
|
||||
|
||||
BIN
sounds/zone.ogg
Normal file
BIN
sounds/zone.ogg
Normal file
Binary file not shown.
38
styles.css
38
styles.css
@ -21,7 +21,7 @@
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
z-index: 13;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
#startPanel {
|
||||
@ -32,7 +32,7 @@
|
||||
left: 0;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
z-index: 9;
|
||||
z-index: 11;
|
||||
}
|
||||
|
||||
#startTop {
|
||||
@ -42,7 +42,7 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #000;
|
||||
z-index: 12;
|
||||
z-index: 14;
|
||||
}
|
||||
|
||||
#startTopProgressBar {
|
||||
@ -52,7 +52,7 @@
|
||||
position: absolute;
|
||||
top: 5%;
|
||||
background-color: #fff;
|
||||
z-index: 13;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
#startTopProgress {
|
||||
@ -67,7 +67,7 @@
|
||||
position: absolute;
|
||||
top: 8%;
|
||||
left: 5%;
|
||||
z-index: 13;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
#startBackground {
|
||||
@ -77,12 +77,12 @@
|
||||
height: 100%;
|
||||
width: auto;
|
||||
transform:translate(-50%,-50%);
|
||||
z-index: 10;
|
||||
z-index: 12;
|
||||
}
|
||||
|
||||
#startLogo {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
z-index: 12;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-left: auto;
|
||||
@ -95,7 +95,7 @@
|
||||
|
||||
#startTitle {
|
||||
position: absolute;
|
||||
z-index: 11;
|
||||
z-index: 13;
|
||||
}
|
||||
|
||||
#startButtonGroup {
|
||||
@ -106,7 +106,7 @@
|
||||
background-color: #000;
|
||||
opacity: 0.85;
|
||||
display: none;
|
||||
z-index: 10;
|
||||
z-index: 12;
|
||||
bottom: 0;
|
||||
margin-bottom: 7%;
|
||||
}
|
||||
@ -142,7 +142,7 @@
|
||||
display: none;
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
z-index: 8;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#logoLabel {
|
||||
@ -170,7 +170,7 @@
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
background: url(images/ground.png) repeat;
|
||||
z-index: 7;
|
||||
z-index: 9;
|
||||
display: none;
|
||||
}
|
||||
#statusBar .status{
|
||||
@ -199,7 +199,7 @@
|
||||
#toolBar {
|
||||
position: absolute;
|
||||
background: url(images/ground.png) repeat;
|
||||
z-index: 6;
|
||||
z-index: 8;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
@ -234,7 +234,7 @@ span#poison, span#weak, span#curse {
|
||||
}
|
||||
|
||||
#curtain {
|
||||
z-index: 5;
|
||||
z-index: 7;
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
background: #000000;
|
||||
@ -256,12 +256,20 @@ span#poison, span#weak, span#curse {
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
#ui {
|
||||
#animate {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
#weather {
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
#ui {
|
||||
z-index: 8;
|
||||
}
|
||||
|
||||
#data {
|
||||
z-index: 7;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.clearfix:before,
|
||||
|
||||
BIN
常用工具/Newtonsoft.Json.dll
Normal file
BIN
常用工具/Newtonsoft.Json.dll
Normal file
Binary file not shown.
BIN
常用工具/RM动画导出器.exe
Normal file
BIN
常用工具/RM动画导出器.exe
Normal file
Binary file not shown.
BIN
常用工具/rgss.dll
Normal file
BIN
常用工具/rgss.dll
Normal file
Binary file not shown.
BIN
常用工具/便捷PS工具.exe
BIN
常用工具/便捷PS工具.exe
Binary file not shown.
BIN
常用工具/地图生成器.exe
BIN
常用工具/地图生成器.exe
Binary file not shown.
@ -12,6 +12,7 @@
|
||||
[K] 打开/关闭快捷商店选择列表
|
||||
[T] 打开/关闭工具栏
|
||||
[ESC] 打开/关闭系统菜单
|
||||
[E] 显示光标
|
||||
[H] 打开帮助页面
|
||||
[R] 回放
|
||||
[SPACE] 轻按(仅在轻按开关打开时有效)
|
||||
|
||||
33
更新说明.txt
33
更新说明.txt
@ -1,4 +1,35 @@
|
||||
HTML5魔塔样板V1.3.2
|
||||
HTML5魔塔样板V1.4.1
|
||||
|
||||
改变图块(setBlock事件)。
|
||||
同一个点的多事件处理(做法详见文档)。
|
||||
地图中每个块的可通行方向控制(悬崖效果)。
|
||||
动画支持带旋转和翻转的帧。
|
||||
现在可以允许用户丢弃道具了(例如不会再使用的装备)。
|
||||
修复行走时按键会发生动画抖动问题。
|
||||
修复无法打开战斗动画的Bug。
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
HTML5魔塔样板V1.4
|
||||
|
||||
动画!动画!!动画!!!
|
||||
瞬间移动。
|
||||
支持天气系统,可以在剧本中设置默认天气。
|
||||
新增自定义事件-图片显示。
|
||||
同时可以在剧本中设定多个背景素材。
|
||||
剧情文本特性控制,人物的对话框效果。
|
||||
单存档同步到服务器,下载到文件和读取。
|
||||
键盘支持自动寻路操作。
|
||||
浏览地图模式下可以查看怪物数据。
|
||||
未成功打怪和开门则不自动存档。
|
||||
重新支持楼梯穿透。
|
||||
支持多结局,成绩将分开统计。
|
||||
重构全局动画、行走动画和行走检测,大幅提升性能。
|
||||
修复所有已知Bug。
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
HTML5魔塔样板V1.3.2
|
||||
|
||||
增加录像和回放功能。
|
||||
增加统计功能,现在能看到每部塔的游戏人数、通关人数和当前MAX了。
|
||||
|
||||
Loading…
Reference in New Issue
Block a user