Merge remote-tracking branch 'refs/remotes/ckcz123/master'

This commit is contained in:
YouWei Zhao 2018-02-12 15:37:14 +08:00
commit 922ba10c82
41 changed files with 2225 additions and 474 deletions

View File

@ -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

File diff suppressed because one or more lines are too long

1
animates/jianji.animate Normal file

File diff suppressed because one or more lines are too long

1
animates/sword.animate Normal file
View 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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
animates/zone.animate Normal file

File diff suppressed because one or more lines are too long

View File

@ -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 // 检查并执行领域、夹击、阻击事件

View File

@ -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的播放。

View File

@ -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 @@
![调试](./img/eventdebug.png)
### 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为可选项表示设置文字显示位置。只能为upcenter和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]} // 启用该点
]
}
```
### 获得圣水后变成墙
这个例子要求获得圣水时不前进(也就是不能走到圣水地方),然后把圣水位置变成墙。
因此需要我们需要覆盖系统triggergetItem并覆盖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:battletype:openDoor等来具体进行控制。
## 加点事件
打败怪物后可以进行加点。

View File

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

View File

@ -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为一个数组代表当前层所有作为背景素材的图片信息。
每一项为一个三元组分别为该背景素材的xy和图片名。其中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函数中。

View File

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

BIN
images/forward.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 B

BIN
images/pause.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

BIN
images/play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

BIN
images/rewind.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

BIN
images/stop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

View File

@ -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>

File diff suppressed because it is too large Load Diff

View File

@ -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, // 是否允许瞬间移动
}
}

View File

@ -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;

View File

@ -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())

View File

@ -8,8 +8,9 @@ main.floors.MT0 = {
"canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
"canUseQuickShop": true, // 该层是否允许使用快捷商店
"defaultGround": "ground", // 默认地面的图块IDterrains中
// "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)点不能往上和左走
},
}

View File

@ -8,8 +8,9 @@ main.floors.sample0 = {
"canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
"canUseQuickShop": true, // 该层是否允许使用快捷商店
"defaultGround": "ground", // 默认地面的图块IDterrains中
// "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)点不能往上和左走
},
}

View File

@ -8,8 +8,9 @@ main.floors.sample1 = {
"canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
"canUseQuickShop": true, // 该层是否允许使用快捷商店
"defaultGround": "grass", // 默认地面的图块IDterrains中
"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)点不能往上和左走
},
}

View File

@ -8,8 +8,9 @@ main.floors.sample2 = {
"canFlyTo": false, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器)
"canUseQuickShop": true, // 该层是否允许使用快捷商店
"defaultGround": "snowGround", // 默认地面的图块IDterrains中
// "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)点不能往上和左走
},
}

View File

@ -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

File diff suppressed because one or more lines are too long

View File

@ -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
View File

@ -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

Binary file not shown.

View File

@ -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,

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
常用工具/rgss.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -12,6 +12,7 @@
[K] 打开/关闭快捷商店选择列表
[T] 打开/关闭工具栏
[ESC] 打开/关闭系统菜单
[E] 显示光标
[H] 打开帮助页面
[R] 回放
[SPACE] 轻按(仅在轻按开关打开时有效)

View File

@ -1,4 +1,35 @@
HTML5魔塔样板V1.3.2
HTML5魔塔样板V1.4.1
改变图块setBlock事件
同一个点的多事件处理(做法详见文档)。
地图中每个块的可通行方向控制(悬崖效果)。
动画支持带旋转和翻转的帧。
现在可以允许用户丢弃道具了(例如不会再使用的装备)。
修复行走时按键会发生动画抖动问题。
修复无法打开战斗动画的Bug。
-----------------------------------------------------------------------
HTML5魔塔样板V1.4
动画!动画!!动画!!!
瞬间移动。
支持天气系统,可以在剧本中设置默认天气。
新增自定义事件-图片显示。
同时可以在剧本中设定多个背景素材。
剧情文本特性控制,人物的对话框效果。
单存档同步到服务器,下载到文件和读取。
键盘支持自动寻路操作。
浏览地图模式下可以查看怪物数据。
未成功打怪和开门则不自动存档。
重新支持楼梯穿透。
支持多结局,成绩将分开统计。
重构全局动画、行走动画和行走检测,大幅提升性能。
修复所有已知Bug。
-----------------------------------------------------------------------
HTML5魔塔样板V1.3.2
增加录像和回放功能。
增加统计功能现在能看到每部塔的游戏人数、通关人数和当前MAX了。