merge from origin:master
29
LICENSE.md
Normal file
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2018, Zhang Chen
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@ -45,6 +45,12 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏!
|
||||
|
||||
## 更新说明
|
||||
|
||||
### 2018.1.12 V1.3.1
|
||||
|
||||
* [x] 增加虚拟键盘
|
||||
* [x] 增加自动存档(回退),A键可快速读档
|
||||
* [x] 修复几处较为严重的Bug
|
||||
|
||||
### 2018.1.1 V1.3
|
||||
|
||||
* [x] 支持全键盘操作。
|
||||
|
||||
@ -93,6 +93,7 @@ core.setAutoHeroMove // 设置勇士的自动行走路线
|
||||
core.autoHeroMove // 让勇士开始自动行走
|
||||
core.setHeroMoveInterval // 设置行走的效果动画
|
||||
core.setHeroMoveTriggerInterval // 设置勇士行走过程中对事件的触发检测
|
||||
core.moveAction // 实际每一步的行走过程
|
||||
* core.turnHero(direction) // 设置勇士的方向(转向)
|
||||
core.canMoveHero // 勇士能否前往某方向
|
||||
core.moveHero // 让勇士开始移动
|
||||
@ -178,16 +179,21 @@ core.clone // 深拷贝一个对象
|
||||
core.formatDate // 格式化时间为字符串
|
||||
core.setTwoDigits // 两位数显示
|
||||
core.debug // 进入Debug模式,攻防血和钥匙都调成很高的数值
|
||||
core.replay // 开始回放
|
||||
core.checkStatus // 判断当前能否进入某个事件
|
||||
core.openBook // 点击怪物手册时的打开操作
|
||||
core.useFly // 点击楼层传送器时的打开操作
|
||||
core.openToolbox // 点击工具栏时的打开操作
|
||||
core.openQuickShop // 点击快捷商店时的打开操作
|
||||
core.save // 点击保存按钮时的打开操作
|
||||
core.load // 点击读取按钮时的打开操作
|
||||
core.openSettings // 点击设置按钮时的打开操作
|
||||
core.doSL // 实际进行存读档事件
|
||||
core.syncSave // 存档同步操作
|
||||
core.saveData // 存档到本地
|
||||
core.loadData // 从本地读档
|
||||
core.encodeRoute // 将路线压缩
|
||||
core.decodeRoute // 将路线解压缩
|
||||
* core.setStatus // 设置勇士属性
|
||||
* core.getStatus // 获得勇士属性
|
||||
core.getLvName // 获得某个等级的名称
|
||||
@ -260,6 +266,7 @@ core.events.changeLight // 改变亮灯(感叹号)的事件
|
||||
* core.events.afterLoadData // 读档事件后,载入事件前,可以执行的操作
|
||||
|
||||
// ------ 点击事件和键盘事件的处理 ------
|
||||
core.events.longClick // 长按
|
||||
core.events.keyDownCtrl // 按下Ctrl键时(快捷跳过对话)
|
||||
core.events.clickConfirmBox // 确认框界面时的点击操作
|
||||
core.events.keyUpConfirmBox // 确认框界面时,放开某个键的操作
|
||||
@ -295,6 +302,7 @@ core.events.keyUpSettings // 系统菜单栏界面时,放开某个键的操作
|
||||
core.events.clickSyncSave // 同步存档界面时的点击操作
|
||||
core.events.keyDownSyncSave // 同步存档界面时,按下某个键的操作
|
||||
core.events.keyUpSyncSave // 同步存档界面时,放开某个键的操作
|
||||
core.events.clickKeyBoard // 虚拟键盘界面时的点击操作
|
||||
core.events.clickAbout // “关于”界面时的点击操作
|
||||
```
|
||||
|
||||
|
||||
@ -142,10 +142,6 @@ floorId指定的是目标楼层的唯一标识符(ID)。
|
||||
|
||||
可以指定time,指定后切换动画时长为指定的数值。
|
||||
|
||||
楼梯和传送门默认可`"穿透"`。所谓穿透,就是当寻路穿过一个楼梯/传送门后,不会触发楼层传送事件,而是继续前进。通过系统Flag可以指定是否穿透,你也可以对每个传送点单独设置该项。
|
||||
|
||||

|
||||
|
||||
## 背景音乐
|
||||
|
||||
本塔支持BGM和SE的播放。
|
||||
@ -190,12 +186,14 @@ this.sounds = [ // 在此存放所有的SE,和文件名一致
|
||||
- **点任意块并拖动:** 指定寻路路线
|
||||
- **单击勇士:** 转向
|
||||
- **双击勇士:** 轻按(仅在轻按开关打开时有效)
|
||||
- **长按任意位置:** 打开虚拟键盘
|
||||
|
||||
键盘操作快捷键如下:
|
||||
|
||||
- **[CTRL]** 跳过对话
|
||||
- **[X]** 打开/关闭怪物手册
|
||||
- **[G]** 打开/关闭楼层传送器
|
||||
- **[A]** 读取自动存档
|
||||
- **[S/D]** 打开/关闭存/读档页面
|
||||
- **[K]** 打开/关闭快捷商店选择列表
|
||||
- **[T]** 打开/关闭工具栏
|
||||
|
||||
@ -465,6 +465,8 @@ direction为可选的,指定的话将使勇士的朝向变成该方向
|
||||
|
||||
time为可选的,指定的话将作为楼层切换动画的时间。
|
||||
|
||||
**time也可以置为0,如果为0则没有楼层切换动画。**
|
||||
|
||||
!> **changeFloor到达一个新的楼层,将不会执行firstArrive事件!如有需求请在到达点设置自定义事件,然后使用type: trigger立刻调用之。**
|
||||
|
||||
### changePos: 当前位置切换/勇士转向
|
||||
@ -844,8 +846,9 @@ events.prototype.addPoint = function (enemy) {
|
||||
全局商店定义在`data.js`中,找到shops一项。
|
||||
|
||||
``` js
|
||||
"shops": { // 定义全局商店(即快捷商店)
|
||||
"moneyShop1": { // 商店唯一ID
|
||||
"shops": [ // 定义全局商店(即快捷商店)
|
||||
{
|
||||
"id": "moneyShop1", // 商店唯一ID
|
||||
"name": "贪婪之神", // 商店名称(标题)
|
||||
"icon": "blueShop", // 商店图标,blueShop为蓝色商店,pinkShop为粉色商店
|
||||
"textInList": "1F金币商店", // 在快捷商店栏中显示的名称
|
||||
@ -870,7 +873,8 @@ events.prototype.addPoint = function (enemy) {
|
||||
// "status:hp+=2*(status:atk+status:def)" 将生命提升攻防和的数值的两倍
|
||||
]
|
||||
},
|
||||
"expShop1": { // 商店唯一ID
|
||||
{
|
||||
"id": "expShop1", // 商店唯一ID
|
||||
"name": "经验之神",
|
||||
"icon": "pinkShop",
|
||||
"textInList": "1F经验商店",
|
||||
@ -885,15 +889,15 @@ events.prototype.addPoint = function (enemy) {
|
||||
{"text": "攻击+5", "need": "30", "effect": "status:atk+=5"},
|
||||
{"text": "防御+5", "need": "30", "effect": "status:def+=5"},
|
||||
]
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
```
|
||||
|
||||
全局商店全部定义在`data.js`中的shops一项里。
|
||||
每个全局商店有一个唯一标识符(ID),然后是一系列对该商店的定义。
|
||||
全局商店全部定义在`data.js`中的shops一项里。商店以数组形式存放,每一个商店都是其中的一个对象。
|
||||
|
||||
- id 为商店的唯一标识符(ID),请确保任何两个商店的id都不相同
|
||||
- name 为商店的名称(打开商店后的标题)
|
||||
- icon 为商店的图标,blueShop为蓝色商店,pinkShop为粉色商店
|
||||
- icon 为商店的图标,在icons.js的npcs中定义。如woman可代表一个商人。
|
||||
- textInList 为其在快捷商店栏中显示的名称,如"3楼金币商店"等
|
||||
- use 为消耗的类型,是金币(money)还是经验(experience)。
|
||||
- need 是一个表达式,计算商店所需要用到的数值。
|
||||
|
||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
BIN
images/常用素材:如需使用请直接替换目录中的对应文件/animates0:经典.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
images/常用素材:如需使用请直接替换目录中的对应文件/animates1:旋转门.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 26 KiB |
BIN
images/常用素材:如需使用请直接替换目录中的对应文件/items1:方块宝石.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
images/常用素材:如需使用请直接替换目录中的对应文件/宝石1.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
images/常用素材:如需使用请直接替换目录中的对应文件/宝石2.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
images/常用素材:如需使用请直接替换目录中的对应文件/宝石3.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
images/常用素材:如需使用请直接替换目录中的对应文件/宝石4.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
images/常用素材:如需使用请直接替换目录中的对应文件/旋转机关门.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
@ -32,7 +32,7 @@
|
||||
<div id='startButtons'>
|
||||
<span class='startButton' id='playGame'>开始游戏</span>
|
||||
<span class='startButton' id='loadGame'>载入游戏</span>
|
||||
<span class='startButton' id='aboutGame'>关于本塔</span>
|
||||
<span class='startButton' id='replayGame'>录像回放</span>
|
||||
</div>
|
||||
<div id='levelChooseButtons'>
|
||||
<span class='startButton' id='easyLevel'>简单</span>
|
||||
|
||||
986
libs/core.js
25
libs/data.js
@ -6,7 +6,7 @@ data.prototype.init = function() {
|
||||
this.firstData = {
|
||||
"title": "魔塔样板", // 游戏名,将显示在标题页面以及切换楼层的界面中
|
||||
"name": "template", // 游戏的唯一英文标识符。由英文、数字、下划线组成,不能超过20个字符。
|
||||
"version": "Ver 1.0.0 (Beta)", // 当前游戏版本;版本不一致的存档不能通用。
|
||||
"version": "Ver 1.3.2", // 当前游戏版本;版本不一致的存档不能通用。
|
||||
"floorId": "sample0", // 初始楼层ID
|
||||
"hero": { // 勇士初始数据
|
||||
"name": "阳光", // 勇士名;可以改成喜欢的
|
||||
@ -32,17 +32,19 @@ data.prototype.init = function() {
|
||||
"poison": false, // 毒
|
||||
"weak": false, // 衰
|
||||
"curse": false, // 咒
|
||||
}
|
||||
},
|
||||
"steps": 0, // 行走步数统计
|
||||
},
|
||||
"startText": [ // 游戏开始前剧情。如果无剧情直接留一个空数组即可。
|
||||
"Hi,欢迎来到 HTML5 魔塔样板!\n\n本样板由艾之葵制作,可以让你在不会写任何代码\n的情况下也能做出属于自己的H5魔塔!",
|
||||
"这里游戏开始时的剧情。\n定义在data.js的startText处。\n\n你可以在这里写上自己的内容。",
|
||||
"赶快来试一试吧!"
|
||||
],
|
||||
"shops": { // 定义全局商店(即快捷商店)
|
||||
"moneyShop1": { // 商店唯一ID
|
||||
"shops": [ // 定义全局商店(即快捷商店)
|
||||
{
|
||||
"id": "moneyShop1", // 商店唯一ID
|
||||
"name": "贪婪之神", // 商店名称(标题)
|
||||
"icon": "blueShop", // 商店图标,blueShop为蓝色商店,pinkShop为粉色商店
|
||||
"icon": "blueShop", // 商店图标,在icons.js中的npc一项定义
|
||||
"textInList": "1F金币商店", // 在快捷商店栏中显示的名称
|
||||
"use": "money", // 商店所要使用的。只能是"money"或"experience"。
|
||||
"need": "20+10*times*(times+1)", // 商店需要的金币/经验数值;可以是一个表达式,以times作为参数计算。
|
||||
@ -65,7 +67,8 @@ data.prototype.init = function() {
|
||||
// "status:hp+=2*(status:atk+status:def)" 将生命提升攻防和的数值的两倍
|
||||
]
|
||||
},
|
||||
"expShop1": { // 商店唯一ID
|
||||
{
|
||||
"id": "expShop1", // 商店唯一ID
|
||||
"name": "经验之神",
|
||||
"icon": "pinkShop",
|
||||
"textInList": "1F经验商店",
|
||||
@ -80,8 +83,8 @@ data.prototype.init = function() {
|
||||
{"text": "攻击+5", "need": "30", "effect": "status:atk+=5"},
|
||||
{"text": "防御+5", "need": "30", "effect": "status:def+=5"},
|
||||
]
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"levelUp": [ // 经验升级所需要的数值,是一个数组
|
||||
{}, // 第一项为初始等级,可以简单留空,也可以写name
|
||||
|
||||
@ -94,7 +97,7 @@ data.prototype.init = function() {
|
||||
|
||||
// effect也允许写一个function,代表本次升级将会执行的操作
|
||||
{"need": 40, "effect": function () {
|
||||
core.drawText("恭喜升级!");
|
||||
core.insertAction("恭喜升级!");
|
||||
core.status.hero.hp *= 2;
|
||||
core.status.hero.atk += 100;
|
||||
core.status.hero.def += 100;
|
||||
@ -155,7 +158,7 @@ data.prototype.init = function() {
|
||||
"bigKeyIsBox": false, // 如果此项为true,则视为钥匙盒,红黄蓝钥匙+1;若为false,则视为大黄门钥匙
|
||||
/****** 怪物相关 ******/
|
||||
"enableNegativeDamage": true, // 是否支持负伤害(回血)
|
||||
"zoneSquare": false, // 领域类型。如果此项为true则为九宫格伤害,为false则为十字伤害
|
||||
"betweenAttackCeil": false, // 夹击方式是向上取整还是向下取整。如果此项为true则为向上取整,为false则为向下取整
|
||||
/****** 系统相关 ******/
|
||||
"startDirectly": false, // 点击“开始游戏”后是否立刻开始游戏而不显示难度选择界面
|
||||
"canOpenBattleAnimate": true, // 是否允许用户开启战斗过程;如果此项为false,则下面两项均强制视为false
|
||||
@ -164,8 +167,8 @@ data.prototype.init = function() {
|
||||
"displayEnemyDamage": true, // 是否地图怪物显伤;用户可以手动在菜单栏中开关
|
||||
"displayExtraDamage": false, // 是否地图高级显伤(领域、夹击等);用户可以手动在菜单栏中开关
|
||||
"enableGentleClick": true, // 是否允许轻触(获得面前物品)
|
||||
"portalWithoutTrigger": true, // 经过楼梯、传送门时是否能“穿透”。穿透的意思是,自动寻路得到的的路径中间经过了楼梯,行走时是否触发楼层转换事件
|
||||
"potionWhileRouting": false, // 寻路算法是否经过血瓶;如果该项为false,则寻路算法会自动尽量绕过血瓶
|
||||
"enableViewMaps": true, // 是否支持在菜单栏中查看所有楼层的地图
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -24,8 +24,8 @@ enemys.prototype.init = function () {
|
||||
'slimeMan': {'name': '影子战士', 'hp': 100, 'atk': 0, 'def': 0, 'money': 11, 'experience': 0, 'special': 10}, // 模仿怪的攻防设为0就好
|
||||
'bluePriest': {'name': '初级法师', 'hp': 100, 'atk': 120, 'def': 0, 'money': 3, 'experience': 0, 'special': 2, 'point': 1}, // 'point'可以在打败怪物后进行加点,详见文档说明。
|
||||
'redPriest': {'name': '高级法师', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'experience': 0, 'special': 0},
|
||||
'brownWizard': {'name': '初级巫师', 'hp': 100, 'atk': 120, 'def': 0, 'money': 16, 'experience': 0, 'special': 15, 'value': 100, 'zoneSquare': true}, // 领域怪需要加value表示领域伤害的数值;zoneSquare代表是否九宫格伤害
|
||||
'redWizard': {'name': '高级巫师', 'hp': 1000, 'atk': 1200, 'def': 0, 'money': 160, 'experience': 0, 'special': 15, 'value': 200, 'range': 2}, // range可选,代表领域伤害的范围;不加默认为1
|
||||
'brownWizard': {'name': '初级巫师', 'hp': 100, 'atk': 120, 'def': 0, 'money': 16, 'experience': 0, 'special': 15, 'value': 100, 'range': 2}, // 领域怪需要加value表示领域伤害的数值;range可选,代表领域伤害的范围;不加默认为1
|
||||
'redWizard': {'name': '高级巫师', 'hp': 1000, 'atk': 1200, 'def': 0, 'money': 160, 'experience': 0, 'special': 15, 'value': 200, 'zoneSquare': true}, // zoneSquare可选,代表是否九宫格伤害,true为是九宫格伤害,false或不设置为十字伤害
|
||||
'yellowGuard': {'name': '初级卫兵', 'hp': 100, 'atk': 120, 'def': 0, 'money': 10, 'experience': 0, 'special': 0},
|
||||
'blueGuard': {'name': '中级卫兵', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'experience': 0, 'special': 0},
|
||||
'redGuard': {'name': '高级卫兵', 'hp': 0, 'atk': 0, 'def': 0, 'money': 0, 'experience': 0, 'special': 0},
|
||||
@ -248,11 +248,11 @@ enemys.prototype.calDamage = function (hero_atk, hero_def, hero_mdef, mon_hp, mo
|
||||
if (this.hasSpecial(mon_special, 8)) counterDamage += parseInt(core.values.counterAttack * hero_atk);
|
||||
|
||||
// 先攻
|
||||
var damage = mon_special == 1 ? per_damage : 0;
|
||||
var damage = this.hasSpecial(mon_special, 1) ? per_damage : 0;
|
||||
// 破甲
|
||||
if (this.hasSpecial(mon_special, 7)) damage += parseInt(core.values.breakArmor * hero_def);
|
||||
// 净化
|
||||
if (this.hasSpecial(mon_special, 9)) damage = core.values.purify * hero_mdef;
|
||||
if (this.hasSpecial(mon_special, 9)) damage += core.values.purify * hero_mdef;
|
||||
|
||||
var turn = parseInt((mon_hp - 1) / (hero_atk - mon_def));
|
||||
var ans = damage + turn * per_damage + (turn + 1) * counterDamage;
|
||||
|
||||
541
libs/events.js
@ -6,6 +6,7 @@ function events() {
|
||||
events.prototype.init = function () {
|
||||
this.events = {
|
||||
'battle': function (data, core, callback) {
|
||||
core.autosave();
|
||||
core.battle(data.event.id, data.x, data.y);
|
||||
if (core.isset(callback))
|
||||
callback();
|
||||
@ -16,9 +17,11 @@ events.prototype.init = function () {
|
||||
callback();
|
||||
},
|
||||
'openDoor': function (data, core, callback) {
|
||||
core.openDoor(data.event.id, data.x, data.y, true);
|
||||
if (core.isset(callback))
|
||||
callback();
|
||||
core.autosave();
|
||||
core.openDoor(data.event.id, data.x, data.y, true, function () {
|
||||
if (core.isset(callback)) callback();
|
||||
core.replay();
|
||||
});
|
||||
},
|
||||
'changeFloor': function (data, core, callback) {
|
||||
var heroLoc = {};
|
||||
@ -27,7 +30,10 @@ events.prototype.init = function () {
|
||||
if (core.isset(data.event.data.direction))
|
||||
heroLoc.direction = data.event.data.direction;
|
||||
core.changeFloor(data.event.data.floorId, data.event.data.stair,
|
||||
heroLoc, data.event.data.time, callback);
|
||||
heroLoc, data.event.data.time, function () {
|
||||
if (core.isset(callback)) callback();
|
||||
core.replay();
|
||||
});
|
||||
},
|
||||
'passNet': function (data, core, callback) {
|
||||
core.events.passNet(data);
|
||||
@ -107,44 +113,136 @@ 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.waitHeroToStop(function() {
|
||||
core.removeGlobalAnimate(0,0,true);
|
||||
core.clearMap('all'); // 清空全地图
|
||||
core.drawText([
|
||||
"\t[结局2]恭喜通关!你的分数是${status:hp}。"
|
||||
"\t[恭喜通关]你的分数是${status:hp}。"
|
||||
], function () {
|
||||
core.restart();
|
||||
core.events.gameOver(true, replaying);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
////// 游戏失败事件 //////
|
||||
events.prototype.lose = function(reason) {
|
||||
core.ui.closePanel();
|
||||
var replaying = core.status.replay.replaying;
|
||||
core.status.replay.replaying=false;
|
||||
core.waitHeroToStop(function() {
|
||||
core.status.replay.replaying=false;
|
||||
core.drawText([
|
||||
"\t[结局1]你死了。\n如题。"
|
||||
], function () {
|
||||
core.restart();
|
||||
core.events.gameOver(false, replaying);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
////// 游戏结束 //////
|
||||
events.prototype.gameOver = function (success, fromReplay) {
|
||||
|
||||
// 上传成绩
|
||||
var confirmUpload = function () {
|
||||
|
||||
if (!success) {
|
||||
core.restart();
|
||||
return;
|
||||
}
|
||||
|
||||
var doUpload = function(username) {
|
||||
if (username==null) username="";
|
||||
|
||||
// upload
|
||||
var formData = new FormData();
|
||||
formData.append('type', 'score');
|
||||
formData.append('name', core.firstData.name);
|
||||
formData.append('version', core.firstData.version);
|
||||
formData.append('platform', core.platform.isPC?"PC":core.platform.isAndroid?"Android":core.platform.isIOS?"iOS":"");
|
||||
formData.append('hard', core.status.hard);
|
||||
formData.append('username', username);
|
||||
formData.append('lv', core.status.hero.lv);
|
||||
formData.append('hp', core.status.hero.hp);
|
||||
formData.append('atk', core.status.hero.atk);
|
||||
formData.append('def', core.status.hero.def);
|
||||
formData.append('mdef', core.status.hero.mdef);
|
||||
formData.append('money', core.status.hero.money);
|
||||
formData.append('experience', core.status.hero.experience);
|
||||
formData.append('steps', core.status.hero.steps);
|
||||
formData.append('route', core.encodeRoute(core.status.route));
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "/games/upload.php");
|
||||
xhr.send(formData);
|
||||
|
||||
core.restart();
|
||||
}
|
||||
|
||||
core.ui.drawConfirmBox("你想记录你的ID和成绩吗?", function () {
|
||||
doUpload(prompt("请输入你的ID:"));
|
||||
}, function () {
|
||||
doUpload("");
|
||||
})
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 下载录像
|
||||
var confirmDownload = function () {
|
||||
core.ui.closePanel();
|
||||
core.ui.drawConfirmBox("你想下载录像吗?", function () {
|
||||
var obj = {
|
||||
'name': core.firstData.name,
|
||||
'version': core.firstData.version,
|
||||
'hard': core.status.hard,
|
||||
'route': core.encodeRoute(core.status.route)
|
||||
}
|
||||
core.download(core.firstData.name+"_"+core.formatDate2(new Date())+".h5route", JSON.stringify(obj));
|
||||
confirmUpload();
|
||||
}, function () {
|
||||
confirmUpload();
|
||||
})
|
||||
}
|
||||
|
||||
if (fromReplay) {
|
||||
core.drawText("录像回放完毕!", function () {
|
||||
core.restart();
|
||||
});
|
||||
}
|
||||
else {
|
||||
confirmDownload();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////// 转换楼层结束的事件 //////
|
||||
events.prototype.afterChangeFloor = function (floorId) {
|
||||
if (!core.isset(core.status.event.id) && !core.hasFlag("visited_"+floorId)) {
|
||||
this.doEvents(core.floors[floorId].firstArrive);
|
||||
if (core.isset(core.status.event.id)) return; // 当前存在事件
|
||||
|
||||
if (!core.hasFlag("visited_"+floorId)) {
|
||||
this.doEvents(core.floors[floorId].firstArrive, null, null, function () {
|
||||
core.autosave();
|
||||
});
|
||||
core.setFlag("visited_"+floorId, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// 自动存档
|
||||
core.autosave();
|
||||
}
|
||||
|
||||
////// 开始执行一系列自定义事件 //////
|
||||
events.prototype.doEvents = function (list, x, y, callback) {
|
||||
if (!core.isset(list)) return;
|
||||
if (!(list instanceof Array)) {
|
||||
list = [list];
|
||||
}
|
||||
|
||||
// 停止勇士
|
||||
core.waitHeroToStop(function() {
|
||||
if (!core.isset(list)) return;
|
||||
if (!(list instanceof Array)) {
|
||||
list = [list];
|
||||
}
|
||||
core.lockControl();
|
||||
core.status.event = {'id': 'action', 'data': {
|
||||
'list': core.clone(list), 'x': x, 'y': y, 'callback': callback
|
||||
@ -165,6 +263,7 @@ events.prototype.doAction = function() {
|
||||
if (core.isset(core.status.event.data.callback))
|
||||
core.status.event.data.callback();
|
||||
core.ui.closePanel();
|
||||
core.replay();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -178,13 +277,20 @@ events.prototype.doAction = function() {
|
||||
// 如果是文字:显示
|
||||
if (typeof data == "string") {
|
||||
core.status.event.data.type='text';
|
||||
core.ui.drawTextBox(data);
|
||||
// 如果是正在回放中,不显示
|
||||
if (core.status.replay.replaying)
|
||||
core.events.doAction();
|
||||
else
|
||||
core.ui.drawTextBox(data);
|
||||
return;
|
||||
}
|
||||
core.status.event.data.type=data.type;
|
||||
switch (data.type) {
|
||||
case "text": // 文字/对话
|
||||
core.ui.drawTextBox(data.data);
|
||||
if (core.status.replay.isreplaying)
|
||||
core.events.doAction();
|
||||
else
|
||||
core.ui.drawTextBox(data.data);
|
||||
break;
|
||||
case "tip":
|
||||
core.drawTip(core.replaceText(data.text));
|
||||
@ -270,7 +376,12 @@ events.prototype.doAction = function() {
|
||||
this.doAction();
|
||||
break;
|
||||
case "openShop": // 打开一个全局商店
|
||||
core.events.openShop(data.id);
|
||||
if (core.status.replay.replaying) { // 正在播放录像,简单将visited置为true
|
||||
core.status.shops[data.id].visited=true;
|
||||
this.doAction();
|
||||
}
|
||||
else
|
||||
core.events.openShop(data.id);
|
||||
break;
|
||||
case "disableShop": // 禁用一个全局商店
|
||||
core.events.disableQuickShop(data.id);
|
||||
@ -351,13 +462,41 @@ events.prototype.doAction = function() {
|
||||
this.doAction();
|
||||
break;
|
||||
case "choices": // 提供选项
|
||||
if (core.status.replay.replaying) {
|
||||
if (core.status.replay.toReplay.length==0) { // 回放完毕
|
||||
core.status.replay.replaying=false;
|
||||
core.drawTip("录像回放完毕");
|
||||
}
|
||||
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)
|
||||
}
|
||||
else {
|
||||
core.status.replay.replaying=false;
|
||||
core.drawTip("录像文件出错");
|
||||
}
|
||||
}
|
||||
}
|
||||
core.ui.drawChoices(data.text, data.choices);
|
||||
break;
|
||||
case "win":
|
||||
core.events.win(data.reason);
|
||||
core.events.win(data.reason, function () {
|
||||
core.events.doAction();
|
||||
});
|
||||
break;
|
||||
case "lose":
|
||||
core.events.lose(data.reason);
|
||||
core.events.lose(data.reason, function () {
|
||||
core.events.doAction();
|
||||
});
|
||||
break;
|
||||
case "function":
|
||||
var func = data["function"];
|
||||
@ -401,12 +540,15 @@ events.prototype.doAction = function() {
|
||||
}
|
||||
|
||||
////// 往当前事件列表之前添加一个或多个事件 //////
|
||||
events.prototype.insertAction = function (action) {
|
||||
events.prototype.insertAction = function (action, x, y, callback) {
|
||||
if (core.status.event.id == null) {
|
||||
this.doEvents(action);
|
||||
this.doEvents(action, x, y, callback);
|
||||
}
|
||||
else {
|
||||
core.unshift(core.status.event.data.list, action)
|
||||
if (core.isset(x)) core.status.event.data.x=x;
|
||||
if (core.isset(y)) core.status.event.data.y=y;
|
||||
if (core.isset(callback)) core.status.event.data.callback=callback;
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,11 +565,15 @@ events.prototype.openShop = function(shopId, needVisited) {
|
||||
shop.visited = true;
|
||||
|
||||
var selection = core.status.event.selection;
|
||||
var actions = [];
|
||||
if (core.isset(core.status.event.data) && core.isset(core.status.event.data.actions))
|
||||
actions=core.status.event.data.actions;
|
||||
|
||||
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};
|
||||
core.status.event.data = {'id': shopId, 'shop': shop, 'actions': actions};
|
||||
core.status.event.selection = selection;
|
||||
|
||||
// 拼词
|
||||
@ -458,7 +604,7 @@ events.prototype.disableQuickShop = function (shopId) {
|
||||
}
|
||||
|
||||
////// 能否使用快捷商店 //////
|
||||
events.prototype.canUseQuickShop = function(shopIndex) {
|
||||
events.prototype.canUseQuickShop = function(shopId) {
|
||||
if (core.isset(core.floors[core.status.floorId].canUseQuickShop) && !core.isset(core.floors[core.status.floorId].canUseQuickShop))
|
||||
return '当前不能使用快捷商店。';
|
||||
|
||||
@ -696,6 +842,14 @@ events.prototype.afterLoadData = function(data) {
|
||||
/********** 点击事件、键盘事件 ************/
|
||||
/****************************************/
|
||||
|
||||
////// 长按 //////
|
||||
events.prototype.longClick = function () {
|
||||
core.waitHeroToStop(function () {
|
||||
// 绘制快捷键
|
||||
core.ui.drawKeyBoard();
|
||||
});
|
||||
}
|
||||
|
||||
////// 按下Ctrl键时(快捷跳过对话) //////
|
||||
events.prototype.keyDownCtrl = function () {
|
||||
if (core.status.event.id=='text') {
|
||||
@ -756,6 +910,8 @@ events.prototype.clickAction = function (x,y) {
|
||||
if (x >= 5 && x <= 7) {
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
// 选择
|
||||
core.status.route.push("choices:"+(y-topIndex));
|
||||
this.insertAction(choices[y-topIndex].action);
|
||||
this.doAction();
|
||||
}
|
||||
@ -771,12 +927,10 @@ events.prototype.keyDownAction = function (keycode) {
|
||||
if (choices.length>0) {
|
||||
if (keycode==38) {
|
||||
core.status.event.selection--;
|
||||
if (core.status.event.selection<0) core.status.event.selection=0;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
if (keycode==40) {
|
||||
core.status.event.selection++;
|
||||
if (core.status.event.selection>=choices.length) core.status.event.selection=choices.length-1;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
}
|
||||
@ -794,6 +948,7 @@ events.prototype.keyUpAction = function (keycode) {
|
||||
var choices = data.choices;
|
||||
if (choices.length>0) {
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
core.status.route.push("choices:"+core.status.event.selection);
|
||||
this.insertAction(choices[core.status.event.selection].action);
|
||||
this.doAction();
|
||||
}
|
||||
@ -870,6 +1025,7 @@ 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);
|
||||
core.ui.closePanel();
|
||||
}
|
||||
@ -892,6 +1048,38 @@ events.prototype.keyUpFly = function (keycode) {
|
||||
return;
|
||||
}
|
||||
|
||||
////// 查看地图界面时的点击操作 //////
|
||||
events.prototype.clickViewMaps = function (x,y) {
|
||||
if(y<=4) {
|
||||
core.ui.drawMaps(core.status.event.data+1);
|
||||
}
|
||||
else if (y>=8) {
|
||||
core.ui.drawMaps(core.status.event.data-1);
|
||||
}
|
||||
else {
|
||||
core.clearMap('data', 0, 0, 416, 416);
|
||||
core.setOpacity('data', 1);
|
||||
core.ui.closePanel();
|
||||
}
|
||||
}
|
||||
|
||||
////// 查看地图界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownViewMaps = function (keycode) {
|
||||
if (keycode==37 || keycode==38) core.ui.drawMaps(core.status.event.data+1);
|
||||
else if (keycode==39 || keycode==40) core.ui.drawMaps(core.status.event.data-1);
|
||||
return;
|
||||
}
|
||||
|
||||
////// 查看地图界面时,放开某个键的操作 //////
|
||||
events.prototype.keyUpViewMaps = function (keycode) {
|
||||
if (keycode==27 || keycode==88 || keycode==13 || keycode==32 || keycode==67) {
|
||||
core.clearMap('data', 0, 0, 416, 416);
|
||||
core.setOpacity('data', 1);
|
||||
core.ui.closePanel();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
////// 商店界面时的点击操作 //////
|
||||
events.prototype.clickShop = function(x,y) {
|
||||
var shop = core.status.event.data.shop;
|
||||
@ -899,6 +1087,9 @@ events.prototype.clickShop = function(x,y) {
|
||||
if (x >= 5 && x <= 7) {
|
||||
var topIndex = 6 - parseInt(choices.length / 2);
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
|
||||
core.status.event.selection=y-topIndex;
|
||||
|
||||
//this.insertAction(choices[y-topIndex].action);
|
||||
//this.doAction();
|
||||
var money = core.getStatus('money'), experience = core.getStatus('experience');
|
||||
@ -912,11 +1103,12 @@ events.prototype.clickShop = function(x,y) {
|
||||
|
||||
if (need > eval(use)) {
|
||||
core.drawTip("你的"+use_text+"不足");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
eval(use+'-='+need);
|
||||
core.status.event.data.actions.push(y-topIndex);
|
||||
|
||||
eval(use+'-='+need);
|
||||
core.setStatus('money', money);
|
||||
core.setStatus('experience', experience);
|
||||
|
||||
@ -930,27 +1122,29 @@ events.prototype.clickShop = function(x,y) {
|
||||
}
|
||||
// 离开
|
||||
else if (y==topIndex+choices.length) {
|
||||
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.boxAnimateObjs = [];
|
||||
core.setBoxAnimate();
|
||||
if (core.status.event.data.fromList)
|
||||
core.ui.drawQuickShop();
|
||||
else core.ui.closePanel();
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
////// 商店界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownShop = function (keycode) {
|
||||
var shop = core.status.event.data.shop;
|
||||
var choices = shop.choices;
|
||||
if (keycode==38) {
|
||||
core.status.event.selection--;
|
||||
if (core.status.event.selection<0) core.status.event.selection=0;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
if (keycode==40) {
|
||||
core.status.event.selection++;
|
||||
if (core.status.event.selection>choices.length) core.status.event.selection=choices.length;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
}
|
||||
@ -982,7 +1176,7 @@ events.prototype.clickQuickShop = function(x, y) {
|
||||
if (x >= 5 && x <= 7) {
|
||||
var topIndex = 6 - parseInt(keys.length / 2);
|
||||
if (y>=topIndex && y<topIndex+keys.length) {
|
||||
var reason = core.events.canUseQuickShop(y-topIndex);
|
||||
var reason = core.events.canUseQuickShop(keys[y - topIndex]);
|
||||
if (core.isset(reason)) {
|
||||
core.drawText(reason);
|
||||
return;
|
||||
@ -999,15 +1193,12 @@ events.prototype.clickQuickShop = function(x, y) {
|
||||
|
||||
////// 快捷商店界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownQuickShop = function (keycode) {
|
||||
var shopList = core.status.shops, keys = Object.keys(shopList);
|
||||
if (keycode==38) {
|
||||
core.status.event.selection--;
|
||||
if (core.status.event.selection<0) core.status.event.selection=0;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
if (keycode==40) {
|
||||
core.status.event.selection++;
|
||||
if (core.status.event.selection>keys.length) core.status.event.selection=keys.length;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
}
|
||||
@ -1141,13 +1332,17 @@ events.prototype.keyUpToolbox = function (keycode) {
|
||||
|
||||
////// 存读档界面时的点击操作 //////
|
||||
events.prototype.clickSL = function(x,y) {
|
||||
|
||||
var index=core.status.event.data;
|
||||
var page = parseInt(index/10), offset=index%10;
|
||||
|
||||
// 上一页
|
||||
if ((x == 3 || x == 4) && y == 12) {
|
||||
core.ui.drawSLPanel(core.status.event.data - 6);
|
||||
core.ui.drawSLPanel(10*(page-1)+offset);
|
||||
}
|
||||
// 下一页
|
||||
if ((x == 8 || x == 9) && y == 12) {
|
||||
core.ui.drawSLPanel(core.status.event.data + 6);
|
||||
core.ui.drawSLPanel(10*(page+1)+offset);
|
||||
}
|
||||
// 返回
|
||||
if (x>=10 && x<=12 && y==12) {
|
||||
@ -1158,50 +1353,77 @@ events.prototype.clickSL = function(x,y) {
|
||||
return;
|
||||
}
|
||||
|
||||
var page=parseInt((core.status.event.data-1)/6);
|
||||
var index=6*page+1;
|
||||
if (y>=1 && y<=4) {
|
||||
if (x>=1 && x<=3) core.doSL(index, core.status.event.id);
|
||||
if (x>=5 && x<=7) core.doSL(index+1, core.status.event.id);
|
||||
if (x>=9 && x<=11) core.doSL(index+2, core.status.event.id);
|
||||
if (x>=1 && x<=3) core.doSL("autoSave", core.status.event.id);
|
||||
if (x>=5 && x<=7) core.doSL(5*page+1, core.status.event.id);
|
||||
if (x>=9 && x<=11) core.doSL(5*page+2, core.status.event.id);
|
||||
}
|
||||
if (y>=7 && y<=10) {
|
||||
if (x>=1 && x<=3) core.doSL(index+3, core.status.event.id);
|
||||
if (x>=5 && x<=7) core.doSL(index+4, core.status.event.id);
|
||||
if (x>=9 && x<=11) core.doSL(index+5, core.status.event.id);
|
||||
if (x>=1 && x<=3) core.doSL(5*page+3, core.status.event.id);
|
||||
if (x>=5 && x<=7) core.doSL(5*page+4, core.status.event.id);
|
||||
if (x>=9 && x<=11) core.doSL(5*page+5, core.status.event.id);
|
||||
}
|
||||
}
|
||||
|
||||
////// 存读档界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownSL = function(keycode) {
|
||||
|
||||
var index=core.status.event.data;
|
||||
var page = parseInt(index/10), offset=index%10;
|
||||
|
||||
if (keycode==37) { // left
|
||||
core.ui.drawSLPanel(core.status.event.data - 1);
|
||||
if (offset==0) {
|
||||
core.ui.drawSLPanel(10*(page-1) + 5);
|
||||
}
|
||||
else {
|
||||
core.ui.drawSLPanel(index - 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (keycode==38) { // up
|
||||
core.ui.drawSLPanel(core.status.event.data - 3);
|
||||
if (offset<3) {
|
||||
core.ui.drawSLPanel(10*(page-1) + offset + 3);
|
||||
}
|
||||
else {
|
||||
core.ui.drawSLPanel(index - 3);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (keycode==39) { // right
|
||||
core.ui.drawSLPanel(core.status.event.data + 1);
|
||||
if (offset==5) {
|
||||
core.ui.drawSLPanel(10*(page+1)+1);
|
||||
}
|
||||
else {
|
||||
core.ui.drawSLPanel(index + 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (keycode==40) { // down
|
||||
core.ui.drawSLPanel(core.status.event.data + 3);
|
||||
if (offset>=3) {
|
||||
core.ui.drawSLPanel(10*(page+1) + offset - 3);
|
||||
}
|
||||
else {
|
||||
core.ui.drawSLPanel(index + 3);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (keycode==33) { // PAGEUP
|
||||
core.ui.drawSLPanel(core.status.event.data - 6);
|
||||
core.ui.drawSLPanel(10*(page-1) + offset);
|
||||
return;
|
||||
}
|
||||
if (keycode==34) { // PAGEDOWN
|
||||
core.ui.drawSLPanel(core.status.event.data + 6);
|
||||
core.ui.drawSLPanel(10*(page+1) + offset);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
////// 存读档界面时,放开某个键的操作 //////
|
||||
events.prototype.keyUpSL = function (keycode) {
|
||||
|
||||
var index=core.status.event.data;
|
||||
var page = parseInt(index/10), offset=index%10;
|
||||
|
||||
if (keycode==27 || keycode==88 || (core.status.event.id == 'save' && keycode==83) || (core.status.event.id == 'load' && keycode==68)) {
|
||||
core.ui.closePanel();
|
||||
if (!core.isPlaying()) {
|
||||
@ -1210,7 +1432,12 @@ events.prototype.keyUpSL = function (keycode) {
|
||||
return;
|
||||
}
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
core.doSL(core.status.event.data, core.status.event.id);
|
||||
if (offset==0) {
|
||||
core.doSL("autoSave", core.status.event.id);
|
||||
}
|
||||
else {
|
||||
core.doSL(5*page+offset, core.status.event.id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1219,7 +1446,7 @@ events.prototype.keyUpSL = function (keycode) {
|
||||
events.prototype.clickSwitchs = function (x,y) {
|
||||
if (x<5 || x>7) return;
|
||||
var choices = [
|
||||
"背景音乐", "背景音效", "战斗动画", "怪物显伤", "领域显伤", "返回主菜单"
|
||||
"背景音乐", "背景音效", "战斗动画", "怪物显伤", "领域显伤", "下载离线版本", "返回主菜单"
|
||||
];
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
@ -1262,8 +1489,11 @@ events.prototype.clickSwitchs = function (x,y) {
|
||||
core.ui.drawSwitchs();
|
||||
break;
|
||||
case 5:
|
||||
window.open(core.firstData.name+".zip", "_blank");
|
||||
break;
|
||||
case 6:
|
||||
core.status.event.selection=0;
|
||||
core.ui.drawSettings(false);
|
||||
core.ui.drawSettings();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1271,17 +1501,12 @@ events.prototype.clickSwitchs = function (x,y) {
|
||||
|
||||
////// 系统设置界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownSwitchs = function (keycode) {
|
||||
var choices = [
|
||||
"背景音乐", "背景音效", "战斗动画", "怪物显伤", "领域显伤", "返回主菜单"
|
||||
];
|
||||
if (keycode==38) {
|
||||
core.status.event.selection--;
|
||||
if (core.status.event.selection<0) core.status.event.selection=0;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
if (keycode==40) {
|
||||
core.status.event.selection++;
|
||||
if (core.status.event.selection>=choices.length) core.status.event.selection=choices.length-1;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
}
|
||||
@ -1290,11 +1515,11 @@ events.prototype.keyDownSwitchs = function (keycode) {
|
||||
events.prototype.keyUpSwitchs = function (keycode) {
|
||||
if (keycode==27 || keycode==88) {
|
||||
core.status.event.selection=0;
|
||||
core.ui.drawSettings(false);
|
||||
core.ui.drawSettings();
|
||||
return;
|
||||
}
|
||||
var choices = [
|
||||
"背景音乐", "背景音效", "战斗动画", "怪物显伤", "领域显伤", "返回主菜单"
|
||||
"背景音乐", "背景音效", "战斗动画", "怪物显伤", "领域显伤", "下载离线版本", "返回主菜单"
|
||||
];
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
@ -1307,7 +1532,7 @@ events.prototype.keyUpSwitchs = function (keycode) {
|
||||
events.prototype.clickSettings = function (x,y) {
|
||||
if (x<5 || x>7) return;
|
||||
var choices = [
|
||||
"系统设置", "快捷商店", "同步存档", "重新开始", "操作帮助", "关于本塔", "返回游戏"
|
||||
"系统设置", "快捷商店", "浏览地图", "同步存档", "重新开始", "数据统计", "操作帮助", "关于本塔", "返回游戏"
|
||||
];
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
@ -1323,26 +1548,80 @@ events.prototype.clickSettings = function (x,y) {
|
||||
core.ui.drawQuickShop();
|
||||
break;
|
||||
case 2:
|
||||
if (!core.flags.enableViewMaps) {
|
||||
core.drawTip("本塔不允许浏览地图!");
|
||||
}
|
||||
else {
|
||||
core.drawText("\t[系统提示]即将进入浏览地图模式。\n\n点击地图上半部分,或按[↑]键可查看前一张地图\n点击地图下半部分,或按[↓]键可查看后一张地图\n点击地图中间,或按[ESC]键可离开浏览地图模式", function () {
|
||||
core.ui.drawMaps(core.floorIds.indexOf(core.status.floorId));
|
||||
})
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
core.status.event.selection=0;
|
||||
core.ui.drawSyncSave();
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
core.status.event.selection=1;
|
||||
core.ui.drawConfirmBox("你确定要重新开始吗?", function () {
|
||||
core.ui.closePanel();
|
||||
core.restart();
|
||||
}, function () {
|
||||
core.status.event.selection=3;
|
||||
core.ui.drawSettings(false);
|
||||
core.ui.drawSettings();
|
||||
});
|
||||
break;
|
||||
case 4:
|
||||
core.ui.drawHelp();
|
||||
break;
|
||||
case 5:
|
||||
core.ui.drawAbout();
|
||||
core.ui.drawWaiting("正在拉取统计信息,请稍后...");
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append('type', 'getinfo');
|
||||
formData.append('name', core.firstData.name);
|
||||
formData.append('version', core.firstData.version);
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "/games/upload.php");
|
||||
|
||||
xhr.onload = function(e) {
|
||||
if (xhr.status==200) {
|
||||
var response = JSON.parse(xhr.response);
|
||||
if (response.code<0) {
|
||||
core.drawText("出错啦!\n无法拉取统计信息。\n错误原因:"+response.msg);
|
||||
}
|
||||
else {
|
||||
var text="\t[本塔统计信息]";
|
||||
var toAdd=false;
|
||||
response.data.forEach(function (t) {
|
||||
if (toAdd) text+="\n\n";
|
||||
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))+"打出。";
|
||||
}
|
||||
})
|
||||
core.drawText(text);
|
||||
}
|
||||
}
|
||||
else {
|
||||
core.drawText("出错啦!\n无法拉取统计信息。\n错误原因:HTTP "+xhr.status);
|
||||
}
|
||||
};
|
||||
xhr.ontimeout = function() {
|
||||
core.drawText("出错啦!\n无法拉取统计信息。\n错误原因:Timeout");
|
||||
}
|
||||
xhr.onerror = function() {
|
||||
core.drawText("出错啦!\n无法拉取统计信息。\n错误原因:XHR Error");
|
||||
}
|
||||
xhr.send(formData);
|
||||
break;
|
||||
case 6:
|
||||
core.ui.drawHelp();
|
||||
break;
|
||||
case 7:
|
||||
core.ui.drawAbout();
|
||||
break;
|
||||
case 8:
|
||||
core.ui.closePanel();
|
||||
break;
|
||||
}
|
||||
@ -1352,17 +1631,12 @@ events.prototype.clickSettings = function (x,y) {
|
||||
|
||||
////// 系统菜单栏界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownSettings = function (keycode) {
|
||||
var choices = [
|
||||
"系统设置", "快捷商店", "同步存档", "重新开始", "操作帮助", "关于本塔", "返回游戏"
|
||||
];
|
||||
if (keycode==38) {
|
||||
core.status.event.selection--;
|
||||
if (core.status.event.selection<0) core.status.event.selection=0;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
if (keycode==40) {
|
||||
core.status.event.selection++;
|
||||
if (core.status.event.selection>=choices.length) core.status.event.selection=choices.length-1;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
}
|
||||
@ -1374,7 +1648,7 @@ events.prototype.keyUpSettings = function (keycode) {
|
||||
return;
|
||||
}
|
||||
var choices = [
|
||||
"系统设置", "快捷商店", "同步存档", "重新开始", "操作帮助", "关于本塔", "返回游戏"
|
||||
"系统设置", "快捷商店", "浏览地图", "同步存档", "重新开始", "数据统计", "操作帮助", "关于本塔", "返回游戏"
|
||||
];
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
@ -1386,7 +1660,7 @@ events.prototype.keyUpSettings = function (keycode) {
|
||||
events.prototype.clickSyncSave = function (x,y) {
|
||||
if (x<5 || x>7) return;
|
||||
var choices = [
|
||||
"同步存档到服务器", "从服务器加载存档", "清空本地存档", "返回主菜单"
|
||||
"同步存档到服务器", "从服务器加载存档", "存档至本地文件", "从本地文件读档", "清空所有存档", "返回主菜单"
|
||||
];
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
if (y>=topIndex && y<topIndex+choices.length) {
|
||||
@ -1399,18 +1673,61 @@ events.prototype.clickSyncSave = function (x,y) {
|
||||
core.syncSave("load");
|
||||
break;
|
||||
case 2:
|
||||
var saves = [];
|
||||
for (var i=1;i<=150;i++) {
|
||||
var data = core.getLocalStorage("save"+i, null);
|
||||
if (core.isset(data)) {
|
||||
saves.push(data);
|
||||
}
|
||||
}
|
||||
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));
|
||||
break;
|
||||
case 3:
|
||||
core.readFile(function (obj) {
|
||||
if (obj.name!=core.firstData.name) {
|
||||
alert("存档和游戏不一致!");
|
||||
return;
|
||||
}
|
||||
if (obj.version!=core.firstData.version) {
|
||||
alert("游戏版本不一致!");
|
||||
return;
|
||||
}
|
||||
if (!core.isset(obj.data)) {
|
||||
alert("无效的存档!");
|
||||
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);
|
||||
}
|
||||
}
|
||||
core.drawText("读取成功!\n你的本地所有存档均已被覆盖。");
|
||||
}, function () {
|
||||
|
||||
});
|
||||
break;
|
||||
case 4:
|
||||
core.status.event.selection=1;
|
||||
core.ui.drawConfirmBox("你确定要清空所有本地存档吗?", function() {
|
||||
core.ui.drawConfirmBox("你确定要清空所有存档吗?", function() {
|
||||
localStorage.clear();
|
||||
core.drawText("\t[操作成功]你的本地所有存档已被清空。");
|
||||
core.drawText("\t[操作成功]你的所有存档已被清空。");
|
||||
}, function() {
|
||||
core.status.event.selection=2;
|
||||
core.ui.drawSyncSave(false);
|
||||
})
|
||||
break;
|
||||
case 3:
|
||||
core.status.event.selection=2;
|
||||
core.ui.drawSettings(false);
|
||||
case 5:
|
||||
core.status.event.selection=3;
|
||||
core.ui.drawSettings();
|
||||
break;
|
||||
|
||||
}
|
||||
@ -1420,17 +1737,12 @@ events.prototype.clickSyncSave = function (x,y) {
|
||||
|
||||
////// 同步存档界面时,按下某个键的操作 //////
|
||||
events.prototype.keyDownSyncSave = function (keycode) {
|
||||
var choices = [
|
||||
"同步存档到服务器", "从服务器加载存档", "清空本地存档", "返回主菜单"
|
||||
];
|
||||
if (keycode==38) {
|
||||
core.status.event.selection--;
|
||||
if (core.status.event.selection<0) core.status.event.selection=0;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
if (keycode==40) {
|
||||
core.status.event.selection++;
|
||||
if (core.status.event.selection>=choices.length) core.status.event.selection=choices.length-1;
|
||||
core.ui.drawChoices(core.status.event.ui.text, core.status.event.ui.choices);
|
||||
}
|
||||
}
|
||||
@ -1439,11 +1751,11 @@ events.prototype.keyDownSyncSave = function (keycode) {
|
||||
events.prototype.keyUpSyncSave = function (keycode) {
|
||||
if (keycode==27 || keycode==88) {
|
||||
core.status.event.selection=2;
|
||||
core.ui.drawSettings(false);
|
||||
core.ui.drawSettings();
|
||||
return;
|
||||
}
|
||||
var choices = [
|
||||
"同步存档到服务器", "从服务器加载存档", "清空本地存档", "返回主菜单"
|
||||
"同步存档到服务器", "从服务器加载存档", "存档至本地文件", "从本地文件读档", "清空所有存档", "返回主菜单"
|
||||
];
|
||||
if (keycode==13 || keycode==32 || keycode==67) {
|
||||
var topIndex = 6 - parseInt((choices.length - 1) / 2);
|
||||
@ -1451,6 +1763,65 @@ events.prototype.keyUpSyncSave = function (keycode) {
|
||||
}
|
||||
}
|
||||
|
||||
////// “虚拟键盘”界面时的点击操作 //////
|
||||
events.prototype.clickKeyBoard = function (x, y) {
|
||||
if (y==3 && x>=1 && x<=11) {
|
||||
core.ui.closePanel();
|
||||
core.keyUp(112+x-1); // F1-F12: 112-122
|
||||
}
|
||||
if (y==4 && x>=1 && x<=10) {
|
||||
core.ui.closePanel();
|
||||
core.keyUp(x==10?48:48+x); // 1-9: 49-57; 0: 48
|
||||
}
|
||||
// 字母
|
||||
var lines = [
|
||||
["Q","W","E","R","T","Y","U","I","O","P"],
|
||||
["A","S","D","F","G","H","J","K","L"],
|
||||
["Z","X","C","V","B","N","M"],
|
||||
];
|
||||
if (y==5 && x>=1 && x<=10) {
|
||||
core.ui.closePanel();
|
||||
core.keyUp(lines[0][x-1].charCodeAt(0));
|
||||
}
|
||||
if (y==6 && x>=1 && x<=9) {
|
||||
core.ui.closePanel();
|
||||
core.keyUp(lines[1][x-1].charCodeAt(0));
|
||||
}
|
||||
if (y==7 && x>=1 && x<=7) {
|
||||
core.ui.closePanel();
|
||||
core.keyUp(lines[2][x-1].charCodeAt(0));
|
||||
}
|
||||
if (y==8 && x>=1 && x<=11) {
|
||||
core.ui.closePanel();
|
||||
if (x==1) core.keyUp(189); // -
|
||||
if (x==2) core.keyUp(187); // =
|
||||
if (x==3) core.keyUp(219); // [
|
||||
if (x==4) core.keyUp(221); // ]
|
||||
if (x==5) core.keyUp(220); // \
|
||||
if (x==6) core.keyUp(186); // ;
|
||||
if (x==7) core.keyUp(222); // '
|
||||
if (x==8) core.keyUp(188); // ,
|
||||
if (x==9) core.keyUp(190); // .
|
||||
if (x==10) core.keyUp(191); // /
|
||||
if (x==11) core.keyUp(192); // `
|
||||
}
|
||||
if (y==9 && x>=1 && x<=10) {
|
||||
core.ui.closePanel();
|
||||
if (x==1) core.keyUp(27); // ESC
|
||||
if (x==2) core.keyUp(9); // TAB
|
||||
if (x==3) core.keyUp(20); // CAPS
|
||||
if (x==4) core.keyUp(16); // SHIFT
|
||||
if (x==5) core.keyUp(17); // CTRL
|
||||
if (x==6) core.keyUp(18); // ALT
|
||||
if (x==7) core.keyUp(32); // SPACE
|
||||
if (x==8) core.keyUp(8); // BACKSPACE
|
||||
if (x==9) core.keyUp(13); // ENTER
|
||||
if (x==10) core.keyUp(46); // DEL
|
||||
}
|
||||
if (y==10 && x>=9 && x<=11)
|
||||
core.ui.closePanel();
|
||||
}
|
||||
|
||||
////// “关于”界面时的点击操作 //////
|
||||
events.prototype.clickAbout = function () {
|
||||
if (core.isPlaying())
|
||||
|
||||
@ -50,7 +50,6 @@ main.floors.sample0 = {
|
||||
"\t[老人,womanMagician]这些是路障、楼梯、传送门。",
|
||||
"\t[老人,womanMagician]血网的伤害数值、中毒后每步伤害数值、衰弱时攻防下降的数值,都在 data.js 内定义。\n\n路障同样会尽量被自动寻路绕过。",
|
||||
"\t[老人,womanMagician]楼梯和传送门需要在changeFloor中定义目标楼层和位置,可参见样板里已有的的写法。",
|
||||
"\t[老人,womanMagician]楼梯和传送门是否可“穿透”,由data.js中的全局变量所决定,你也可以单独设置。\n穿透的意思是,自动寻路得到的路径中间经过了楼梯,行走时是否触发楼层转换事件。\n例如,下面的“下箭头”就是不能穿透的。",
|
||||
{"type": "hide", "time": 500}
|
||||
],
|
||||
"2,8": [ // 守着第一批怪物的老人
|
||||
@ -75,7 +74,6 @@ main.floors.sample0 = {
|
||||
{"type": "hide", "time": 500}
|
||||
]
|
||||
},
|
||||
|
||||
},
|
||||
"changeFloor": { // 楼层转换事件;该事件不能和上面的events有冲突(同位置点),否则会被覆盖
|
||||
"6,0": {"floorId": "sample1", "stair": "downFloor"}, // 目标点:sample1层的下楼梯位置
|
||||
@ -85,8 +83,8 @@ 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], "portalWithoutTrigger": false}, // 不能穿透
|
||||
"6,12": {"floorId": "sample0", "loc": [10,10], "direction": "left", "time": 1000, "portalWithoutTrigger": false},
|
||||
"5,12": {"floorId": "sample0", "loc": [6,10], "time": 0}, // time=0表示无切换时间
|
||||
"6,12": {"floorId": "sample0", "loc": [10,10], "direction": "left", "time": 1000},
|
||||
},
|
||||
"afterBattle": { // 战斗后可能触发的事件列表
|
||||
"2,6": ["\t[ghostSkeleton]不可能,你怎么可能打败我!\n(一个打败怪物触发的事件)"]
|
||||
|
||||
@ -14,23 +14,23 @@ icons.prototype.init = function () {
|
||||
'ground': 0,
|
||||
'grass': 1,
|
||||
'grass2': 2,
|
||||
'snowGround': 3,
|
||||
'ground2': 4,
|
||||
'ground3': 5,
|
||||
'ground4': 6,
|
||||
'sand': 7,
|
||||
'ground5': 8,
|
||||
'yellowWall2': 9,
|
||||
'whiteWall2': 10,
|
||||
'blueWall2': 11,
|
||||
'blockWall': 12,
|
||||
'grayWall': 13,
|
||||
'white': 14,
|
||||
'ground6': 15,
|
||||
'soil': 16,
|
||||
'yellowWall': 17,
|
||||
'whiteWall': 18,
|
||||
'blueWall': 19,
|
||||
'yellowWall': 3,
|
||||
'whiteWall': 4,
|
||||
'blueWall': 5,
|
||||
'snowGround': 6,
|
||||
'ground2': 7,
|
||||
'ground3': 8,
|
||||
'ground4': 9,
|
||||
'sand': 10,
|
||||
'ground5': 11,
|
||||
'yellowWall2': 12,
|
||||
'whiteWall2': 13,
|
||||
'blueWall2': 14,
|
||||
'blockWall': 15,
|
||||
'grayWall': 16,
|
||||
'white': 17,
|
||||
'ground6': 18,
|
||||
'soil': 19,
|
||||
'star': 20,
|
||||
'lava': 21,
|
||||
'ice': 22,
|
||||
|
||||
@ -143,8 +143,11 @@ items.prototype.getItemEffectTip = function(itemId) {
|
||||
}
|
||||
|
||||
////// 使用道具 //////
|
||||
items.prototype.useItem = function (itemId) {
|
||||
if (!this.canUseItem(itemId)) return;
|
||||
items.prototype.useItem = function (itemId, callback) {
|
||||
if (!this.canUseItem(itemId)) {
|
||||
if (core.isset(callback)) callback();
|
||||
return;
|
||||
}
|
||||
var itemCls = core.material.items[itemId].cls;
|
||||
|
||||
if (itemId=='book') core.ui.drawBook(0);
|
||||
@ -174,6 +177,7 @@ items.prototype.useItem = function (itemId) {
|
||||
// 上楼器/下楼器
|
||||
core.changeFloor(core.status.event.data.id, null, {'direction': core.status.hero.loc.direction, 'x': core.status.event.data.x, 'y': core.status.event.data.y}, null, function (){
|
||||
core.drawTip(core.material.items[itemId].name + "使用成功");
|
||||
core.replay();
|
||||
});
|
||||
}
|
||||
if (itemId == 'poisonWine') core.setFlag('poison', false);
|
||||
@ -193,11 +197,19 @@ items.prototype.useItem = function (itemId) {
|
||||
core.setFlag('curse', false);
|
||||
}
|
||||
core.updateStatusBar();
|
||||
|
||||
// 记录路线
|
||||
if (itemId!='book' && itemId!='fly') {
|
||||
core.status.route.push("item:"+itemId);
|
||||
}
|
||||
|
||||
// 道具使用完毕:删除
|
||||
if (itemCls=='tools')
|
||||
core.status.hero.items[itemCls][itemId]--;
|
||||
if (core.status.hero.items[itemCls][itemId]==0)
|
||||
delete core.status.hero.items[itemCls][itemId];
|
||||
|
||||
if (core.isset(callback)) callback();
|
||||
}
|
||||
|
||||
////// 当前能否使用道具 //////
|
||||
|
||||
13
libs/maps.js
@ -356,16 +356,7 @@ maps.prototype.load = function (data, floorId) {
|
||||
}
|
||||
|
||||
////// 将当前地图重新变成二维数组形式 //////
|
||||
maps.prototype.getMapArray = function (maps, floorId){
|
||||
if (!core.isset(floorId)) {
|
||||
var map = {};
|
||||
for (var id in maps) {
|
||||
map[id] = this.getMapArray(maps, id);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
var thisFloor = maps[floorId];
|
||||
maps.prototype.getMapArray = function (blockArray){
|
||||
|
||||
var blocks = [];
|
||||
for (var x=0;x<13;x++) {
|
||||
@ -374,7 +365,7 @@ maps.prototype.getMapArray = function (maps, floorId){
|
||||
blocks[x].push(0);
|
||||
}
|
||||
}
|
||||
thisFloor.blocks.forEach(function (block) {
|
||||
blockArray.forEach(function (block) {
|
||||
if (!(core.isset(block.enable) && !block.enable))
|
||||
blocks[block.y][block.x] = block.id;
|
||||
});
|
||||
|
||||
136
libs/ui.js
@ -257,6 +257,8 @@ ui.prototype.drawChoices = function(content, choices) {
|
||||
|
||||
if (choices.length>0) {
|
||||
if (!core.isset(core.status.event.selection)) core.status.event.selection=0;
|
||||
if (core.status.event.selection<0) core.status.event.selection=0;
|
||||
if (core.status.event.selection>=choices.length) core.status.event.selection=choices.length-1;
|
||||
var len = core.canvas.ui.measureText(core.replaceText(choices[core.status.event.selection].text || choices[core.status.event.selection])).width;
|
||||
core.strokeRect('ui', 208-len/2-5, choice_top + 32 * core.status.event.selection - 20, len+10, 28, "#FFD700", 2);
|
||||
}
|
||||
@ -271,7 +273,8 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) {
|
||||
core.status.event.data = {'yes': yesCallback, 'no': noCallback};
|
||||
core.status.event.ui = text;
|
||||
|
||||
if (!core.isset(core.status.event.selection)) core.status.event.selection=1;
|
||||
if (!core.isset(core.status.event.selection) || core.status.event.selection>1) core.status.event.selection=1;
|
||||
if (core.status.event.selection<0) core.status.event.selection=0;
|
||||
|
||||
var background = core.canvas.ui.createPattern(core.material.ground, "repeat");
|
||||
core.clearMap('ui', 0, 0, 416, 416);
|
||||
@ -319,29 +322,26 @@ ui.prototype.drawSwitchs = function() {
|
||||
var choices = [
|
||||
"背景音乐:"+(core.musicStatus.bgmStatus ? "[ON]" : "[OFF]"),
|
||||
"背景音效:"+(core.musicStatus.soundStatus ? "[ON]" : "[OFF]"),
|
||||
"战斗动画: " + (core.flags.battleAnimate ? "[ON]" : "[OFF]"),
|
||||
"怪物显伤: " + (core.flags.displayEnemyDamage ? "[ON]" : "[OFF]"),
|
||||
"领域显伤: " + (core.flags.displayExtraDamage ? "[ON]" : "[OFF]"),
|
||||
"战斗动画: "+(core.flags.battleAnimate ? "[ON]" : "[OFF]"),
|
||||
"怪物显伤: "+(core.flags.displayEnemyDamage ? "[ON]" : "[OFF]"),
|
||||
"领域显伤: "+(core.flags.displayExtraDamage ? "[ON]" : "[OFF]"),
|
||||
"下载离线版本",
|
||||
"返回主菜单"
|
||||
];
|
||||
this.drawChoices(null, choices);
|
||||
|
||||
}
|
||||
|
||||
////// 绘制系统菜单栏 //////
|
||||
ui.prototype.drawSettings = function (need) {
|
||||
if (!core.checkStatus('settings', need))
|
||||
return;
|
||||
ui.prototype.drawSettings = function () {
|
||||
core.status.event.id = 'settings';
|
||||
|
||||
this.drawChoices(null, [
|
||||
"系统设置", "快捷商店", "同步存档", "重新开始", "操作帮助", "关于本塔", "返回游戏"
|
||||
"系统设置", "快捷商店", "浏览地图", "同步存档", "重新开始", "数据统计", "操作帮助", "关于本塔", "返回游戏"
|
||||
]);
|
||||
}
|
||||
|
||||
////// 绘制快捷商店选择栏 //////
|
||||
ui.prototype.drawQuickShop = function (need) {
|
||||
if (core.isset(need) && !core.checkStatus('selectShop', need))
|
||||
return;
|
||||
ui.prototype.drawQuickShop = function () {
|
||||
|
||||
core.status.event.id = 'selectShop';
|
||||
|
||||
@ -654,12 +654,17 @@ ui.prototype.drawWaiting = function(text) {
|
||||
core.setAlpha('ui', 1);
|
||||
core.setFillStyle('ui', background);
|
||||
|
||||
var left = 97, top = 208 - 32 - 16, right = 416 - 2 * left, bottom = 416 - 2 * top;
|
||||
core.setFont('ui', 'bold 17px Verdana');
|
||||
var text_length = core.canvas.ui.measureText(text).width;
|
||||
|
||||
var right = Math.max(text_length+50, 220);
|
||||
var left = 208-right/2, top = 208 - 32 - 16, bottom = 416 - 2 * top;
|
||||
|
||||
core.fillRect('ui', left, top, right, bottom, background);
|
||||
core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2);
|
||||
|
||||
core.canvas.ui.textAlign = "center";
|
||||
core.fillText('ui', text, 208, top + 56, "#FFFFFF", "bold 17px Verdana");
|
||||
core.fillText('ui', text, 208, top + 56, '#FFFFFF');
|
||||
|
||||
}
|
||||
|
||||
@ -669,7 +674,7 @@ ui.prototype.drawSyncSave = function () {
|
||||
core.status.event.id = 'syncSave';
|
||||
|
||||
this.drawChoices(null, [
|
||||
"同步存档到服务器", "从服务器加载存档", "清空本地存档", "返回主菜单"
|
||||
"同步存档到服务器", "从服务器加载存档", "存档至本地文件", "从本地文件读档", "清空所有存档", "返回主菜单"
|
||||
]);
|
||||
|
||||
}
|
||||
@ -902,6 +907,38 @@ ui.prototype.drawFly = function(page) {
|
||||
this.drawThumbnail(floorId, 'ui', core.status.maps[floorId].blocks, 20, 100, 273);
|
||||
}
|
||||
|
||||
////// 绘制浏览地图界面 //////
|
||||
ui.prototype.drawMaps = function (index) {
|
||||
if (!core.isset(index)) index=core.floorIds.indexOf(core.status.floorId);
|
||||
|
||||
if (index<0) index=0;
|
||||
if (index>=core.floorIds.length) index=core.floorIds.length-1;
|
||||
|
||||
core.lockControl();
|
||||
core.status.event.id = 'viewMaps';
|
||||
core.status.event.data = index;
|
||||
|
||||
var floorId = core.floorIds[index];
|
||||
|
||||
clearTimeout(core.interval.tipAnimate);
|
||||
|
||||
core.clearMap('ui', 0, 0, 416, 416);
|
||||
core.setAlpha('ui', 1);
|
||||
this.drawThumbnail(floorId, 'ui', core.status.maps[floorId].blocks, 0, 0, 416);
|
||||
|
||||
core.clearMap('data', 0, 0, 416, 416);
|
||||
core.setOpacity('data', 0.2);
|
||||
core.canvas.data.textAlign = 'left';
|
||||
core.setFont('data', '16px Arial');
|
||||
|
||||
var text = core.floors[floorId].title;
|
||||
var textX = 16, textY = 18, width = textX + core.canvas.data.measureText(text).width + 16, height = 42;
|
||||
core.fillRect('data', 5, 5, width, height, '#000');
|
||||
core.setOpacity('data', 0.5);
|
||||
core.fillText('data', text, textX + 5, textY + 15, '#fff');
|
||||
|
||||
}
|
||||
|
||||
////// 绘制道具栏 //////
|
||||
ui.prototype.drawToolbox = function(index) {
|
||||
|
||||
@ -1020,16 +1057,15 @@ ui.prototype.drawToolbox = function(index) {
|
||||
////// 绘制存档/读档界面 //////
|
||||
ui.prototype.drawSLPanel = function(index) {
|
||||
if (!core.isset(index)) index=1;
|
||||
if (index<=0) index=1;
|
||||
if (index>180) index=180;
|
||||
if (index<0) index=0;
|
||||
|
||||
var page = parseInt(index/10), offset=index%10;
|
||||
if (page>=30) page=29;
|
||||
if (offset>5) offset=5;
|
||||
index=10*page+offset;
|
||||
|
||||
core.status.event.data=index;
|
||||
|
||||
var page=parseInt((index-1)/6);
|
||||
|
||||
// core.status.event.data = page;
|
||||
// core.status.savePage = page;
|
||||
|
||||
core.clearMap('ui', 0, 0, 416, 416);
|
||||
core.setAlpha('ui', 0.85);
|
||||
core.fillRect('ui', 0, 0, 416, 416, '#000000');
|
||||
@ -1040,12 +1076,11 @@ ui.prototype.drawSLPanel = function(index) {
|
||||
|
||||
var name=core.status.event.id=='save'?"存档":"读档";
|
||||
for (var i=0;i<6;i++) {
|
||||
var id=6*page+i+1;
|
||||
var data=core.getLocalStorage("save"+id,null);
|
||||
|
||||
var id=5*page+i;
|
||||
var data=core.getLocalStorage(i==0?"autoSave":"save"+id, null);
|
||||
if (i<3) {
|
||||
core.fillText('ui', name+id, (2*i+1)*u, 35, '#FFFFFF', "bold 17px Verdana");
|
||||
core.strokeRect('ui', (2*i+1)*u-size/2, 50, size, size, id==index?'#FFD700':'#FFFFFF', id==index?6:2);
|
||||
core.fillText('ui', i==0?"自动存档":name+id, (2*i+1)*u, 35, '#FFFFFF', "bold 17px Verdana");
|
||||
core.strokeRect('ui', (2*i+1)*u-size/2, 50, size, size, i==offset?'#FFD700':'#FFFFFF', i==offset?6:2);
|
||||
if (core.isset(data) && core.isset(data.floorId)) {
|
||||
this.drawThumbnail(data.floorId, 'ui', core.maps.load(data.maps, data.floorId).blocks, (2*i+1)*u-size/2, 50, size, data.hero.loc);
|
||||
core.fillText('ui', core.formatDate(new Date(data.time)), (2*i+1)*u, 65+size, '#FFFFFF', '10px Verdana');
|
||||
@ -1057,7 +1092,7 @@ ui.prototype.drawSLPanel = function(index) {
|
||||
}
|
||||
else {
|
||||
core.fillText('ui', name+id, (2*i-5)*u, 230, '#FFFFFF', "bold 17px Verdana");
|
||||
core.strokeRect('ui', (2*i-5)*u-size/2, 245, size, size, id==index?'#FFD700':'#FFFFFF', id==index?6:2);
|
||||
core.strokeRect('ui', (2*i-5)*u-size/2, 245, size, size, i==offset?'#FFD700':'#FFFFFF', i==offset?6:2);
|
||||
if (core.isset(data) && core.isset(data.floorId)) {
|
||||
this.drawThumbnail(data.floorId, 'ui', core.maps.load(data.maps, data.floorId).blocks, (2*i-5)*u-size/2, 245, size, data.hero.loc);
|
||||
core.fillText('ui', core.formatDate(new Date(data.time)), (2*i-5)*u, 260+size, '#FFFFFF', '10px Verdana');
|
||||
@ -1091,7 +1126,7 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, heroL
|
||||
}
|
||||
}
|
||||
|
||||
var mapArray = core.maps.getMapArray(core.status.maps, floorId);
|
||||
var mapArray = core.maps.getMapArray(blocks);
|
||||
for (var b in blocks) {
|
||||
var block = blocks[b];
|
||||
if (core.isset(block.event) && !(core.isset(block.enable) && !block.enable)) {
|
||||
@ -1116,6 +1151,44 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, heroL
|
||||
}
|
||||
}
|
||||
|
||||
ui.prototype.drawKeyBoard = function () {
|
||||
core.lockControl();
|
||||
core.status.event.id = 'keyBoard';
|
||||
|
||||
core.clearMap('ui', 0, 0, 416, 416);
|
||||
|
||||
var left = 16, top = 48, right = 416 - 2 * left, bottom = 416 - 2 * top;
|
||||
var background = core.canvas.ui.createPattern(core.material.ground, "repeat");
|
||||
core.fillRect('ui', left, top, right, bottom, background);
|
||||
core.strokeRect('ui', left - 1, top - 1, right + 1, bottom + 1, '#FFFFFF', 2);
|
||||
|
||||
core.canvas.ui.textAlign = "center";
|
||||
core.fillText('ui', "虚拟键盘", 208, top+35, "#FFD700", "bold 22px Verdana");
|
||||
|
||||
core.setFont('ui', '17px Verdana');
|
||||
core.setFillStyle('ui', '#FFFFFF');
|
||||
var offset = 128-9;
|
||||
|
||||
var lines = [
|
||||
["F1","F2","F3","F4","F5","F6","F7","F8","F9","10","11"],
|
||||
["1","2","3","4","5","6","7","8","9","0"],
|
||||
["Q","W","E","R","T","Y","U","I","O","P"],
|
||||
["A","S","D","F","G","H","J","K","L"],
|
||||
["Z","X","C","V","B","N","M"],
|
||||
["-","=","[","]","\\",";","'",",",".","/","`"],
|
||||
["ES","TA","CA","SH","CT","AL","SP","BS","EN","DE"]
|
||||
]
|
||||
|
||||
lines.forEach(function (line) {
|
||||
for (var i=0;i<line.length;i++) {
|
||||
core.fillText('ui', line[i], 48+32*i, offset);
|
||||
}
|
||||
offset+=32;
|
||||
});
|
||||
|
||||
core.fillText("ui", "返回游戏", 416-80, offset-3, '#FFFFFF', 'bold 15px Verdana');
|
||||
}
|
||||
|
||||
////// 绘制“关于”界面 //////
|
||||
ui.prototype.drawAbout = function() {
|
||||
|
||||
@ -1151,11 +1224,13 @@ ui.prototype.drawHelp = function () {
|
||||
"[CTRL] 跳过对话\n" +
|
||||
"[X] 打开/关闭怪物手册\n" +
|
||||
"[G] 打开/关闭楼层传送器\n" +
|
||||
"[A] 读取自动存档(回退)\n" +
|
||||
"[S/D] 打开/关闭存/读档页面\n" +
|
||||
"[K] 打开/关闭快捷商店选择列表\n" +
|
||||
"[T] 打开/关闭工具栏\n" +
|
||||
"[ESC] 打开/关闭系统菜单\n" +
|
||||
"[H] 打开帮助页面\n"+
|
||||
"[R] 回放\n"+
|
||||
"[SPACE] 轻按(仅在轻按开关打开时有效)\n" +
|
||||
"[1] 快捷使用破墙镐\n" +
|
||||
"[2] 快捷使用炸弹/圣锤\n" +
|
||||
@ -1165,6 +1240,7 @@ ui.prototype.drawHelp = function () {
|
||||
"点任意块: 寻路并移动\n"+
|
||||
"点任意块并拖动: 指定寻路路线\n"+
|
||||
"单击勇士: 转向\n"+
|
||||
"双击勇士: 轻按(仅在轻按开关打开时有效)"
|
||||
"双击勇士: 轻按(仅在轻按开关打开时有效)\n"+
|
||||
"长按任意位置:打开虚拟键盘"
|
||||
]);
|
||||
}
|
||||
37
main.js
@ -2,7 +2,7 @@ function main() {
|
||||
|
||||
//------------------------ 用户修改内容 ------------------------//
|
||||
|
||||
this.version = "0.1"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。
|
||||
this.version = "1.3.2"; // 游戏版本号;如果更改了游戏内容建议修改此version以免造成缓存问题。
|
||||
|
||||
this.useCompress = false; // 是否使用压缩文件
|
||||
// 当你即将发布你的塔时,请使用“JS代码压缩工具”将所有js代码进行压缩,然后将这里的useCompress改为true。
|
||||
@ -53,7 +53,7 @@ function main() {
|
||||
'startButtons': document.getElementById('startButtons'),
|
||||
'playGame': document.getElementById('playGame'),
|
||||
'loadGame': document.getElementById('loadGame'),
|
||||
'aboutGame': document.getElementById('aboutGame'),
|
||||
'replayGame': document.getElementById('replayGame'),
|
||||
'levelChooseButtons': document.getElementById('levelChooseButtons'),
|
||||
'easyLevel': document.getElementById('easyLevel'),
|
||||
'normalLevel': document.getElementById('normalLevel'),
|
||||
@ -338,7 +338,7 @@ main.statusBar.image.toolbox.onclick = function () {
|
||||
////// 点击状态栏中的快捷商店时 //////
|
||||
main.statusBar.image.shop.onclick = function () {
|
||||
if (main.core.isPlaying())
|
||||
main.core.ui.drawQuickShop(true);
|
||||
main.core.openQuickShop(true);
|
||||
}
|
||||
|
||||
////// 点击状态栏中的存档按钮时 //////
|
||||
@ -356,7 +356,7 @@ main.statusBar.image.load.onclick = function () {
|
||||
////// 点击状态栏中的系统菜单时 //////
|
||||
main.statusBar.image.settings.onclick = function () {
|
||||
if (main.core.isPlaying())
|
||||
main.core.ui.drawSettings(true);
|
||||
main.core.openSettings(true);
|
||||
}
|
||||
|
||||
////// 点击“开始游戏”时 //////
|
||||
@ -377,8 +377,33 @@ main.dom.loadGame.onclick = function() {
|
||||
}
|
||||
|
||||
////// 点击“关于本塔”时 //////
|
||||
main.dom.aboutGame.onclick = function () {
|
||||
main.core.ui.drawAbout();
|
||||
main.dom.replayGame.onclick = function () {
|
||||
// main.core.ui.drawAbout();
|
||||
|
||||
core.readFile(function (obj) {
|
||||
if (obj.name!=core.firstData.name) {
|
||||
alert("存档和游戏不一致!");
|
||||
return;
|
||||
}
|
||||
if (obj.version!=core.firstData.version) {
|
||||
alert("游戏版本不一致!");
|
||||
return;
|
||||
}
|
||||
if (!core.isset(obj.route) || !core.isset(obj.hard)) {
|
||||
alert("无效的录像!");
|
||||
return;
|
||||
}
|
||||
|
||||
core.dom.startPanel.style.display = 'none';
|
||||
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));
|
||||
});
|
||||
}, function () {
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
////// 点击“简单难度”时 //////
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
margin-top: 8%;
|
||||
max-width: 100%;
|
||||
text-align: center;
|
||||
font: bold 4rem 华文行楷;
|
||||
font: bold 4rem STXingkai;
|
||||
}
|
||||
|
||||
#startTitle {
|
||||
@ -147,7 +147,7 @@
|
||||
|
||||
#logoLabel {
|
||||
margin-top: 8%;
|
||||
font: bold 3rem 华文行楷;
|
||||
font: bold 3rem STXingkai;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
@ -169,7 +169,7 @@
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
background: url(images/ground.png) round;
|
||||
background: url(images/ground.png) repeat;
|
||||
z-index: 7;
|
||||
display: none;
|
||||
}
|
||||
@ -198,7 +198,7 @@
|
||||
}
|
||||
#toolBar {
|
||||
position: absolute;
|
||||
background: url(images/ground.png) round;
|
||||
background: url(images/ground.png) repeat;
|
||||
z-index: 6;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
|
||||
@ -3,14 +3,17 @@
|
||||
=== 全局 ===
|
||||
[↑][↓][←][→] 移动勇士
|
||||
[CTRL] 跳过对话
|
||||
[Z] 转向
|
||||
[X] 打开/关闭怪物手册
|
||||
[G] 打开/关闭楼层传送器
|
||||
[A] 读取自动存档
|
||||
[S] 打开/关闭存档页面
|
||||
[D] 打开/关闭读档页面
|
||||
[K] 打开/关闭快捷商店选择列表
|
||||
[T] 打开/关闭工具栏
|
||||
[ESC] 打开/关闭系统菜单
|
||||
[H] 打开帮助页面
|
||||
[R] 回放
|
||||
[SPACE] 轻按(仅在轻按开关打开时有效)
|
||||
[1] 快捷使用破墙镐
|
||||
[2] 快捷使用炸弹/圣锤(先检测有没有炸弹,没有再检测圣锤)
|
||||
|
||||