From a58067cd6ae27e3515954f030c0232dd648adaf0 Mon Sep 17 00:00:00 2001 From: oc Date: Sun, 31 Dec 2017 01:35:21 +0800 Subject: [PATCH] Update V1.3 --- README.md | 19 ++- docs/api.md | 193 ++++++++++++++------- docs/element.md | 99 +++++++++-- docs/event.md | 159 +++++++++++++---- docs/img/domainenemy.png | Bin 22145 -> 0 bytes docs/img/nattack.png | Bin 0 -> 8523 bytes docs/img/ps.png | Bin 80216 -> 28629 bytes docs/img/zone.png | Bin 0 -> 13131 bytes docs/personalization.md | 134 +++++++-------- docs/start.md | 18 +- libs/core.js | 361 +++++++++++++++++++++++---------------- libs/enemys.js | 19 ++- libs/events.js | 198 +++++++++++---------- libs/floors/MT0.js | 2 + libs/floors/sample0.js | 2 + libs/floors/sample1.js | 2 + libs/floors/sample2.js | 3 +- libs/items.js | 15 +- libs/maps.js | 11 +- libs/ui.js | 84 +++------ 更新说明.txt | 1 + 21 files changed, 824 insertions(+), 496 deletions(-) delete mode 100644 docs/img/domainenemy.png create mode 100644 docs/img/nattack.png create mode 100644 docs/img/zone.png diff --git a/README.md b/README.md index bb72521e..36fb01bf 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,20 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! ## 更新说明 -### 2017.12.21 +### 2017.12.31 V1.3 + +* [x] 支持全键盘操作。 +* [x] 便捷PS工具支持更改图片色相。 +* [x] 支持经验升级(进阶/境界塔)。 +* [x] 打败怪物可以进行加点(加点塔)。 +* [x] 增加阻击、N连击等属性;在怪物手册有属性显示。 +* [x] 支持九宫格领域和大范围领域。 +* [x] 增加负伤。 +* [x] 支持各种BGM的播放。 +* [x] 支持不同层使用不同的地面素材;支持多个Autotile同时存在 √ +* [x] 许多细节进行了优化,一些已知的Bug进行了修复。 + +### 2017.12.21 V1.2 * [x] 新增:本地HTTP服务器。 * [x] 新增:可视化地图编辑工具。 @@ -57,7 +70,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! * [x] 新增:更多的默认素材,现在对于大多数地图风格无需P图,直接替换即可。 * [x] 添加部分自定义事件,部分细节优化,一些已知的Bug进行了修复。 -### 2017.12.16 +### 2017.12.16 V1.1 * [x] 新增:战斗过程显示,可以在设置中关闭 * [x] 新增:勇士支持48*32(大图)的行走图 @@ -67,7 +80,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! * [x] 增添Web的Markdown文档,移除原本的doc和pdf文档。 * [x] 修复若干Bug。 -### 2017.12.9 +### 2017.12.9 V1.0 * [x] 发布初版HTML5魔塔样板 diff --git a/docs/api.md b/docs/api.md index 51973cda..d1b609f4 100644 --- a/docs/api.md +++ b/docs/api.md @@ -4,32 +4,39 @@ 可以在chrome浏览器的控制台中(`ctrl+shift+I`,找到Console)中直接进行调用,以查看效果。 +!> **`main.js`:游戏入口。所有其他JS文件都是被此文件加载。** + +``` js + +``` + !> **`core.js`:系统核心文件。所有核心逻辑处理都在此文件完成。** ``` js * core.status.floorId // 获得当前层floorId * core.status.thisMap // 获得当前层的地图信息 +* core.status.maps // 获得所有楼层的地图信息 +* core.floors // 获得所有楼层的剧本 // ------ 初始化部分 ------ core.init // 初始化 -core.showStartAnimate // 显示开始界面 -core.hideStartAnimate // 隐藏开始界面 +core.showStartAnimate // 显示游戏开始界面 +core.hideStartAnimate // 隐藏游戏开始界面 core.setStartProgressVal // 设置加载进度条进度 core.setStartLoadTipText // 设置加载进度条提示文字 core.loader // 加载图片和音频 core.loadImage // 加载图片 -core.loadSound // 加载音频 -core.loadSoundItem // 加载某一个音频 +core.loadMusic // 加载音频 core.isPlaying // 游戏是否已经开始 core.clearStatus // 清除游戏状态和数据 core.resetStatus // 重置游戏状态和初始数据 -core.startGame // 具体开始游戏 +core.startGame // 开始游戏 * core.restart // 重新开始游戏;此函数将回到标题页面 // ------ 键盘、鼠标事件 ------ core.onKeyDown // 按下某个键时 core.onKeyUp // 放开某个键时 -core.pressKey // 按住某个键不动时 +core.pressKey // 按住某个键时 core.keyDown // 根据按下键的code来执行一系列操作 core.keyUp // 根据放开键的code来执行一系列操作 core.ondown // 点击(触摸)事件按下时 @@ -37,14 +44,14 @@ core.onmove // 当在触摸屏上滑动时 core.onup // 当点击(触摸)事件放开时 core.getClickLoc // 获得点击事件相对左上角的坐标(0到12之间) core.onclick // 具体点击屏幕上(x,y)点时,执行的操作 -core.onmousewheel // 滑动鼠标滚轮时的操作(楼层传送时可用滚轮切换楼层) +core.onmousewheel // 滑动鼠标滚轮时的操作 // ------ 自动寻路代码相关 ------ core.clearAutomaticRouteNode // 清除自动寻路路线 core.stopAutomaticRoute // 停止自动寻路操作 core.continueAutomaticRoute // 继续剩下的自动寻路操作 -core.clearContinueAutomaticRoute // 清除剩下的自动寻路列表 -core.setAutomaticRoute // 设置一个自动寻路 +core.clearContinueAutomaticRoute // 清空剩下的自动寻路列表 +core.setAutomaticRoute // 设置自动寻路路线 core.automaticRoute // 自动寻路算法,找寻最优路径 core.fillPosWithPoint // 显示离散的寻路点 core.clearStepPostfix // 清除已经寻路过的部分 @@ -54,13 +61,15 @@ core.stopAutoHeroMove // 停止勇士的自动行走 core.setAutoHeroMove // 设置勇士的自动行走路线 core.autoHeroMove // 让勇士开始自动行走 core.setHeroMoveInterval // 设置行走的效果动画 -core.setHeroMoveTriggerInterval // 设置勇士行走过程中对途经事件的触发检测 -* core.turnHero(direction) // 设置勇士的方向(转向);如果指定了direction则会面向该方向,否则执行一个转向操作。 +core.setHeroMoveTriggerInterval // 设置勇士行走过程中对事件的触发检测 +* core.turnHero(direction) // 设置勇士的方向(转向) +core.canMoveHero // 勇士能否前往某方向 core.moveHero // 让勇士开始移动 +core.eventMoveHero // 使用事件让勇士移动。这个函数将不会触发任何事件。 core.moveOneStep // 每移动一格后执行的事件。中毒时在这里进行扣血判断。 core.waitHeroToStop(callback) // 停止勇士的一切行动,等待勇士行动结束后,再执行callback回调函数。 core.stopHero // 停止勇士的移动状态。 -core.drawHero // 在hero层绘制勇士。 +core.drawHero // 绘制勇士。 * core.setHeroLoc(name, value) // 设置勇士的位置。name为”direction”,”x”,”y” * core.getHeroLoc(name) // 获得勇士的位置。 * core.nextX // 获得勇士面对位置的x坐标 @@ -71,42 +80,49 @@ core.drawHero // 在hero层绘制勇士。 * core.battle(id, x, y, force, callback) // 进行战斗;force表示是否强制战斗 core.afterBattle // 战斗完毕 core.trigger(x,y) // 触发x,y点的事件 -* core.changeFloor(floorId, stair, heroLoc, time, callback) // 楼层切换floorId为目标楼层Id,stair可指定为上/下楼梯,time动画时间 -core.mapChangeAnimate // 实际切换的动画效果 -core.clearMap // 清除地图显示 +* core.changeFloor(floorId, stair, heroLoc, time, callback) // 楼层切换。floorId为目标楼层Id,stair可指定为上/下楼梯,time动画时间 +core.mapChangeAnimate // 地图切换动画效果 +core.clearMap // 清除地图 core.fillText // 在某个canvas上绘制一段文字 core.fillRect // 在某个canvas上绘制一个矩形 core.strokeRect // 在某个canvas上绘制一个矩形的边框 +core.drawLine // 在某个canvas上绘制一条线 core.setFont // 设置某个canvas的文字字体 core.setLineWidth // 设置某个canvas的线宽度 core.saveCanvas // 保存某个canvas状态 -core.loadCanvas // 读取某个canvas状态 +core.loadCanvas // 加载某个canvas状态 core.setStrokeStyle // 设置某个canvas边框属性 core.setAlpha // 设置某个canvas的alpha值 core.setOpacity // 设置某个canvas的透明度 core.setFillStyle // 设置某个canvas的绘制属性(如颜色等) * core.drawMap(mapId, callback) // 绘制某张地图。mapId为地图Id,绘制完毕将执行callback回调函数。 +core.drawAutotile // 绘制Autotile +core.drawAutotileBlock // 绘制Autotile的某一块 * core.noPassExists(x,y) // 某个点是否不可通行 core.noPass // 某个点是否在区域内且不可通行 * core.npcExists(x,y) // 某个点是否存在NPC -* core.terrainExists(x,y) // 某个点是否存在指定的地形 +* core.terrainExists(x,y) // 某个点是否存在(指定的)地形 * core.stairExists(x,y) // 某个点是否存在楼梯 * core.nearStair // 当前位置是否在楼梯边 -* core.enemyExists(x,y) // 某个点是否存在怪物 +* core.enemyExists(x,y) // 某个点是否存在(指定的)怪物 * core.getBlock(x, y, floorId, needEnable) // 获得某个点的block。floorId指定目标楼层,needEnable如果为false则即使该点的事件处于禁用状态也将被返回(否则只有事件启用的点才被返回) core.moveBlock // 显示移动某块的动画,达到{“type”:”move”}的效果 core.animateBlock // 显示/隐藏某个块时的动画效果 -core.addBlock // 将某个块从禁用变成启用状态 +core.showBlock // 将某个块从禁用变成启用状态 core.removeBlock // 将某个块从启用变成禁用状态 core.removeBlockById // 根据block的索引删除该块 core.removeBlockByIds // 一次性删除多个block core.addGlobalAnimate // 添加一个全局动画 core.removeGlobalAnimate // 删除一个或所有全局动画 core.setGlobalAnimate // 设置全局动画的显示效果 +core.syncGlobalAnimate // 同步所有的全局动画效果 core.setBoxAnimate // 显示UI层某个box的动画(如怪物手册中怪物的动画) core.drawBoxAnimate // 绘制UI层的box动画 -core.setFg // 色调渐变 -* core.updateFg // 更新全地图的显伤 +core.updateCheckBlock // 更新领域、夹击、阻击的伤害地图 +core.checkBlock // 检查并执行领域、夹击、阻击事件 +core.snipe // 阻击事件(动画效果) +core.setFg // 更改画面色调 +* core.updateFg // 更新全地图显伤 * core.itemCount // 获得某个物品的个数 * core.hasItem // 是否存在某个物品 * core.setItem // 设置某个物品的个数 @@ -114,23 +130,23 @@ core.setFg // 色调渐变 * core.useItem // 使用某个物品;直接调用items.js中的useItem函数。 * core.canUseItem // 能否使用某个物品。直接调用items.js中的canUseItem函数。 * core.addItem // 增加某个物品的个数 -* core.getItem // 获得某个物品时的事件 +core.getNextItem // 获得面前的物品(轻按) +* core.getItem // 获得某个物品 * core.drawTip // 左上角绘制一段提示 * core.drawText // 地图中间绘制一段文字 // ------ 系统机制 ------ core.replaceText // 将文字中的${和}(表达式)进行替换 core.calValue // 计算表达式的值 -core.splitText // 字符串自动换行的分割 +core.doEffect // 执行一个表达式的effect操作 +core.splitLines // 字符串自动换行的分割 core.unshift // 向某个数组前插入另一个数组或元素 core.setLocalStorage // 设置本地存储 core.getLocalStorage // 获得本地存储 core.removeLocalStorage // 移除本地存储 -core.clone // 复制一个对象 +core.clone // 深拷贝一个对象 core.formatDate // 格式化时间为字符串 core.setTwoDigits // 两位数显示 -core.win // 获胜;将直接调用events.js中的win函数 -core.lose // 失败;将直接调用events.js中的lose函数 core.debug // 进入Debug模式,攻防血和钥匙都调成很高的数值 core.checkStatus // 判断当前能否进入某个事件 core.openBook // 点击怪物手册时的打开操作 @@ -144,6 +160,7 @@ core.saveData // 存档到本地 core.loadData // 从本地读档 * core.setStatus // 设置勇士属性 * core.getStatus // 获得勇士属性 +core.getLvName // 获得某个等级的名称 * core.setFlag // 设置某个自定义变量或flag * core.getFlag // 获得某个自定义变量或flag * core.hasFlag // 是否存在某个自定义变量或flag,且值为true @@ -151,17 +168,16 @@ core.insertAction // 往当前事件列表之前插入一系列事件 * core.lockControl // 锁定状态栏,常常用于事件处理 * core.unlockControl // 解锁状态栏 * core.isset // 判断某对象是否不为undefined也不会null -* core.playSound // 播放音频 * core.playBgm // 播放背景音乐 -core.changeSoundStatus // 切换声音状态 -core.enableSound // 启用音效 -core.disableSound // 禁用音效 +* core.pauseBgm // 暂停背景音乐的播放 +* core.resumeBgm // 恢复背景音乐的播放 +* core.playSound // 播放音频 core.show // 动画显示某对象 core.hide // 动画使某对象消失 core.clearStatusBar // 清空状态栏 core.updateStatusBar // 更新状态栏 core.resize // 屏幕分辨率改变后重新自适应 -core.resetSize // 屏幕分辨率改变后重新自适应 +core.domRenderer // 渲染DOM // ------ core.js 结束 ------ ``` @@ -171,53 +187,105 @@ core.resetSize // 屏幕分辨率改变后重新自适应 !> **`enemys.js` 定义了怪物信息。** ``` js -* core.enemys.getSpecialText // 获得特殊属性的文字 +core.enemys.init // 初始化 +* core.enemys.getEnemys // 获得一个或所有怪物数据 +* core.enemys.hasSpecial // 判断是否含有某特殊属性 +* core.enemys.getSpecialText // 获得所有特殊属性的名称 +* core.enemys.getSpecialHint // 获得每个特殊属性的说明 * core.enemys.getDamage // 获得某个怪物的伤害 -* core.enemys.getExtraDamage // 获得某个怪物的额外伤害(吸血) -* core.enemys.getCritical // 计算某个怪物的临界值 -* core.enemys.getCriticalDamage // 计算某个怪物的临界减伤 -* core.enemys.getDefDamage // 计算某个怪物的1防减伤 -* core.enemys.calDamage // 实际的伤害计算公式 -core.enemys.getCurrentEnemys // 获得当前层剩下的的怪物列表 +* core.enemys.getExtraDamage // 获得某个怪物的额外伤害 +* core.enemys.getCritical // 临界值计算 +* core.enemys.getCriticalDamage // 临界减伤计算 +* core.enemys.getDefDamage // 1防减伤计算 +* core.enemys.calDamage // 具体的伤害计算公式 +core.enemys.getCurrentEnemys // 获得当前楼层的怪物列表 ``` !> **`events.js` 定义了各个事件的处理流程。** ``` js -* core.events.startGame // 开始游戏 -* core.events.win // 获胜 -* core.events.lose // 失败 -core.events.checkBlock // 检查领域、夹击事件 -core.events.afterChangeFloor // 楼层切换结束时的事件 +core.events.init // 初始化 +core.events.getEvents // 获得一个或所有系统事件类型 +core.events.startGame // 游戏开始事件 +* core.events.setInitData // 不同难度分别设置初始属性 +* core.events.win // 游戏获胜事件 +* core.events.lose // 游戏失败事件 +core.events.afterChangeFloor // 转换楼层结束的事件 core.events.doEvents // 开始执行一系列自定义事件 core.events.doAction // 执行当前自定义事件列表中的下一个事件 -core.events.insertAction // 往当前自定义事件列表前插入若干个事件 +core.events.insertAction // 往当前事件列表之前添加一个或多个事件 core.events.openShop // 打开一个全局商店 -core.events.disableQuickShop // 禁用一个快捷商店 +core.events.disableQuickShop // 禁用一个全局商店 * core.events.canUseQuickShop // 当前能否使用快捷商店 +* core.events.checkLvUp // 检查升级事件 * core.events.useItem // 尝试使用道具 +core.events.addPoint // 加点事件 core.events.afterBattle // 战斗结束后触发的事件 core.events.afterOpenDoor // 开一个门后触发的事件 core.events.passNet // 经过一个路障 -core.events.beforeSaveData // 即将存档前可以执行的操作 -core.events.afterLoadData // 读档后,载入事件前可以执行的操作 +core.events.changeLight // 改变亮灯(感叹号)的事件 +* core.events.afterChangeLight // 改变亮灯之后,可以触发的事件 +* core.events.afterUseBomb // 使用炸弹/圣锤后的事件 +* core.events.beforeSaveData // 即将存档前可以执行的操作 +* core.events.afterLoadData // 读档事件后,载入事件前,可以执行的操作 -// ------ 界面上的点击事件 ------ -core.events.clickAction // 自定义事件处理时,对用户点击的处理 -core.events.clickBook // 怪物手册打开时,对用户点击的处理 -core.events.clickFly // 楼层传送器打开时,对用户点击的处理 -core.events.clickShop // 全局商店打开时,对用户点击的处理 -core.events.clickQuickShop // 快捷商店选项打开时 -core.events.clickToolbox // 工具栏打开时 -core.events.clickSL // 存/读档界面打开时 -core.events.clickSettings // 设置页面打开时 +// ------ 点击事件和键盘事件的处理 ------ +core.events.keyDownCtrl // 按下Ctrl键时(快捷跳过对话) +core.events.clickConfirmBox // 确认框界面时的点击操作 +core.events.keyUpConfirmBox // 确认框界面时,放开某个键的操作 +core.events.clickAction // 自定义事件时的点击操作 +core.events.keyDownAction // 自定义事件时,按下某个键的操作 +core.events.keyUpAction // 自定义事件时,放开某个键的操作 +core.events.clickBook // 怪物手册界面的点击操作 +core.events.keyDownBook // 怪物手册界面时,按下某个键的操作 +core.events.keyUpBook // 怪物手册界面时,放开某个键的操作 +core.events.clickBookDetail // 怪物手册属性显示界面时的点击操作 +core.events.clickFly // 楼层传送器界面时的点击操作 +core.events.keyDownFly // 楼层传送器界面时,按下某个键的操作 +core.events.keyUpFly // 楼层传送器界面时,放开某个键的操作 +core.events.clickShop // 商店界面时的点击操作 +core.events.keyDownShop // 商店界面时,按下某个键的操作 +core.events.keyUpShop // 商店界面时,放开某个键的操作 +core.events.clickQuickShop // 快捷商店界面时的点击操作 +core.events.keyDownQuickShop // 快捷商店界面时,按下某个键的操作 +core.events.keyUpQuickShop // 快捷商店界面时,放开某个键的操作 +core.events.clickToolbox // 工具栏界面时的点击操作 +core.events.clickToolboxIndex // 选择工具栏界面中某个Index后的操作 +core.events.keyDownToolbox // 工具栏界面时,按下某个键的操作 +core.events.keyUpToolbox // 工具栏界面时,放开某个键的操作 +core.events.clickSL // 存读档界面时的点击操作 +core.events.keyDownSL // 存读档界面时,按下某个键的操作 +core.events.keyUpSL // 存读档界面时,放开某个键的操作 +core.events.clickSwitchs // 系统设置界面时的点击操作 +core.events.keyDownSwitchs // 系统设置界面时,按下某个键的操作 +core.events.keyUpSwitchs // 系统设置界面时,放开某个键的操作 +core.events.clickSettings // 系统菜单栏界面时的点击事件 +core.events.keyDownSettings // 系统菜单栏界面时,按下某个键的操作 +core.events.keyUpSettings // 系统菜单栏界面时,放开某个键的操作 +core.events.clickSyncSave // 同步存档界面时的点击操作 +core.events.keyDownSyncSave // 同步存档界面时,按下某个键的操作 +core.events.keyUpSyncSave // 同步存档界面时,放开某个键的操作 +core.events.clickAbout // “关于”界面时的点击操作 ``` -!> `maps.js` 定义了地图,以及每个数字所代表的意义。 +!> `icons.js` 定义了素材ID和它在图片上的索引的对应关系。 + +!> `items.js` 定义了每个道具的名称,以及使用效果。 + +``` js +core.items.init // 初始化 +core.items.getItems // 获得所有道具 +core.items.getItemEffect // “即捡即用类”道具的使用效果 +core.items.getItemEffectTip // “即捡即用类”道具的文字提示 +* core.items.useItem // 使用道具 +* core.items.cauUseItem // 当前能否使用道具 +``` + +!> `maps.js` 定义了数字-ID的对应关系。 ``` js core.maps.loadFloor // 加载某个楼层(从剧本或存档中) -core.maps.getBlock // 将数字替换成实际的内容 +core.maps.getBlock // 数字和ID的对应关系 core.maps.addEvent // 向该楼层添加剧本的自定义事件 core.maps.addChangeFloor // 向该楼层添加剧本的楼层转换事件 core.maps.initMaps // 初始化所有地图 @@ -232,16 +300,19 @@ core.ui.closePanel // 结束一切事件和绘制,关闭UI窗口,返回游 core.ui.drawTextBox // 绘制一个对话框 core.ui.drawChoices // 绘制一个选项界面 core.ui.drawConfirmBox // 绘制一个确认/取消的警告页面 +core.ui.drawSwitchs // 绘制系统设置界面 core.ui.drawSettings // 绘制系统菜单栏 core.ui.drawQuickShop // 绘制快捷商店选择栏 -core.ui.drawBattleAnimate // 绘制战斗过程 -core.ui.drawWaiting // 绘制一个“请稍后”页面 -core.ui.drawSyncSave // 绘制存档同步选项 +core.ui.drawBattleAnimate // 绘制战斗动画 +core.ui.drawWaiting // 绘制等待界面 +core.ui.drawSyncSave // 绘制存档同步界面 core.ui.drawPagination // 绘制分页 core.ui.drawEnemyBook // 绘制怪物手册 +core.ui.drawBookDetail // 绘制怪物属性的详细信息 core.ui.drawFly // 绘制楼层传送器 core.ui.drawToolbox // 绘制道具栏 core.ui.drawSLPanel // 绘制存档/读档界面 core.ui.drawThumbnail // 绘制一个缩略图 core.ui.drawAbout // 绘制“关于”界面 +core.ui.drawHelp // 绘制帮助界面 ``` diff --git a/docs/element.md b/docs/element.md index 668c0c2d..50459e42 100644 --- a/docs/element.md +++ b/docs/element.md @@ -40,14 +40,15 @@ ``` js enemys.prototype.getSpecialText = function (enemyId) { if (enemyId == undefined) return ""; - var special = this.enemys[enemyId].special; + var enemy = this.enemys[enemyId]; + var special = enemy.special; var text = []; if (this.hasSpecial(special, 1)) text.push("先攻"); if (this.hasSpecial(special, 2)) text.push("魔攻"); if (this.hasSpecial(special, 3)) text.push("坚固"); if (this.hasSpecial(special, 4)) text.push("2连击"); if (this.hasSpecial(special, 5)) text.push("3连击"); - if (this.hasSpecial(special, 6)) text.push("4连击"); + if (this.hasSpecial(special, 6)) text.push((enemy.n||4)+"连击"); if (this.hasSpecial(special, 7)) text.push("破甲"); if (this.hasSpecial(special, 8)) text.push("反击"); if (this.hasSpecial(special, 9)) text.push("净化"); @@ -59,22 +60,35 @@ enemys.prototype.getSpecialText = function (enemyId) { if (this.hasSpecial(special, 15)) text.push("领域"); if (this.hasSpecial(special, 16)) text.push("夹击"); if (this.hasSpecial(special, 17)) text.push("仇恨"); + if (this.hasSpecial(special, 18)) text.push("阻击"); + if (this.hasSpecial(special, 19)) text.push("自爆"); + if (this.hasSpecial(special, 20)) text.push("无敌"); return text.join(" "); } ``` -如果需要双属性,则采用100x+y的写法。例如 103 则视为同时拥有1和3的属性,即先攻且坚固。同理1314为衰弱诅咒双属性。 +多属性可采用数组的写法,比如`'special': [1,3]`视为同时拥有先攻和坚固属性;`'special': [5,10,14,18]`视为拥有3连击、魔防、诅咒、阻击四个属性。 -如果需要三属性,则采用10000x+100y+z的写法。例如71116视为同时拥有7,11和16的属性,即破甲、吸血、夹击。 +本塔支持战斗动画,在`data.js`中存在三个全局选项:`canOpenBattleAnimate`, `showBattleAnimateConfirm`, `battleAnimate`。 +- `canOpenBattleAnimate`代表是否允许用户开启战斗动画。如果你添加了一些自定义属性,且不想修改战斗界面的UI,则可以将其关闭。 +- `showBattleAnimateConfirm`代表是否在游戏开始时给用户提供开启动画的选项。对于一些偏向于萌新的塔,可以开启此项。 +- `battleAnimate`代表是否默认开启战斗动画。此项会被用户存储的设置给覆盖。 +- 如果`canOpenBattleAnimate`为false,则后面两个也强制为false。 -四个乃至更多的属性以此类推。 +怪物可以负伤,在`data.js`的全局变量`enableNegativeDamage`中指定。 -怪物的伤害计算在下面的`calDamage`函数中,如有自己需求的伤害计算公式请修改该函数的代码。 +下面的`getSpecialHint`函数则给定了每个特殊属性的详细描述。这个描述将在怪物手册中看到。 + +**打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。** 如果`data.js`中的enableExperience为false,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。 拿到幸运金币后,打怪获得的金币将翻倍。 +N连击怪物的special是6,且我们可以为它定义n代表实际连击数。参见样板中剑王的写法。 + +![N连击](./img/nattack.png) + 吸血怪需要在怪物后添加value,代表吸血的比例。 ![怪物吸血](./img/blood.png) @@ -89,15 +103,21 @@ enemys.prototype.getSpecialText = function (enemyId) { 领域怪需要在怪物后添加value,代表领域伤害的数值。如果勇士生命值扣减到0,则直接死亡触发lose事件。 -![怪物领域](./img/domainenemy.png) +领域是十字伤害还是九宫格伤害由data.js中的全局变量`zoneSquare`设定。你也可以对该怪物自行进行设定。 -请注意如果吸血和领域同时存在,则value会冲突。**因此请勿将吸血和领域放置在同一个怪物身上。** +`range`选项可选,代表该领域怪的范围,不写则默认为1。 -本塔暂不支持阻击、激光、自爆、退化等属性。 +![怪物领域](./img/zone.png) + +阻击怪同样需要在怪物后添加value,代表领域伤害的数值。如果勇士生命值扣减到0,则直接死亡触发lose事件。 + +!> 阻击怪后退的地点不能有任何事件存在,即使是已经被禁用的自定义事件! + +请注意如果吸血、领域、阻击中任何两个同时存在,则value会冲突。**因此请勿将吸血、领域或阻击放置在同一个怪物身上。** 如有额外需求,可参见[自定义怪物属性](personalization#自定义自定义怪物属性),里面讲了如何设置一个新的怪物属性。 -### 路障、楼梯、传送门 +### 路障,楼梯,传送门 血网的伤害数值、中毒后每步伤害数值、衰弱时暂时攻防下降的数值,都在 `data.js` 的values内定义。 @@ -123,6 +143,65 @@ floorId指定的是目标楼层的唯一标识符(ID)。 ![楼层转换穿透](./img/floorset.png) +### 背景音乐 + +本塔支持BGM和SE的播放。 + +要播放音乐和音效,你需要将对应的文件放在sounds目录下,然后在main.js中进行定义 + +``` js +this.bgms = [ // 在此存放所有的bgm,和文件名一致。第一项为默认播放项 + // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 + '058-Slow01.mid', 'bgm.mp3', 'qianjin.mid', 'star.mid' +]; +this.sounds = [ // 在此存放所有的SE,和文件名一致 + // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 + 'floor.mp3', 'attack.ogg', 'door.ogg', 'item.ogg' +] +``` + +!> 音频名不能使用中文,不能带空格或特殊字符。 + +目前BGM支持主流的音乐格式,如mp3, ogg, mid格式等。SE则不支持mid格式的播放。 + +!> mid格式是通过数学方法模拟出来的音乐效果,质量可能会和实际效果差距较大。 + +定义完毕后,我们可以调用`playBgm`/`playSound`事件来播放对应的音乐/音效,有关事件的详细介绍请参见[事件](event)。 + +**另外,考虑到用户的流量问题,将遵循如下规则:** +- **如果用户当前使用的电脑,则默认开启音乐效果,并播放默认BGM** +- **如果用户当前使用的手机,且处于Wifi状态,则默认开启音乐效果,并播放默认BGM** +- **其他情况,将默认关闭音乐效果,只有在用户在菜单栏中点击“音乐开关”后才会播放音乐** + +!> iOS平台以及部分浏览器不支持获得当前网络状态,此时即使在使用Wifi也必须要用户点击“音乐开关”才能播放音乐。 + +### 操作说明 + +本塔主要支持鼠标(触摸屏)操作和键盘操作。 + +鼠标(触摸屏)操作说明如下: +- **点状态栏中图标:** 进行对应的操作 +- **点任意块:** 寻路并移动 +- **点任意块并拖动:** 指定寻路路线 +- **单击勇士:** 转向 +- **双击勇士:** 轻按(仅在轻按开关打开时有效) + +键盘操作快捷键如下: +- **[CTRL]** 跳过对话 +- **[X]** 打开/关闭怪物手册 +- **[G]** 打开/关闭楼层传送器 +- **[S/D]** 打开/关闭存/读档页面 +- **[K]** 打开/关闭快捷商店选择列表 +- **[T]** 打开/关闭工具栏 +- **[ESC]** 打开/关闭系统菜单 +- **[H]** 打开帮助页面 +- **[SPACE]** 轻按(仅在轻按开关打开时有效) +- **[1]** 快捷使用破墙镐 +- **[2]** 快捷使用炸弹/圣锤 +- **[3]** 快捷使用中心对称飞行器 + +以上快捷键也能在游戏菜单中的操作说明中看到。 +     diff --git a/docs/event.md b/docs/event.md index f9cab896..a1525c3c 100644 --- a/docs/event.md +++ b/docs/event.md @@ -397,7 +397,9 @@ revisit常常使用在一些商人之类的地方,当用户购买物品后不 如果强制战斗失败,则会立刻生命归0并死亡,调用lose函数,接下来的事件不会再被执行。 -强制战斗没有指定loc的选项,因此战斗后需要调用hide使怪物消失(如果有必要)。强制战斗不会触发任何afterBattle里的事件。 +打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](#加点事件)。 + +强制战斗没有指定loc的选项,因此战斗后需要调用hide使怪物消失(如果有必要)。 ### openDoor: 开门 @@ -416,8 +418,6 @@ loc指定门的坐标,floorId指定门所在的楼层ID。如果是当前层 如果loc所在的点既不是门也不是墙壁,则忽略本事件。 -openDoor不会触发任何afterOpenDoor里的事件。 - ### changeFloor: 楼层切换 在事件中也可以对楼层进行切换。一个比较典型的例子就是TSW中,勇士在三楼的陷阱被扔到了二楼,就是一个楼层切换事件。 @@ -553,6 +553,26 @@ move完毕后移动的NPC/怪物一定会消失,只不过可以通过immediate 不过值得注意的是,用这种方式移动勇士的过程中将无视一切地形,无视一切事件,中毒状态也不会扣血。 +### playBgm: 播放背景音乐 + +使用playBgm可以播放一个背景音乐。 + +使用方法:`{"type": "playBgm", "name": "bgm.mp3"}` + +值得注意的是,额外添加进文件的背景音乐,需在main.js中this.bgms里加载它。 + +目前支持mp3/ogg/wav/mid等多种格式的音乐播放。 + +有关BGM播放的详细说明参见[背景音乐](element#背景音乐) + +### pauseBgm: 暂停背景音乐 + +使用`{"type": "pauseBgm"}`可以暂停背景音乐的播放。 + +### resumeBgm: 恢复背景音乐 + +使用`{"type": "resumeBgm"}`可以恢复背景音乐的播放。 + ### playSound: 播放音效 使用playSound可以立刻播放一个音效。 @@ -561,10 +581,6 @@ move完毕后移动的NPC/怪物一定会消失,只不过可以通过immediate 值得注意的是,如果是额外添加进文件的音效,则需在main.js中this.sounds里加载它。 -!> 自定义添加的音效名请勿包含`-`,否则将无法正常使用! - -由于考虑到用户流量问题,每个额外音效最好不超过20KB。 - ### win: 获得胜利 `{"type": "win", "reason": "xxx"}` 将会直接调用events.js中的win函数,并将reason作为参数传入。 @@ -756,6 +772,43 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 // …… ``` +## 加点事件 + +打败怪物后可以进行加点。 + +如果要对某个怪物进行加点操作,则首先需要修改该怪物的点数值,即在怪物定义的后面添加`point`,代表怪物本身的加点数值。 + +``` js +... 'def': 0, 'money': 1, 'experience': 1, 'special': 0, 'point': 1}, // 在怪物后面添加point代表怪物的加点数 +``` + +然后在`events.js`文件中找到`addPoint`函数。它将返回一个choices事件。修改此函数为我们需要的加点项即可。 + +``` js +////// 加点 ////// +events.prototype.addPoint = function (enemy) { + var point = enemy.point; // 获得该怪物的point + if (!core.isset(point) || point<=0) return []; + + // 加点,返回一个choices事件 + return [ + {"type": "choices", + "choices": [ // 提供三个选项:对于每一点,攻击+1/防御+2/生命+200 + {"text": "攻击+"+(1*point), "action": [ + {"type": "setValue", "name": "status:atk", "value": "status:atk+"+(1*point)} + ]}, + {"text": "防御+"+(2*point), "action": [ + {"type": "setValue", "name": "status:def", "value": "status:def+"+(2*point)} + ]}, + {"text": "生命+"+(200*point), "action": [ + {"type": "setValue", "name": "status:hp", "value": "status:hp+"+(200*point)} + ]}, + ] + } + ]; +} +``` + ## 全局商店 我们可以采用上面的choices方式来给出一个商店。这样的商店确实可以有效地进行操作,但是却是"非全局"的,换句话说,只有在碰到NPC的时候才能触发商店事件。 @@ -776,7 +829,6 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 // 上面的例子是50层商店的计算公式。你也可以写任意其他的计算公式,只要以times作为参数即可。 // 例如: "need": "25" 就是恒定需要25金币的商店; "need": "20+2*times" 就是第一次访问要20金币,以后每次递增2金币的商店。 // 如果是对于每个选项有不同的计算公式,写 "need": "-1" 即可。可参见下面的经验商店。 - "text": "勇敢的武士啊,给我${need}金币就可以:", // 显示的文字,需手动加换行符。可以使用${need}表示上面的need值。 "choices": [ // 商店的选项 {"text": "生命+800", "effect": "status:hp+=800"}, @@ -784,10 +836,12 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 {"text": "攻击+4", "effect": "status:atk+=4"}, {"text": "防御+4", "effect": "status:def+=4"}, {"text": "魔防+10", "effect": "status:mdef+=10"} - // effect只能对status和item进行操作,不能修改flag值。且其中间只能用+=符号(也就是只能增加某个属性或道具) + // effect只能对status和item进行操作,不能修改flag值。 + // 必须是X+=Y的形式,其中Y可以是一个表达式,以status:xxx或item:xxx为参数 // 其他effect样例: // "item:yellowKey+=1" 黄钥匙+1 // "item:pickaxe+=3" 破墙镐+3 + // "status:hp+=2*(status:atk+status:def)" 将生命提升攻防和的数值的两倍 ] }, "expShop1": { // 商店唯一ID @@ -800,13 +854,13 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 "choices": [ // 在choices中写need,可以针对每个选项都有不同的需求。 // 这里的need同样可以以times作为参数,比如 "need": "100+20*times" - {"text": "等级+1", "need": "100", "effect": "status:hp+=1000;status:atk+=7;status:def+=7"}, + {"text": "等级+1", "need": "100", "effect": "status:lv+=1;status:hp+=1000;status:atk+=7;status:def+=7"}, // 多个effect直接以分号分开即可。如上面的意思是生命+1000,攻击+7,防御+7。 {"text": "攻击+5", "need": "30", "effect": "status:atk+=5"}, {"text": "防御+5", "need": "30", "effect": "status:def+=5"}, ] - } -} + }, +}, ``` 全局商店全部定义在`data.js`中的shops一项里。 @@ -887,37 +941,70 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 当且仅当勇士第一次到达某层时,将会触发此事件。可以利用此事件来显示一些剧情,或再让它调用 `{"type": "trigger"}` 来继续调用其他的事件。 +## 经验升级(进阶/境界塔) + +本塔也支持经验升级,即用户杀怪获得经验后,可以到达某些数值自动进阶,全面提升属性。 + +要经验升级,你需要先在`data.js`中的全局变量中启用。你需要将`enableExperience`启用经验,且`enableLevelUp`启用进阶。同时你也可以将`enableLv`置为true以在状态栏中显示当前等级(境界)。 + +同时,你还需要在`data.js`中的`levelUp`来定义每一个进阶所需要的生命值,以及进阶时的效果。 + +``` js +"levelUp": [ // 经验升级所需要的数值,是一个数组 + {}, // 第一项为初始等级,可以简单留空,也可以写name + + // 每一个里面可以含有三个参数 need, name, effect + // need为所需要的经验数值,是一个正整数。请确保need所需的依次递增 + // name为该等级的名称,也可以省略代表使用系统默认值;本项将显示在状态栏中 + // effect为本次升级所执行的操作,可由若干项组成,由分号分开 + // 其中每一项写法和上面的商店完全相同,同样必须是X+=Y的形式,Y是一个表达式,同样可以使用status:xxx或item:xxx代表勇士的某项数值/道具个数 + {"need": 20, "name": "第二级", "effect": "status:hp+=2*(status:atk+status:def);status:atk+=10;status:def+=10"}, // 先将生命提升攻防和的2倍;再将攻击+10,防御+10 + + // effect也允许写一个function,代表本次升级将会执行的操作,比如可以显示一段提示文字,或者触发一个事件 + {"need": 40, "effect": function () { + core.drawText("恭喜升级!"); + core.status.hero.hp *= 2; + core.status.hero.atk += 100; + core.status.hero.def += 100; + }}, + + // 依次往下写需要的数值即可 +] +``` + +`levelUp`是一个数组,里面分别定义了每个等级的信息。里面每一项是一个object,主要有三个参数`need`, `name`, `effect` +- `need` 该等级所需要的经验值,是一个正整数。请确保数组中的need依次递增。 +- `name` 该等级的名称,比如“佣兵下级”等。该项可以忽略,以使用系统默认的等级。该项将显示在状态栏中。 +- `effect` 为本次等级执行的操作。它有两种写法:字符串,或函数。 + - 如果`effect`为字符串,则和上面的全局商店的写法完全相同。可由分号分开,每一项为X+=Y的形式,X为你要修改的勇士属性/道具个数,Y为一个表达式。 + - 如果`effect`为函数,则也允许写一个`function`,来代表本次升级将会执行的操作。 + ## 开始,难度分歧,获胜与失败 -游戏开始时将调用`events.js`中的startGame函数。 +游戏开始时将调用`events.js`中的`startGame`函数。 -它将显示`data.js`中的startText内容(可以修改成自己的),并正式开始游戏。 +它将显示`data.js`中的startText内容(可以修改成自己的),提供战斗动画开启选择,设置初始福利,并正式开始游戏。 + +我们可以修改`setInitData`函数来对于不同难度分别设置初始属性。 其参数hard为以下三个字符串之一:`"Easy"`, `"Normal"`, `"Hard"`,分别对应三个难度。针对不同的难度,我们可以设置一些难度分歧。 ``` js -////// 游戏开始事件 ////// -events.prototype.startGame = function (hard) { - - if (core.status.isStarting) return; - core.status.isStarting = true; - - core.hideStartAnimate(function() { - core.drawText(core.clone(core.firstData.startText), function() { - core.startGame(hard); - if (hard=='Easy') { // 简单难度 - core.setFlag('hard', 1); // 可以用flag:hard来获得当前难度 - // 可以在此设置一些初始福利,比如设置初始生命值可以调用: - // core.setStatus("hp", 10000); - } - if (hard=='Normal') { // 普通难度 - core.setFlag('hard', 2); // 可以用flag:hard来获得当前难度 - } - if (hard=='Hard') { // 困难难度 - core.setFlag('hard', 3); // 可以用flag:hard来获得当前难度 - } - }); - }) +////// 不同难度分别设置初始属性 ////// +events.prototype.setInitData = function (hard) { + if (hard=='Easy') { // 简单难度 + core.setFlag('hard', 1); // 可以用flag:hard来获得当前难度 + // 可以在此设置一些初始福利,比如设置初始生命值可以调用: + // core.setStatus("hp", 10000); + // 赠送一把黄钥匙可以调用 + // core.setItem("yellowKey", 1); + } + if (hard=='Normal') { // 普通难度 + core.setFlag('hard', 2); // 可以用flag:hard来获得当前难度 + } + if (hard=='Hard') { // 困难难度 + core.setFlag('hard', 3); // 可以用flag:hard来获得当前难度 + } } ``` diff --git a/docs/img/domainenemy.png b/docs/img/domainenemy.png deleted file mode 100644 index b74eabcb1dd5d4efbc70902fa6d15993fa2e1368..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22145 zcmYhi1yCH#_XUc(26qVV1b3GZWO4W4PH##?Jlx`El02@BQy~CW4$egF8l4$x0 zujltx_+zy5RT~e${9}9I;GgsE-|*$hpRSyN!R@pXiu+7TS8V=I-;hBlrSv$7I!e#mw6887T)Ch`8Eb4^h8# zfaVsiFR@A8+mTuI^AZzjVYNiblJ-uzn;p-F$)@PAXI~_j1 zFLe;!&8FY46i8OM8tv%ld0Z`t?sfn9vzOKH<~1isjND;oSzwFQWi`wi%UW5u(nfhO zxpeC0TOUhLyTs}PKBBMdZSKL3tjiQ&%>3<|~4ojN{+1lcv>SyBl zw^IldKNZu}RboHI3H-#g6XqRGGtvWoUEtV(WV(>F3VKwy+JJbn6H;bF#JH1eE?o+jrF)BLZ11J#E8jnz} zxv-1(ySvk!iFOjn?^@MoE&h6Ho^LP_Y3{-Rb&A}VU_grFL3!metKq#O6bR140s>{R zaKH7!da+56WhFx$Rp&|&q6EU@jh^Joa=K7iyk`69pLhJtcg@+p z1%g+Wr>^Utf+fSVo^aL<`7~R`Oo}FX!WdNoTHLN*(D&JZ?qSTzOg3yqIJODKkIuzeowk==be8>VQ zoMwjc^|5zxnrBnNuMhRjOvSw#!sWE*LY7b+T?V$mOOuo$DDr|v^=Be?@mKkw_Xypg zd*27|{Z%~ip|Zvjgk}^^KyJ!PbCG1TQsG(9uuQq;KO;rY#qjY71u-v1 zvMQvbv+fOds3vkOTBM|qr&!R_D*!(bR5L5K4$tQgi#Ebe#NFNzz|?M_jNHOsQH$*Kb}W$c_G`c%m(*{h z4{&ijp4|}4e9Q{7!bLEY*0hb6yB5A%PTrh$Z)~O)7mw~X>sdZf6T#3D1E#f49Zyk` zlvE2S4?`-IAPis~;UW?ZoC|r?;bT5dRrq|b)zpVB{wPTl>5jrNzTNYg1zz^gN;>XoA2lF8vGF4i*Em>1A!^U-_X_2@A?z6_Xm5SFp$M<=1SQQE-q zsR)5r#v|?Bl1_@Ao1WvTe;wD{34dey`y}h$2kCk28lBY;lO7hkb(O8naGLba-0tdQ$U_`X6ivM;I)8rF*HAEk{Y-mk=IUY*VTlHHM|v;4lDxci>H zzFufLMxgwg-Zc+jny8G-VZ*kRgr^(f$@`{{(#MrLe-DK^W`{7!k)Qs^;+(=^AKzE~ z8CA`y!1|!$Z7HP^TNApjo=hzP=;ys#(UhfrpIy0dQ&w=AJE0W)5rrrT5$(M@cWTVU zl#{#Z854zG%3H>do7Ajd4}T>1v4B_fu#I<5$EX=OCNci^S{Aq|D5u>p2B}}b;r|{{ zJBD&ky=5aZ{(vDP*ZrJT%A|6wVsVF`57M3~dzcc{R~cEg5+9^1|=uiwX|vq1Q+YN5&!KX3Fq_E^1{f%oeHhRwv$o5LWqCtp>#%2 zLVLNi&J)ug;|dFHE_t}pGYKt?--}m}(N@7*@j!`C_`bdKCEto5QGA%v;~qO0;8P^` zrZxU5GYs3G(FhaLi^kJ5rL9(5hs6g(3wjVw&pY&pEd&xL zTM;YGc-QhtW|O-sDgS9U_RyVDkd`LiW7bMs{H4N>gu66@G0_tS-9ZbtL;bYr?_kgZ z?T+o0B?8BBjnIilpTkP~@1aUI)O&meEDx`-=|YmBMz6?$r~QeLRlW_%;Jrx0cF>ut z4W0qN2*I7Cc1!HfSgcggr~cu~mW>YwgkWG+lp&-Ibwg=2N9J1t9zz{OSq zxT;*wR(+mZBDĕ+H-0DP8cZ$aQ{ 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 diff --git a/docs/img/nattack.png b/docs/img/nattack.png new file mode 100644 index 0000000000000000000000000000000000000000..011b0c551074b4a43bba5566d749e83785335026 GIT binary patch literal 8523 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 YXmpq!_@V9^&5?{~-#1W)s@g~W7ZC|$%>V!Z literal 0 HcmV?d00001 diff --git a/docs/img/ps.png b/docs/img/ps.png index 9e0837e31326ab5b14820839f3c2ff51f6ac9487..9e28c8642f6cda8de6f75edeeff014e51f9654bc 100644 GIT binary patch literal 28629 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 z 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 eCY0@Aj=jl@_vVp@kKn(|PDxHxw(!X--~R Autotile的ID和文件名完全相同!且其ID/文件名不能含有中文、空格或特殊字符。 #### 新添加道具 如果你需要新增一个未被定义的道具: -1. 指定一个唯一的英文ID,不能和items中现有的重复。 -2. 进入icons.js,在items分类下进行添加(对应图标在图片上的位置,即index) +1. 指定一个唯一的英文ID,不能和现有的重复。 +2. 进入icons.js,在items分类下进行添加索引(对应图标在图片上的位置,即index) 3. 指定一个数字,在maps.js的getBlock下类似进行添加。 4. 在items.js中仿照其他道具,来添加道具的信息。 -``` js -if (id == 63) tmp.event = {'cls': 'items', 'id': 'moneyPocket'} // 金钱袋 -if (id == 64) tmp.event = {'cls': 'items', 'id': 'shoes'} // 绿鞋 -if (id == 65) tmp.event = {'cls': 'items', 'id': 'hammer'} // 圣锤 -// 可以在这里添加自己的数字-ID对应关系,但不能和任何已有的数字重复 -``` - 有关如何自行实现一个道具的效果,参见[自定义道具效果](#自定义道具效果)。 #### 新添加怪物 如果我们需要新添加怪物,请在enemys.png中新增一行,然后复制粘贴上四帧怪物图的**1和3帧**。 +你可以通过便捷PS工具的“更改色相”来将红头怪变成橙头怪等。 + 然后执行如下操作: 1. 指定一个唯一的英文ID,不能和enemys中现有的重复。 -2. 进入icons.js,在enemys分类下进行添加(对应图标在图片上的位置,即index) +2. 进入icons.js,在enemys分类下进行添加索引(对应图标在图片上的位置,即index) 3. 在maps.js的getBlock下继续进行添加。请注意其ID为200开始的顺序,即如果新增一行为261,依次类推 4. 在enemys.js中仿照其他怪物,来添加怪物的信息。 -``` js -if (id == 258) tmp.event = {'cls': 'enemys', 'id': 'octopus'}; -if (id == 259) tmp.event = {'cls': 'enemys', 'id': 'fairy'}; -if (id == 260) tmp.event = {'cls': 'enemys', 'id': 'greenKnight'}; -// 在此依次添加,数字要求是递增的 -``` - 有关如何自行实现一个怪物的特殊属性或伤害计算公式,参见[怪物的特殊属性](#怪物的特殊属性)。 #### 新添加NPC -类似同上,给NPC指定ID,在icons.js中指定ID-index关系,在maps.js中指定ID-数字的关系,即可。 +1. 指定一个唯一的英文ID,不能和现有的重复。 +2. 进入icons.js,在npcs分类下进行添加索引(对应图标在图片上的位置,即index) +3. 指定一个数字,在maps.js的getBlock下类似进行添加。 ### 地图生成器使用自定义素材 @@ -176,18 +189,24 @@ enemys.prototype.getExtraDamage = function (monster) { } // ... 下略 ``` -3. 免疫领域、夹击效果:在`core.js`中,找到updateCheckBlock函数,并编辑成如果有神圣盾标记,则直接返回。 +3. 免疫领域、夹击、阻击效果:在`core.js`中,找到checkBlock函数,并编辑成如果有神圣盾标记,则将伤害变成0。 ``` js -// 更新领域、显伤点 -core.prototype.updateCheckBlock = function() { - if (!core.isset(core.status.thisMap)) return; - if (!core.isset(core.status.checkBlockMap)) core.updateCheckBlockMap(); - core.status.checkBlock = []; - if (core.hasItem('shield5')) return; // 如拥有神圣盾则直接返回 - for (var x=0;x<13;x++) { - for (var y=0;y<13;y++) { - // 计算(x,y)点伤害 - var damage = 0; +// 检查领域、夹击、阻击事件 +core.prototype.checkBlock = function () { + var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'); + var damage = core.status.checkBlock.damage[13*x+y]; + if (damage>0) { + if (core.hasFlag("shield5")) damage = 0; // 如果存在神圣盾,则将伤害变成0 + core.status.hero.hp -= damage; + + // 检查阻击事件 + var snipe = []; + var scan = { + 'up': {'x': 0, 'y': -1}, + 'left': {'x': -1, 'y': 0}, + 'down': {'x': 0, 'y': 1}, + 'right': {'x': 1, 'y': 0} + } // ... 下略 ``` 4. 如果有更高的需求,例如想让吸血效果变成一半(如异空间),则还是在上面这些地方进行对应的修改即可。 @@ -196,42 +215,15 @@ core.prototype.updateCheckBlock = function() { 如果你对现有的怪物不满意,想自行添加怪物属性(例如让怪物拥有双属性乃至更多属性),也是可以的。具体参见`enemys.js`文件。 -你需自己指定一个special数字,修改getSpecialText函数。 +你需自己指定一个special数字,修改getSpecialText函数(属性名)和getSpecialHint函数(属性提示文字)。 如果要修改伤害计算公式,请修改下面的calDamage函数。请注意,如果无法战斗,该函数必须返回`999999999`。 -因此无敌属性可以这样设置: - -先给无敌属性指定一个数字,例如18,在getSpecialText中定义 - -``` js -// ... 上略 - if (this.hasSpecial(special, 15)) text.push("领域"); - if (this.hasSpecial(special, 16)) text.push("夹击"); - if (this.hasSpecial(special, 17)) text.push("仇恨"); - if (this.hasSpecial(special, 18)) text.push("无敌"); // 添加无敌的显示 - return text.join(" "); -} - -``` - -然后修改calDamage,如果无敌属性且勇士没有拥有十字架,则立刻返回无穷大。 - -``` js -enemys.prototype.calDamage = function (hero_atk, hero_def, hero_mdef, mon_hp, mon_atk, mon_def, mon_special) { - if (this.hasSpecial(mon_special, 18) && !core.hasItem("cross")) // 如果是无敌属性,且勇士未持有十字架 - return 999999999; // 返回无限大 - - // 魔攻 - if (this.hasSpecial(mon_special, 2)) hero_def = 0; -// ... 下略 -``` - 对于吸血怪的额外伤害计算在getExtraDamage中。 对于毒衰弱怪物的战斗后结算在`events.js`中的afterBattle函数中。 -对于领域、夹击怪物的检查在`events.js`中的checkBlock函数中。 +对于领域、夹击、阻击怪物的检查在`events.js`中的checkBlock函数中。 `getCritical`, `getCriticalDamage`和`getDefDamage`三个函数依次计算的是该怪物的临界值、临界减伤和1防减伤。也可以适当进行修改。 diff --git a/docs/start.md b/docs/start.md index 127fd819..10300b46 100644 --- a/docs/start.md +++ b/docs/start.md @@ -36,7 +36,23 @@ 然后将楼层名改为MT1,floorId改名为MT1;title可以改成任意内容,将在切换楼层时进行显示(比如可以改成“1层小塔”)。 -具体样板文件的每个要素都有详细的注释。我们最终的任务其实是,将每个楼层的剧本(地图&事件)给写完即可。 +具体样板文件的每个要素如下: +- **`floorId`** 楼层唯一标识符;必须和文件名,以及 `main.floors.xxx` 完全一致 +- **`title`** 楼层中文名,将在切换楼层时进行显示 +- **`canFlyTo`** 当前楼层可否被楼传器飞到。如果该层不能飞到,则也在该层也不允许使用楼传器。 +- **`canUseQuickShop`** 当前楼层可否使用快捷商店。 +- **`defaultGround`** 该层的背景(地面)素材。需要是在`icon.js`里`terrains`中定义的一个ID,如`ground`, `grass2`等等。 +- **`color`** 该层的画面色调。本项可选,如果不写则色调为默认值(无色调),否则是一个RGBA数组,比如`[255,0,0,0.3]`等。 +- **`bgm`** 到达该层后默认播放的BGM。本项可忽略。 +- **`map`** 本层地图,需要是13x13数组,建议使用地图生成器或者可视化地图编辑器制作。 +- **`firstArrive`** 第一次到该楼层触发的事件 +- **`events`** 该楼的所有可能事件列表 +- **`changeFloor`** 楼层转换事件;该事件不能和上面的events有冲突(同位置点),否则会被覆盖 +- **`afterBattle`** 战斗后可能触发的事件列表 +- **`afterGetItem`** 获得道具后可能触发的事件列表 +- **`afterOpenDoor`** 开完门后可能触发的事件列表 + +我们最终的任务其实是,将每个楼层的剧本(地图&事件)给写完即可。 换句话说,只需要简单的复制操作,我们就可以新建一个剧本了。 diff --git a/libs/core.js b/libs/core.js index e572fe5b..cef47e25 100644 --- a/libs/core.js +++ b/libs/core.js @@ -104,6 +104,7 @@ function core() { /////////// 系统事件相关 /////////// +////// 初始化 ////// core.prototype.init = function (dom, statusBar, canvas, images, bgms, sounds, floorIds, floors, coreData) { core.dom = dom; core.statusBar = statusBar; @@ -192,6 +193,7 @@ core.prototype.init = function (dom, statusBar, canvas, images, bgms, sounds, fl }); } +////// 显示游戏开始界面 ////// core.prototype.showStartAnimate = function (callback) { core.dom.startPanel.style.opacity=1; core.dom.startPanel.style.display="block"; @@ -218,6 +220,7 @@ core.prototype.showStartAnimate = function (callback) { }, 20); } +////// 隐藏游戏开始界面 ////// core.prototype.hideStartAnimate = function (callback) { var opacityVal = 1; var startAnimate = window.setInterval(function () { @@ -231,14 +234,17 @@ core.prototype.hideStartAnimate = function (callback) { }, 20); } +////// 设置加载进度条进度 ////// core.prototype.setStartProgressVal = function (val) { core.dom.startTopProgress.style.width = val + '%'; } +////// 设置加载进度条提示文字 ////// core.prototype.setStartLoadTipText = function (text) { core.dom.startTopLoadTips.innerHTML = text; } +////// 加载图片和音频 ////// core.prototype.loader = function (callback) { var loadedImageNum = 0, allImageNum = 0, allSoundNum = 0; allImageNum = core.images.length; @@ -271,6 +277,7 @@ core.prototype.loader = function (callback) { } } +////// 加载图片 ////// core.prototype.loadImage = function (imgName, callback) { try { core.setStartLoadTipText('加载图片 ' + imgName + ' 中...'); @@ -289,6 +296,7 @@ core.prototype.loadImage = function (imgName, callback) { } } +////// 加载音频 ////// core.prototype.loadMusic = function (callback) { core.bgms.forEach(function (t) { @@ -388,12 +396,14 @@ core.prototype.loadMusic = function (callback) { callback(); } +////// 游戏是否已经开始 ////// core.prototype.isPlaying = function() { if (core.isset(core.status.played) && core.status.played) return true; return false; } +////// 清除游戏状态和数据 ////// core.prototype.clearStatus = function() { // 停止各个Timeout和Interval for (var i in core.interval) { @@ -404,6 +414,7 @@ core.prototype.clearStatus = function() { core.resize(main.dom.body.clientWidth, main.dom.body.clientHeight); } +////// 重置游戏状态和初始数据 ////// core.prototype.resetStatus = function(hero, hard, floorId, maps) { // 停止各个Timeout和Interval @@ -428,6 +439,7 @@ core.prototype.resetStatus = function(hero, hard, floorId, maps) { core.resize(main.dom.body.clientWidth, main.dom.body.clientHeight); } +////// 开始游戏 ////// core.prototype.startGame = function (hard, callback) { console.log('开始游戏'); @@ -439,7 +451,7 @@ core.prototype.startGame = function (hard, callback) { }); } - +////// 重新开始游戏;此函数将回到标题页面 ////// core.prototype.restart = function() { core.showStartAnimate(); } @@ -451,6 +463,7 @@ core.prototype.restart = function() { /////////// 键盘、鼠标事件相关 /////////// +////// 按下某个键时 ////// core.prototype.onkeyDown = function(e) { if (!core.isset(core.status.holdingKeys))core.status.holdingKeys=[]; var isArrow={37:true,38:true,39:true,40:true}[e.keyCode] @@ -467,6 +480,7 @@ core.prototype.onkeyDown = function(e) { } } +////// 放开某个键时 ////// core.prototype.onkeyUp = function(e) { var isArrow={37:true,38:true,39:true,40:true}[e.keyCode] if(isArrow && !core.status.lockControl){ @@ -484,6 +498,7 @@ core.prototype.onkeyUp = function(e) { } } +////// 按住某个键时 ////// core.prototype.pressKey = function (keyCode) { if (keyCode === core.status.holdingKeys.slice(-1)[0]) { core.keyDown(keyCode); @@ -491,6 +506,7 @@ core.prototype.pressKey = function (keyCode) { } } +////// 根据按下键的code来执行一系列操作 ////// core.prototype.keyDown = function(keyCode) { if(core.status.automaticRouting || core.status.automaticRouted) { core.stopAutomaticRoute(); @@ -589,6 +605,7 @@ core.prototype.keyDown = function(keyCode) { } } +////// 根据放开键的code来执行一系列操作 ////// core.prototype.keyUp = function(keyCode) { if (core.status.lockControl) { @@ -742,6 +759,7 @@ core.prototype.keyUp = function(keyCode) { core.stopHero(); } +////// 点击(触摸)事件按下时 ////// core.prototype.ondown = function (x ,y) { if (!core.status.played || core.status.lockControl) { core.onclick(x, y, []); @@ -758,6 +776,7 @@ core.prototype.ondown = function (x ,y) { core.fillPosWithPoint(pos); } +////// 当在触摸屏上滑动时 ////// core.prototype.onmove = function (x ,y) { if (core.status.holdingPath==0){return;} core.status.mouseOutCheck =1; @@ -780,6 +799,7 @@ core.prototype.onmove = function (x ,y) { } } +////// 当点击(触摸)事件放开时 ////// core.prototype.onup = function () { core.status.holdingPath=0; if(core.status.stepPostfix.length>0){ @@ -800,6 +820,7 @@ core.prototype.onup = function () { } } +////// 获得点击事件相对左上角的坐标(0到12之间) ////// core.prototype.getClickLoc = function (x, y) { var statusBar = {'x': 0, 'y': 0}; @@ -824,6 +845,7 @@ core.prototype.getClickLoc = function (x, y) { return loc; } +////// 具体点击屏幕上(x,y)点时,执行的操作 ////// core.prototype.onclick = function (x, y, stepPostfix) { // console.log("Click: (" + x + "," + y + ")"); @@ -939,6 +961,7 @@ core.prototype.onclick = function (x, y, stepPostfix) { } +////// 滑动鼠标滚轮时的操作 ////// core.prototype.onmousewheel = function (direct) { // 向下滚动是 -1 ,向上是 1 @@ -951,8 +974,8 @@ core.prototype.onmousewheel = function (direct) { // 怪物手册 if (core.status.lockControl && core.status.event.id == 'book') { - if (direct==1) core.ui.drawEnemyBook(core.status.event.data - 1); - if (direct==-1) core.ui.drawEnemyBook(core.status.event.data + 1); + if (direct==1) core.ui.drawBook(core.status.event.data - 1); + if (direct==-1) core.ui.drawBook(core.status.event.data + 1); return; } @@ -971,11 +994,13 @@ core.prototype.onmousewheel = function (direct) { /////////// 寻路代码相关 /////////// +////// 清除自动寻路路线 ////// core.prototype.clearAutomaticRouteNode = function (x, y) { if (core.status.event.id==null) core.canvas.ui.clearRect(x * 32 + 5, y * 32 + 5, 27, 27); } +////// 停止自动寻路操作 ////// core.prototype.stopAutomaticRoute = function () { if (!core.status.played) { return; @@ -989,6 +1014,7 @@ core.prototype.stopAutomaticRoute = function () { core.canvas.ui.clearRect(0, 0, 416, 416); } +////// 继续剩下的自动寻路操作 ////// core.prototype.continueAutomaticRoute = function () { // 此函数只应由events.afterOpenDoor和events.afterBattle调用 var moveStep = core.status.moveStepBeforeStop; @@ -999,11 +1025,13 @@ core.prototype.continueAutomaticRoute = function () { core.setAutoHeroMove(moveStep); } +////// 清空剩下的自动寻路列表 ////// core.prototype.clearContinueAutomaticRoute = function () { core.canvas.ui.clearRect(0, 0, 416, 416); core.status.moveStepBeforeStop=[]; } +////// 设置自动寻路路线 ////// core.prototype.setAutomaticRoute = function (destX, destY, stepPostfix) { if (!core.status.played || core.status.lockControl) { return; @@ -1118,7 +1146,8 @@ core.prototype.setAutomaticRoute = function (destX, destY, stepPostfix) { core.status.automaticRoutingTemp = {'destX': 0, 'destY': 0, 'moveStep': []}; } -// BFS + +////// 自动寻路算法,找寻最优路径 ////// core.prototype.automaticRoute = function (destX, destY) { var startX = core.getHeroLoc('x'); var startY = core.getHeroLoc('y'); @@ -1217,10 +1246,12 @@ core.prototype.automaticRoute = function (destX, destY) { return ans; } +////// 显示离散的寻路点 ////// core.prototype.fillPosWithPoint = function (pos) { core.fillRect('ui', pos.x*32+12,pos.y*32+12,8,8, '#bfbfbf'); } +////// 清除已经寻路过的部分 ////// core.prototype.clearStepPostfix = function () { if(core.status.mouseOutCheck >0){ core.status.mouseOutCheck--; @@ -1241,6 +1272,7 @@ core.prototype.clearStepPostfix = function () { /////////// 自动行走 & 行走控制 /////////// +////// 停止勇士的自动行走 ////// core.prototype.stopAutoHeroMove = function () { core.status.autoHeroMove = false; core.status.automaticRouting = false; @@ -1253,6 +1285,7 @@ core.prototype.stopAutoHeroMove = function () { clearInterval(core.interval.heroAutoMoveScan); } +////// 设置勇士的自动行走路线 ////// core.prototype.setAutoHeroMove = function (steps, start) { if (steps.length == 0) { return; @@ -1272,12 +1305,14 @@ core.prototype.setAutoHeroMove = function (steps, start) { }, 80); } +////// 让勇士开始自动行走 ////// core.prototype.autoHeroMove = function (direction, step) { core.status.autoHeroMove = true; core.status.destStep = step; core.moveHero(direction); } +////// 设置行走的效果动画 ////// core.prototype.setHeroMoveInterval = function (direction, x, y, callback) { if (core.status.heroMoving) { return; @@ -1309,6 +1344,7 @@ core.prototype.setHeroMoveInterval = function (direction, x, y, callback) { }, 12.5); } +////// 设置勇士行走过程中对事件的触发检测 ////// core.prototype.setHeroMoveTriggerInterval = function () { var direction, x, y; var scan = { @@ -1322,7 +1358,7 @@ core.prototype.setHeroMoveTriggerInterval = function () { direction = core.getHeroLoc('direction'); x = core.getHeroLoc('x'); y = core.getHeroLoc('y'); - var noPass = core.noPass(x + scan[direction].x, y + scan[direction].y), canMove = core.canMove(); + var noPass = core.noPass(x + scan[direction].x, y + scan[direction].y), canMove = core.canMoveHero(); if (noPass || !canMove) { if (canMove) // 非箭头:触发 core.trigger(x + scan[direction].x, y + scan[direction].y); @@ -1365,6 +1401,7 @@ core.prototype.setHeroMoveTriggerInterval = function () { }, 50); } +////// 设置勇士的方向(转向) ////// core.prototype.turnHero = function(direction) { if (core.isset(direction)) { core.status.hero.loc.direction = direction; @@ -1378,7 +1415,8 @@ core.prototype.turnHero = function(direction) { core.canvas.ui.clearRect(0, 0, 416, 416); } -core.prototype.canMove = function() { +////// 勇士能否前往某方向 ////// +core.prototype.canMoveHero = function() { var direction = core.getHeroLoc('direction'); var nowBlock = core.getBlock(core.getHeroLoc('x'),core.getHeroLoc('y')); if (nowBlock!=null){ @@ -1416,11 +1454,13 @@ core.prototype.canMove = function() { return true; } +////// 让勇士开始移动 ////// core.prototype.moveHero = function (direction) { core.setHeroLoc('direction', direction); core.status.heroStop = false; } +/////// 使用事件让勇士移动。这个函数将不会触发任何事件 ////// core.prototype.eventMoveHero = function(steps, time, callback) { time = time || 100; @@ -1481,6 +1521,7 @@ core.prototype.eventMoveHero = function(steps, time, callback) { }, time/8); } +////// 每移动一格后执行的事件 ////// core.prototype.moveOneStep = function() { // 中毒状态 if (core.hasFlag('poison')) { @@ -1495,6 +1536,7 @@ core.prototype.moveOneStep = function() { } } +////// 停止勇士的一切行动,等待勇士行动结束后,再执行callback ////// core.prototype.waitHeroToStop = function(callback) { core.stopAutomaticRoute(); core.clearContinueAutomaticRoute(); @@ -1507,10 +1549,12 @@ core.prototype.waitHeroToStop = function(callback) { } } +////// 停止勇士的移动状态 ////// core.prototype.stopHero = function () { core.status.heroStop = true; } +////// 绘制勇士 ////// core.prototype.drawHero = function (direction, x, y, status, offsetX, offsetY) { offsetX = offsetX || 0; offsetY = offsetY || 0; @@ -1523,13 +1567,54 @@ core.prototype.drawHero = function (direction, x, y, status, offsetX, offsetY) { core.canvas.hero.drawImage(core.material.images.hero, heroIcon[status] * 32, heroIcon.loc * height, 32, height, x + offsetX, y + offsetY + 32-height, 32, height); } +////// 设置勇士的位置 ////// +core.prototype.setHeroLoc = function (itemName, itemVal) { + if (itemVal == '++') { + core.status.hero.loc[itemName]++; + return; + } + else if (itemVal == '--') { + core.status.hero.loc[itemName]--; + return; + } + core.status.hero.loc[itemName] = itemVal; +} + +////// 获得勇士的位置 ////// +core.prototype.getHeroLoc = function (itemName) { + if (!core.isset(itemName)) return core.status.hero.loc; + return core.status.hero.loc[itemName]; +} + +////// 获得勇士面对位置的x坐标 ////// +core.prototype.nextX = function() { + var scan = { + 'up': {'x': 0, 'y': -1}, + 'left': {'x': -1, 'y': 0}, + 'down': {'x': 0, 'y': 1}, + 'right': {'x': 1, 'y': 0} + }; + return core.getHeroLoc('x')+scan[core.getHeroLoc('direction')].x; +} + +////// 获得勇士面对位置的y坐标 ////// +core.prototype.nextY = function () { + var scan = { + 'up': {'x': 0, 'y': -1}, + 'left': {'x': -1, 'y': 0}, + 'down': {'x': 0, 'y': 1}, + 'right': {'x': 1, 'y': 0} + }; + return core.getHeroLoc('y')+scan[core.getHeroLoc('direction')].y; +} + /////////// 自动行走 & 行走控制 END /////////// /////////// 地图处理 /////////// -// 开门 +////// 开门 ////// core.prototype.openDoor = function (id, x, y, needKey, callback) { if (core.interval.openDoorAnimate!=null) return; @@ -1580,7 +1665,7 @@ core.prototype.openDoor = function (id, x, y, needKey, callback) { }, speed) } -// 战斗 +////// 战斗 ////// core.prototype.battle = function (id, x, y, force, callback) { if (core.status.moveStepBeforeStop.length==0) { core.status.moveStepBeforeStop=core.status.autoStepRoutes.slice(core.status.autoStep-1,core.status.autoStepRoutes.length); @@ -1609,6 +1694,7 @@ core.prototype.battle = function (id, x, y, force, callback) { } } +////// 战斗完毕 ////// core.prototype.afterBattle = function(id, x, y, callback) { core.status.hero.hp -= core.enemys.getDamage(id); if (core.status.hero.hp<=0) { @@ -1641,6 +1727,7 @@ core.prototype.afterBattle = function(id, x, y, callback) { } +////// 触发(x,y)点的事件 ////// core.prototype.trigger = function (x, y) { var mapBlocks = core.status.thisMap.blocks; var noPass; @@ -1667,7 +1754,7 @@ core.prototype.trigger = function (x, y) { } } -// 楼层切换 +////// 楼层切换 ////// core.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback) { time = time || 800; time /= 20; @@ -1676,6 +1763,8 @@ core.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback) core.stopAutomaticRoute(); core.clearContinueAutomaticRoute(); core.dom.floorNameLabel.innerHTML = core.status.maps[floorId].title; + if (!core.isset(stair) && !core.isset(heroLoc)) + heroLoc = core.status.hero.loc; if (core.isset(stair)) { if (!core.isset(heroLoc)) heroLoc={}; var blocks = core.status.maps[floorId].blocks; @@ -1710,6 +1799,11 @@ core.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback) core.statusBar.floor.style.fontStyle = 'italic'; else core.statusBar.floor.style.fontStyle = 'normal'; + // 更改BGM + if (core.isset(core.floors[floorId].bgm)) { + core.playBgm(core.floors[floorId].bgm); + } + // 不存在事件时,更改画面色调 if (core.status.event.id == null) { // 默认画面色调 @@ -1750,7 +1844,7 @@ core.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback) }, 50); } -// 地图切换 +////// 地图切换动画效果 ////// core.prototype.mapChangeAnimate = function (mode, time, callback) { if (mode == 'show') { core.show(core.dom.floorMsgGroup, time, function () { @@ -1764,6 +1858,7 @@ core.prototype.mapChangeAnimate = function (mode, time, callback) { } } +////// 清除地图 ////// core.prototype.clearMap = function (map, x, y, width, height) { if (map == 'all') { for (var m in core.canvas) { @@ -1775,6 +1870,7 @@ core.prototype.clearMap = function (map, x, y, width, height) { } } +////// 在某个canvas上绘制一段文字 ////// core.prototype.fillText = function (map, text, x, y, style, font) { if (core.isset(style)) { core.setFillStyle(map, style); @@ -1785,6 +1881,7 @@ core.prototype.fillText = function (map, text, x, y, style, font) { core.canvas[map].fillText(text, x, y); } +////// 在某个canvas上绘制一个矩形 ////// core.prototype.fillRect = function (map, x, y, width, height, style) { if (core.isset(style)) { core.setFillStyle(map, style); @@ -1792,6 +1889,7 @@ core.prototype.fillRect = function (map, x, y, width, height, style) { core.canvas[map].fillRect(x, y, width, height); } +////// 在某个canvas上绘制一个矩形的边框 ////// core.prototype.strokeRect = function (map, x, y, width, height, style, lineWidth) { if (core.isset(style)) { core.setStrokeStyle(map, style); @@ -1802,6 +1900,7 @@ core.prototype.strokeRect = function (map, x, y, width, height, style, lineWidth core.canvas[map].strokeRect(x, y, width, height); } +////// 在某个canvas上绘制一条线 ////// core.prototype.drawLine = function (map, x1, y1, x2, y2, style, lineWidth) { if (core.isset(style)) { core.setStrokeStyle(map, style); @@ -1815,10 +1914,12 @@ core.prototype.drawLine = function (map, x1, y1, x2, y2, style, lineWidth) { core.canvas[map].stroke(); } +////// 设置某个canvas的文字字体 ////// core.prototype.setFont = function (map, font) { core.canvas[map].font = font; } +////// 设置某个canvas的线宽度 ////// core.prototype.setLineWidth = function (map, lineWidth) { if (map == 'all') { for (var m in core.canvas) { @@ -1828,14 +1929,17 @@ core.prototype.setLineWidth = function (map, lineWidth) { core.canvas[map].lineWidth = lineWidth; } +////// 保存某个canvas状态 ////// core.prototype.saveCanvas = function (map) { core.canvas[map].save(); } +////// 加载某个canvas状态 ////// core.prototype.loadCanvas = function (map) { core.canvas[map].restore(); } +////// 设置某个canvas边框属性 ////// core.prototype.setStrokeStyle = function (map, style) { if (map == 'all') { for (var m in core.canvas) { @@ -1847,6 +1951,7 @@ core.prototype.setStrokeStyle = function (map, style) { } } +////// 设置某个canvas的alpha值 ////// core.prototype.setAlpha = function (map, alpha) { if (map == 'all') { for (var m in core.canvas) { @@ -1856,6 +1961,7 @@ core.prototype.setAlpha = function (map, alpha) { else core.canvas[map].globalAlpha = alpha; } +////// 设置某个canvas的透明度 ////// core.prototype.setOpacity = function (map, opacity) { if (map == 'all') { for (var m in core.canvas) { @@ -1865,6 +1971,7 @@ core.prototype.setOpacity = function (map, opacity) { else core.canvas[map].canvas.style.opacity = opacity; } +////// 设置某个canvas的绘制属性(如颜色等) ////// core.prototype.setFillStyle = function (map, style) { if (map == 'all') { for (var m in core.canvas) { @@ -1876,11 +1983,7 @@ core.prototype.setFillStyle = function (map, style) { } } -/** - * 地图绘制 - * @param mapName 地图ID - * @param callback 绘制完毕后的回调函数 - */ +////// 绘制某张地图 ////// core.prototype.drawMap = function (mapName, callback) { var mapData = core.status.maps[mapName]; var mapBlocks = mapData.blocks; @@ -1921,6 +2024,7 @@ core.prototype.drawMap = function (mapName, callback) { callback(); } +////// 绘制Autotile ////// core.prototype.drawAutotile = function (floorId, canvas, autotileMaps, left, top, size, autotileId) { if (!core.isset(autotileId)) { @@ -1966,6 +2070,7 @@ core.prototype.drawAutotile = function (floorId, canvas, autotileMaps, left, top } } +////// 绘制Autotile的某一块 ////// core.prototype.drawAutotileBlock = function (floorId, map, x, y, size, autotile, index) { var canvas = core.canvas[map]; var groundId = core.floors[floorId].defaultGround || "ground"; @@ -2049,51 +2154,53 @@ core.prototype.drawAutotileBlock = function (floorId, map, x, y, size, autotile, } } -core.prototype.autotileExists = function (x, y, floorId) { - var block = core.getBlock(x,y,floorId); - if (block==null) return false; - return block.block.event.cls == 'autotile'; -} - +////// 某个点是否不可通行 ////// core.prototype.noPassExists = function (x, y, floorId) { var block = core.getBlock(x,y,floorId); if (block==null) return false; return core.isset(block.block.event.noPass) && block.block.event.noPass; } +////// 某个点是否在区域内且不可通行 ////// core.prototype.noPass = function (x, y) { return x<0 || x>12 || y<0 || y>12 || core.noPassExists(x,y); } +////// 某个点是否存在NPC ////// core.prototype.npcExists = function (x, y, floorId) { var block = core.getBlock(x,y,floorId); if (block==null) return false; return block.block.event.cls == 'npcs'; } +////// 某个点是否存在(指定的)地形 ////// core.prototype.terrainExists = function (x, y, id, floorId) { var block = core.getBlock(x,y,floorId); if (block==null) return false; - return block.block.event.cls=='terrains' && block.block.event.id==id; + return block.block.event.cls=='terrains' && (core.isset(id)?block.block.event.id==id:true); } +////// 某个点是否存在楼梯 ////// core.prototype.stairExists = function (x, y, floorId) { var block = core.getBlock(x,y,floorId); if (block==null) return false; return block.block.event.cls=='terrains' && (block.block.event.id=='upFloor' || block.block.event.id=='downFloor'); } +////// 当前位置是否在楼梯边 ////// core.prototype.nearStair = function() { var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'); return core.stairExists(x,y) || core.stairExists(x-1,y) || core.stairExists(x,y-1) || core.stairExists(x+1,y) || core.stairExists(x,y+1); } +////// 某个点是否存在(指定的)怪物 ////// core.prototype.enemyExists = function (x, y, id,floorId) { var block = core.getBlock(x,y,floorId); if (block==null) return false; return block.block.event.cls=='enemys' && (core.isset(id)?block.block.event.id==id:true); } +////// 获得某个点的block ////// core.prototype.getBlock = function (x, y, floorId, needEnable) { if (!core.isset(floorId)) floorId=core.status.floorId; if (!core.isset(needEnable)) needEnable=true; @@ -2107,6 +2214,7 @@ core.prototype.getBlock = function (x, y, floorId, needEnable) { return null; } +////// 显示移动某块的动画,达到{“type”:”move”}的效果 ////// core.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) { time = time || 500; @@ -2206,6 +2314,7 @@ core.prototype.moveBlock = function(x,y,steps,time,immediateHide,callback) { }, time/16); } +////// 显示/隐藏某个块时的动画效果 ////// core.prototype.animateBlock = function (x,y,type,time,callback) { if (type!='hide') type='show'; @@ -2248,8 +2357,8 @@ core.prototype.animateBlock = function (x,y,type,time,callback) { }, time/10); } -// 显示一个事件 -core.prototype.addBlock = function(x,y,floodId) { +////// 将某个块从禁用变成启用状态 ////// +core.prototype.showBlock = function(x, y, floodId) { floodId = floodId || core.status.floorId; var block = core.getBlock(x,y,floodId,false); if (block==null) return; // 不存在 @@ -2268,6 +2377,7 @@ core.prototype.addBlock = function(x,y,floodId) { } } +////// 将某个块从启用变成禁用状态 ////// core.prototype.removeBlock = function (x, y, floorId) { floorId = floorId || core.status.floorId; @@ -2287,7 +2397,7 @@ core.prototype.removeBlock = function (x, y, floorId) { core.updateFg(); } - +////// 根据block的索引删除该块 ////// core.prototype.removeBlockById = function (index, floorId) { var blocks = core.status.maps[floorId].blocks; @@ -2306,12 +2416,14 @@ core.prototype.removeBlockById = function (index, floorId) { blocks[index].enable = false; } +////// 一次性删除多个block ////// core.prototype.removeBlockByIds = function (floorId, ids) { ids.sort(function (a,b) {return b-a}).forEach(function (id) { core.removeBlockById(id, floorId); }); } +////// 添加一个全局动画 ////// core.prototype.addGlobalAnimate = function (animateMore, x, y, loc, image) { if (animateMore == 2) { core.status.twoAnimateObjs.push({ @@ -2333,6 +2445,7 @@ core.prototype.addGlobalAnimate = function (animateMore, x, y, loc, image) { } } +////// 删除一个或所有全局动画 ////// core.prototype.removeGlobalAnimate = function (x, y, all) { if (all == true) { core.status.twoAnimateObjs = []; @@ -2352,6 +2465,7 @@ core.prototype.removeGlobalAnimate = function (x, y, all) { } } +////// 设置全局动画的显示效果 ////// core.prototype.setGlobalAnimate = function (speed) { clearInterval(core.interval.twoAnimate); clearInterval(core.interval.fourAnimate); @@ -2380,6 +2494,7 @@ core.prototype.setGlobalAnimate = function (speed) { }, speed / 2); } +////// 同步所有的全局动画效果 ////// core.prototype.syncGlobalAnimate = function () { core.status.twoAnimateObjs.forEach(function (t) { t.status=0; @@ -2389,6 +2504,7 @@ core.prototype.syncGlobalAnimate = function () { }) } +////// 显示UI层某个box的动画 ////// core.prototype.setBoxAnimate = function () { clearInterval(core.interval.boxAnimate); if (core.status.boxAnimateObjs.length > 0) { @@ -2400,6 +2516,7 @@ core.prototype.setBoxAnimate = function () { } } +////// 绘制UI层的box动画 ////// core.prototype.drawBoxAnimate = function (background) { for (var a = 0; a < core.status.boxAnimateObjs.length; a++) { var obj = core.status.boxAnimateObjs[a]; @@ -2411,7 +2528,7 @@ core.prototype.drawBoxAnimate = function (background) { } } -// 更新领域、显伤 +////// 更新领域、夹击、阻击的伤害地图 ////// core.prototype.updateCheckBlock = function() { core.status.checkBlock = {}; if (!core.isset(core.status.thisMap)) return; @@ -2505,8 +2622,8 @@ core.prototype.updateCheckBlock = function() { } } +////// 检查并执行领域、夹击、阻击事件 ////// core.prototype.checkBlock = function () { - // 检查领域、夹击事件 var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'); var damage = core.status.checkBlock.damage[13*x+y]; if (damage>0) { @@ -2532,14 +2649,14 @@ core.prototype.checkBlock = function () { } } - if (core.status.checkBlock.betweenAttack[13*x+y]) { + if (core.status.checkBlock.betweenAttack[13*x+y] && damage>0) { core.drawTip('受到夹击,生命变成一半'); } // 阻击 - else if (snipe.length>0) { + else if (snipe.length>0 && damage>0) { core.drawTip('受到阻击伤害'+damage+'点'); } - else { + else if (damage>0) { core.drawTip('受到领域伤害'+damage+'点'); } if (core.status.hero.hp<=0) { @@ -2560,6 +2677,7 @@ core.prototype.checkBlock = function () { } } +////// 阻击事件(动画效果) ////// core.prototype.snipe = function (snipes) { core.waitHeroToStop(function() { core.lockControl(); @@ -2664,6 +2782,7 @@ core.prototype.snipe = function (snipes) { }); } +////// 更改画面色调 ////// core.prototype.setFg = function(color, time, callback) { if (!core.isset(time)) time=750; if (time<=0) time=0; @@ -2718,47 +2837,7 @@ core.prototype.setFg = function(color, time, callback) { } - -core.prototype.setHeroLoc = function (itemName, itemVal) { - if (itemVal == '++') { - core.status.hero.loc[itemName]++; - return; - } - else if (itemVal == '--') { - core.status.hero.loc[itemName]--; - return; - } - core.status.hero.loc[itemName] = itemVal; -} - -core.prototype.getHeroLoc = function (itemName) { - if (!core.isset(itemName)) return core.status.hero.loc; - return core.status.hero.loc[itemName]; -} - -core.prototype.nextX = function() { - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; - return core.getHeroLoc('x')+scan[core.getHeroLoc('direction')].x; -} - -core.prototype.nextY = function () { - var scan = { - 'up': {'x': 0, 'y': -1}, - 'left': {'x': -1, 'y': 0}, - 'down': {'x': 0, 'y': 1}, - 'right': {'x': 1, 'y': 0} - }; - return core.getHeroLoc('y')+scan[core.getHeroLoc('direction')].y; -} - -/** - * 更新显伤 - */ +////// 更新全地图显伤 ////// core.prototype.updateFg = function () { if (!core.isset(core.status.thisMap) || !core.isset(core.status.thisMap.blocks)) return; @@ -2821,9 +2900,7 @@ core.prototype.updateFg = function () { } } -/** - * 物品处理 start - */ +////// 获得某个物品的个数 ////// core.prototype.itemCount = function (itemId) { if (!core.isset(itemId) || !core.isset(core.material.items[itemId])) return 0; var itemCls = core.material.items[itemId].cls; @@ -2831,10 +2908,12 @@ core.prototype.itemCount = function (itemId) { return core.isset(core.status.hero.items[itemCls][itemId]) ? core.status.hero.items[itemCls][itemId] : 0; } +////// 是否存在某个物品 ////// core.prototype.hasItem = function (itemId) { return core.itemCount(itemId) > 0; } +////// 设置某个物品的个数 ////// core.prototype.setItem = function (itemId, itemNum) { var itemCls = core.material.items[itemId].cls; if (itemCls == 'items') return; @@ -2844,6 +2923,7 @@ core.prototype.setItem = function (itemId, itemNum) { core.status.hero.items[itemCls][itemId] = itemNum; } +////// 删除某个物品 ////// core.prototype.removeItem = function (itemId) { if (!core.hasItem(itemId)) return false; var itemCls = core.material.items[itemId].cls; @@ -2855,15 +2935,18 @@ core.prototype.removeItem = function (itemId) { return true; } +////// 使用某个物品 ////// core.prototype.useItem = function (itemId) { core.items.useItem(itemId); return; } +////// 能否使用某个物品 ////// core.prototype.canUseItem = function (itemId) { return core.items.canUseItem(itemId); } +////// 增加某个物品的个数 ////// core.prototype.addItem = function (itemId, itemNum) { var itemData = core.material.items[itemId]; var itemCls = itemData.cls; @@ -2878,6 +2961,7 @@ core.prototype.addItem = function (itemId, itemNum) { core.status.hero.items[itemCls][itemId] += itemNum; } +////// 获得面前的物品(轻按) ////// core.prototype.getNextItem = function() { if (!core.status.heroStop || !core.flags.enableGentleClick) return; var nextX = core.nextX(), nextY = core.nextY(); @@ -2888,6 +2972,7 @@ core.prototype.getNextItem = function() { } } +////// 获得某个物品 ////// core.prototype.getItem = function (itemId, itemNum, itemX, itemY, callback) { // core.getItemAnimate(itemId, itemNum, itemX, itemY); core.playSound('item.ogg'); @@ -2909,6 +2994,7 @@ core.prototype.getItem = function (itemId, itemNum, itemX, itemY, callback) { else if (core.isset(callback)) callback(); } +////// 左上角绘制一段提示 ////// core.prototype.drawTip = function (text, itemIcon) { var textX, textY, width, height, hide = false, opacityVal = 0; clearInterval(core.interval.tipAnimate); @@ -2964,6 +3050,7 @@ core.prototype.drawTip = function (text, itemIcon) { }, 30); } +////// 地图中间绘制一段文字 ////// core.prototype.drawText = function (contents, callback) { if (core.isset(contents)) { if (typeof contents == 'string') { @@ -3006,18 +3093,19 @@ core.prototype.drawText = function (contents, callback) { /////////// 地图相关 END /////////// -/** - * 系统机制 start - */ -// 替换文本中的数为实际值 + + +/////////// 系统机制 /////////// + +////// 将文字中的${和}(表达式)进行替换 ////// core.prototype.replaceText = function (text) { return text.replace(/\${([^}]+)}/g, function (word, value) { return core.calValue(value); }); } - +////// 计算表达式的值 ////// core.prototype.calValue = function (value) { value=value.replace(/status:([\w\d_]+)/g, "core.getStatus('$1')"); value=value.replace(/item:([\w\d_]+)/g, "core.itemCount('$1')"); @@ -3025,6 +3113,7 @@ core.prototype.calValue = function (value) { return eval(value); } +////// 执行一个表达式的effect操作 ////// core.prototype.doEffect = function (expression) { // 必须使用"+=" var arr = expression.split("+="); @@ -3040,6 +3129,7 @@ core.prototype.doEffect = function (expression) { } } +////// 字符串自动换行的分割 ////// core.prototype.splitLines = function(canvas, text, maxLength, font) { if (core.isset(font)) core.setFont(canvas, font); @@ -3064,6 +3154,7 @@ core.prototype.splitLines = function(canvas, text, maxLength, font) { return contents; } +////// 向某个数组前插入另一个数组或元素 ////// core.prototype.unshift = function (a,b) { if (!(a instanceof Array) || !core.isset(b)) return; if (b instanceof Array) { @@ -3075,6 +3166,7 @@ core.prototype.unshift = function (a,b) { return a; } +////// 设置本地存储 ////// core.prototype.setLocalStorage = function(key, value) { try { localStorage.setItem(core.firstData.name + "_" + key, JSON.stringify(value)); @@ -3085,16 +3177,20 @@ core.prototype.setLocalStorage = function(key, value) { return false; } } + +////// 获得本地存储 ////// core.prototype.getLocalStorage = function(key, defaultValue) { var value = localStorage.getItem(core.firstData.name+"_"+key); if (core.isset(value)) return JSON.parse(value); return defaultValue; } +////// 移除本地存储 ////// core.prototype.removeLocalStorage = function (key) { localStorage.removeItem(core.firstData.name+"_"+key); } +////// 深拷贝一个对象 ////// core.prototype.clone = function (data) { if (!core.isset(data)) return data; // date @@ -3129,25 +3225,19 @@ core.prototype.clone = function (data) { return data; } +////// 格式化时间为字符串 ////// core.prototype.formatDate = function(date) { if (!core.isset(date)) return ""; return date.getFullYear()+"-"+core.setTwoDigits(date.getMonth()+1)+"-"+core.setTwoDigits(date.getDate())+" " +core.setTwoDigits(date.getHours())+":"+core.setTwoDigits(date.getMinutes())+":"+core.setTwoDigits(date.getSeconds()); } +////// 两位数显示 ////// core.prototype.setTwoDigits = function (x) { return parseInt(x)<10?"0"+x:x; } -core.prototype.win = function(reason) { - core.events.win(reason); -} - -core.prototype.lose = function(reason) { - core.events.lose(reason); -} - -// 作弊 +////// 作弊 ////// core.prototype.debug = function() { core.setStatus('hp', 999999); core.setStatus('atk', 10000); @@ -3167,9 +3257,10 @@ core.prototype.debug = function() { core.drawTip("作弊成功"); } -core.prototype.checkStatus = function (name, need, item, clearData) { +////// 判断当前能否进入某个事件 ////// +core.prototype.checkStatus = function (name, need, item) { if (need && core.status.event.id == name) { - core.ui.closePanel(clearData); + core.ui.closePanel(); return false; } @@ -3189,12 +3280,14 @@ core.prototype.checkStatus = function (name, need, item, clearData) { return true; } +////// 点击怪物手册时的打开操作 ////// core.prototype.openBook = function (need) { - if (!core.checkStatus('book', need, true, true)) + if (!core.checkStatus('book', need, true)) return; core.useItem('book'); } +////// 点击楼层传送器时的打开操作 ////// core.prototype.useFly = function (need) { if (!core.checkStatus('fly', need, true)) return; @@ -3216,18 +3309,21 @@ core.prototype.useFly = function (need) { return; } +////// 点击工具栏时的打开操作 ////// core.prototype.openToolbox = function (need) { if (!core.checkStatus('toolbox', need)) return; core.ui.drawToolbox(); } +////// 点击保存按钮时的打开操作 ////// core.prototype.save = function(need) { if (!core.checkStatus('save', need)) return; core.ui.drawSLPanel(core.status.saveIndex); } +////// 点击读取按钮时的打开操作 ////// core.prototype.load = function (need) { // 游戏开始前读档 @@ -3244,6 +3340,7 @@ core.prototype.load = function (need) { core.ui.drawSLPanel(core.status.saveIndex); } +////// 实际进行存读档事件 ////// core.prototype.doSL = function (id, type) { core.status.saveIndex=id; if (type=='save') { @@ -3277,6 +3374,7 @@ core.prototype.doSL = function (id, type) { } } +////// 存档同步操作 ////// core.prototype.syncSave = function(type) { if (type=='save') { core.status.event.selection=1; @@ -3405,6 +3503,7 @@ core.prototype.syncSave = function(type) { } +////// 存档到本地 ////// core.prototype.saveData = function(dataId) { var data = { 'floorId': core.status.floorId, @@ -3427,6 +3526,7 @@ core.prototype.saveData = function(dataId) { return core.setLocalStorage(dataId, data); } +////// 从本地读档 ////// core.prototype.loadData = function (data, callback) { core.resetStatus(data.hero, data.hard, data.floorId, core.maps.load(data.maps)); @@ -3445,24 +3545,29 @@ core.prototype.loadData = function (data, callback) { }); } +////// 设置勇士属性 ////// core.prototype.setStatus = function (statusName, statusVal) { core.status.hero[statusName] = statusVal; } +////// 获得勇士属性 ////// core.prototype.getStatus = function (statusName) { return core.status.hero[statusName]; } +////// 获得某个等级的名称 ////// core.prototype.getLvName = function () { if (core.status.hero.lv>core.firstData.levelUp.length) return core.status.hero.lv; return core.firstData.levelUp[core.status.hero.lv-1].name || core.status.hero.lv; } +////// 设置某个自定义变量或flag ////// core.prototype.setFlag = function(flag, value) { if (!core.isset(core.status.hero)) return; core.status.hero.flags[flag]=value; } +////// 获得某个自定义变量或flag ////// core.prototype.getFlag = function(flag, defaultValue) { if (!core.isset(core.status.hero)) return defaultValue; var value = core.status.hero.flags[flag]; @@ -3470,24 +3575,28 @@ core.prototype.getFlag = function(flag, defaultValue) { return defaultValue; } -// 只有不为0或false时才会返回true +////// 是否存在某个自定义变量或flag,且值为true ////// core.prototype.hasFlag = function(flag) { if (core.getFlag(flag)) return true; return false; } +////// 往当前事件列表之前插入一系列事件 ////// core.prototype.insertAction = function (list) { core.events.insertAction(list); } +////// 锁定状态栏,常常用于事件处理 ////// core.prototype.lockControl = function () { core.status.lockControl = true; } +////// 解锁状态栏 ////// core.prototype.unLockControl = function () { core.status.lockControl = false; } +////// 判断某对象是否不为undefined也不会null ////// core.prototype.isset = function (val) { if (val == undefined || val == null) { return false; @@ -3495,6 +3604,7 @@ core.prototype.isset = function (val) { return true } +////// 播放背景音乐 ////// core.prototype.playBgm = function (bgm) { // 如果不允许播放 @@ -3530,6 +3640,7 @@ core.prototype.playBgm = function (bgm) { } } +////// 暂停背景音乐的播放 ////// core.prototype.pauseBgm = function () { // 直接暂停播放 try { @@ -3544,7 +3655,12 @@ core.prototype.pauseBgm = function () { } } +////// 恢复背景音乐的播放 ////// core.prototype.resumeBgm = function () { + + // 如果不允许播放 + if (!core.musicStatus.bgmStatus) return; + // 恢复BGM try { if (core.isset(core.musicStatus.playingBgm)) { @@ -3564,6 +3680,7 @@ core.prototype.resumeBgm = function () { } } +////// 播放音频 ////// core.prototype.playSound = function (sound) { // 如果不允许播放 @@ -3597,27 +3714,7 @@ core.prototype.playSound = function (sound) { } } -core.prototype.changeSoundStatus = function () { - if (core.musicStatus.soundStatus) { - main.core.disabledSound(); - } - else { - main.core.enabledSound(); - } -} - -core.prototype.enabledSound = function () { - core.musicStatus.soundStatus = true; - core.playBgm('bgm', 'mp3'); - core.setLocalStorage('soundStatus', true); -} - -core.prototype.disabledSound = function () { - core.musicStatus.playedBgm.pause(); - core.musicStatus.soundStatus = false; - core.setLocalStorage('soundStatus', false); -} - +////// 动画显示某对象 ////// core.prototype.show = function (obj, speed, callback) { if (!core.isset(speed)) { obj.style.display = 'block'; @@ -3638,6 +3735,7 @@ core.prototype.show = function (obj, speed, callback) { }, speed); } +////// 动画使某对象消失 ////// core.prototype.hide = function (obj, speed, callback) { if (!core.isset(speed)) { obj.style.display = 'none'; @@ -3658,8 +3756,7 @@ core.prototype.hide = function (obj, speed, callback) { } -////// 状态栏相关 ////// - +////// 清空状态栏 ////// core.prototype.clearStatusBar = function() { var statusList = ['floor', 'lv', 'hp', 'atk', 'def', 'mdef', 'money', 'experience', 'up', 'yellowKey', 'blueKey', 'redKey', 'poison', 'weak', 'curse', 'hard']; statusList.forEach(function (e) { @@ -3669,13 +3766,11 @@ core.prototype.clearStatusBar = function() { core.statusBar.image.fly.style.opacity = 0.3; } -/** - * 更新状态栏 - */ +////// 更新状态栏 ////// core.prototype.updateStatusBar = function () { // 检查等级 - core.checkLvUp(); + core.events.checkLvUp(); // 检查HP上限 if (core.values.HPMAX>0) { @@ -3725,32 +3820,7 @@ core.prototype.updateStatusBar = function () { core.updateFg(); } -core.prototype.checkLvUp = function () { - if (!core.flags.enableLevelUp || core.status.hero.lv>=core.firstData.levelUp.length) return; - // 计算下一个所需要的数值 - var need=core.firstData.levelUp[core.status.hero.lv].need; - if (!core.isset(need)) return; - if (core.status.hero.experience>=need) { - // 升级 - core.status.hero.lv++; - var effect = core.firstData.levelUp[core.status.hero.lv-1].effect; - if (typeof effect == "string") { - if (effect.indexOf("function")==0) { - eval("("+effect+")()"); - } - else { - effect.split(";").forEach(function (t) { - core.doEffect(t); - }); - } - } - else if (effect instanceof Function) { - effect(); - } - core.checkLvUp(); - } -} - +////// 屏幕分辨率改变后重新自适应 ////// core.prototype.resize = function(clientWidth, clientHeight) { // 默认画布大小 @@ -4055,6 +4125,7 @@ core.prototype.resize = function(clientWidth, clientHeight) { core.domRenderer(); } +////// 渲染DOM ////// core.prototype.domRenderer = function(){ core.dom.statusBar.style.display = 'block'; diff --git a/libs/enemys.js b/libs/enemys.js index f9e29705..1738102d 100644 --- a/libs/enemys.js +++ b/libs/enemys.js @@ -2,6 +2,7 @@ function enemys() { } +////// 初始化 ////// enemys.prototype.init = function () { // 怪物属性初始化定义: this.enemys = { @@ -68,17 +69,20 @@ enemys.prototype.init = function () { } } +////// 获得一个或所有怪物数据 ////// enemys.prototype.getEnemys = function (enemyId) { - if (enemyId == undefined) { + if (!core.isset(enemyId)) { return this.enemys; } return this.enemys[enemyId]; } +////// 判断是否含有某特殊属性 ////// enemys.prototype.hasSpecial = function (special, test) { return (special instanceof Array)?special.indexOf(test)>=0:(special!=0&&(special%100==test||this.hasSpecial(parseInt(special/100), test))); } +////// 获得所有特殊属性的名称 ////// enemys.prototype.getSpecialText = function (enemyId) { if (enemyId == undefined) return ""; var enemy = this.enemys[enemyId]; @@ -107,7 +111,7 @@ enemys.prototype.getSpecialText = function (enemyId) { return text; } -////// 获得每个属性的文字提示 ////// +////// 获得每个特殊属性的说明 ////// enemys.prototype.getSpecialHint = function (enemy, special) { if (!core.isset(special)) { var hints = []; @@ -147,6 +151,7 @@ enemys.prototype.getSpecialHint = function (enemy, special) { return "" } +////// 获得某个怪物的伤害 ////// enemys.prototype.getDamage = function (monsterId) { var monster = core.material.enemys[monsterId]; var hero_atk = core.status.hero.atk, hero_def = core.status.hero.def, hero_mdef = core.status.hero.mdef; @@ -156,6 +161,7 @@ enemys.prototype.getDamage = function (monsterId) { return damage + this.getExtraDamage(monster); } +////// 获得某个怪物的额外伤害 ////// enemys.prototype.getExtraDamage = function (monster) { var extra_damage = 0; if (this.hasSpecial(monster.special, 11)) { // 吸血 @@ -169,7 +175,7 @@ enemys.prototype.getExtraDamage = function (monster) { return extra_damage; } -// 临界值计算 +////// 临界值计算 ////// enemys.prototype.getCritical = function (monsterId) { var monster = core.material.enemys[monsterId]; if (this.hasSpecial(monster.special, 3) || this.hasSpecial(monster.special, 10)) return "???"; @@ -187,7 +193,7 @@ enemys.prototype.getCritical = function (monsterId) { return 0; } -// 临界减伤计算 +////// 临界减伤计算 ////// enemys.prototype.getCriticalDamage = function (monsterId) { var c = this.getCritical(monsterId); if (c == '???') return '???'; @@ -201,7 +207,7 @@ enemys.prototype.getCriticalDamage = function (monsterId) { monster.hp, monster.atk, monster.def, monster.special, monster.n); } -// 1防减伤计算 +////// 1防减伤计算 ////// enemys.prototype.getDefDamage = function (monsterId) { var monster = core.material.enemys[monsterId]; var nowDamage = this.calDamage(core.status.hero.atk, core.status.hero.def, core.status.hero.mdef, @@ -212,6 +218,7 @@ enemys.prototype.getDefDamage = function (monsterId) { return nowDamage - nextDamage; } +////// 具体的伤害计算公式 ////// enemys.prototype.calDamage = function (hero_atk, hero_def, hero_mdef, mon_hp, mon_atk, mon_def, mon_special, n) { if (this.hasSpecial(mon_special, 20) && !core.hasItem("cross")) // 如果是无敌属性,且勇士未持有十字架 @@ -254,7 +261,7 @@ enemys.prototype.calDamage = function (hero_atk, hero_def, hero_mdef, mon_hp, mo return core.flags.enableNegativeDamage?ans:Math.max(0, ans); } -// 获得当前楼层的怪物列表 +////// 获得当前楼层的怪物列表 ////// enemys.prototype.getCurrentEnemys = function () { var enemys = []; var used = {}; diff --git a/libs/events.js b/libs/events.js index cd866e90..cf66d51e 100644 --- a/libs/events.js +++ b/libs/events.js @@ -2,6 +2,7 @@ function events() { } +////// 初始化 ////// events.prototype.init = function () { this.events = { 'battle': function (data, core, callback) { @@ -45,9 +46,9 @@ events.prototype.init = function () { } } -// 初始化 +////// 获得一个或所有系统事件类型 ////// events.prototype.getEvents = function (eventName) { - if (eventName == undefined) { + if (!core.isset(eventName)) { return this.events; } return this.events[eventName]; @@ -87,12 +88,14 @@ events.prototype.startGame = function (hard) { }) } -////// 简单难度设置初始福利 ////// +////// 不同难度分别设置初始属性 ////// events.prototype.setInitData = function (hard) { if (hard=='Easy') { // 简单难度 core.setFlag('hard', 1); // 可以用flag:hard来获得当前难度 // 可以在此设置一些初始福利,比如设置初始生命值可以调用: // core.setStatus("hp", 10000); + // 赠送一把黄钥匙可以调用 + // core.setItem("yellowKey", 1); } if (hard=='Normal') { // 普通难度 core.setFlag('hard', 2); // 可以用flag:hard来获得当前难度 @@ -102,9 +105,8 @@ events.prototype.setInitData = function (hard) { } } -////// 游戏结束事件 ////// +////// 游戏获胜事件 ////// events.prototype.win = function(reason) { - // 获胜 core.waitHeroToStop(function() { core.removeGlobalAnimate(0,0,true); core.clearMap('all'); // 清空全地图 @@ -116,8 +118,8 @@ events.prototype.win = function(reason) { }); } +////// 游戏失败事件 ////// events.prototype.lose = function(reason) { - // 失败 core.waitHeroToStop(function() { core.drawText([ "\t[结局1]你死了。\n如题。" @@ -133,20 +135,9 @@ events.prototype.afterChangeFloor = function (floorId) { this.doEvents(core.floors[floorId].firstArrive); core.setFlag("visited_"+floorId, true); } - - // 播放BGM - if (floorId == 'sample0') { - core.playBgm('bgm.mp3'); - } - if (floorId == 'sample1') { - core.playBgm('star.mid'); - } - if (floorId == 'sample2') { - core.playBgm('qianjin.mid'); - } } -////// 实际事件的处理 ////// +////// 开始执行一系列自定义事件 ////// events.prototype.doEvents = function (list, x, y, callback) { // 停止勇士 core.waitHeroToStop(function() { @@ -162,6 +153,7 @@ events.prototype.doEvents = function (list, x, y, callback) { }); } +////// 执行当前自定义事件列表中的下一个事件 ////// events.prototype.doAction = function() { // 清空boxAnimate和UI层 clearInterval(core.interval.boxAnimate); @@ -172,7 +164,7 @@ events.prototype.doAction = function() { if (core.status.event.data.list.length==0) { if (core.isset(core.status.event.data.callback)) core.status.event.data.callback(); - core.ui.closePanel(false); + core.ui.closePanel(); return; } @@ -201,12 +193,12 @@ events.prototype.doAction = function() { case "show": // 显示 if (core.isset(data.time) && data.time>0 && (!core.isset(data.floorId) || data.floorId==core.status.floorId)) { core.animateBlock(data.loc[0],data.loc[1],'show', data.time, function () { - core.addBlock(data.loc[0],data.loc[1],data.floorId); + core.showBlock(data.loc[0],data.loc[1],data.floorId); core.events.doAction(); }); } else { - core.addBlock(data.loc[0],data.loc[1],data.floorId) + core.showBlock(data.loc[0],data.loc[1],data.floorId) this.doAction(); } break; @@ -418,7 +410,7 @@ events.prototype.insertAction = function (action) { } } -////// 打开商店 ////// +////// 打开一个全局商店 ////// events.prototype.openShop = function(shopId, needVisited) { var shop = core.status.shops[shopId]; shop.times = shop.times || 0; @@ -460,35 +452,11 @@ events.prototype.openShop = function(shopId, needVisited) { core.ui.drawChoices(content, choices); } +////// 禁用一个全局商店 ////// events.prototype.disableQuickShop = function (shopId) { core.status.shops[shopId].visited = false; } -////// 降低难度 ////// - -events.prototype.decreaseHard = function() { - core.drawTip("本塔不支持降低难度!"); - /* - if (core.status.hard == 0) { - core.drawTip("当前已是难度0,不能再降低难度了"); - return; - } - var add = 100, x=core.status.hard; - while (x<10) { - x++; add*=2; - } - core.ui.drawConfirmBox("本次操作可生命+" + add + ",确定吗?", function () { - core.status.hero.hp += add; - core.status.hard--; - core.updateStatusBar(); - core.ui.closePanel(); - core.drawTip("降低难度成功,生命+" + add); - }, function () { - core.ui.drawSettings(false); - }); - */ -} - ////// 能否使用快捷商店 ////// events.prototype.canUseQuickShop = function(shopIndex) { if (core.isset(core.floors[core.status.floorId].canUseQuickShop) && !core.isset(core.floors[core.status.floorId].canUseQuickShop)) @@ -497,9 +465,36 @@ events.prototype.canUseQuickShop = function(shopIndex) { return null; } +////// 检查升级事件 ////// +events.prototype.checkLvUp = function () { + if (!core.flags.enableLevelUp || core.status.hero.lv>=core.firstData.levelUp.length) return; + // 计算下一个所需要的数值 + var need=core.firstData.levelUp[core.status.hero.lv].need; + if (!core.isset(need)) return; + if (core.status.hero.experience>=need) { + // 升级 + core.status.hero.lv++; + var effect = core.firstData.levelUp[core.status.hero.lv-1].effect; + if (typeof effect == "string") { + if (effect.indexOf("function")==0) { + eval("("+effect+")()"); + } + else { + effect.split(";").forEach(function (t) { + core.doEffect(t); + }); + } + } + else if (effect instanceof Function) { + effect(); + } + this.checkLvUp(); + } +} + ////// 尝试使用道具 ////// events.prototype.useItem = function(itemId) { - core.ui.closePanel(false); + core.ui.closePanel(); if (itemId=='book') { core.openBook(false); @@ -522,7 +517,7 @@ events.prototype.useItem = function(itemId) { else core.drawTip("当前无法使用"+core.material.items[itemId].name); } -////// 加点 ////// +////// 加点事件 ////// events.prototype.addPoint = function (enemy) { var point = enemy.point; if (!core.isset(point) || point<=0) return []; @@ -531,22 +526,21 @@ events.prototype.addPoint = function (enemy) { return [ {"type": "choices", "choices": [ - {"text": "生命+"+(200*point), "action": [ - {"type": "setValue", "name": "status:hp", "value": "status:hp+"+(200*point)} - ]}, {"text": "攻击+"+(1*point), "action": [ {"type": "setValue", "name": "status:atk", "value": "status:atk+"+(1*point)} ]}, {"text": "防御+"+(2*point), "action": [ {"type": "setValue", "name": "status:def", "value": "status:def+"+(2*point)} ]}, + {"text": "生命+"+(200*point), "action": [ + {"type": "setValue", "name": "status:hp", "value": "status:hp+"+(200*point)} + ]}, ] } ]; - } -/****** 打完怪物 ******/ +////// 战斗结束后触发的事件 ////// events.prototype.afterBattle = function(enemyId,x,y,callback) { // 毒衰咒的处理 @@ -607,7 +601,7 @@ events.prototype.afterBattle = function(enemyId,x,y,callback) { } -/****** 开完门 ******/ +////// 开一个门后触发的事件 ////// events.prototype.afterOpenDoor = function(doorId,x,y,callback) { var todo = []; @@ -628,7 +622,7 @@ events.prototype.afterOpenDoor = function(doorId,x,y,callback) { if (core.isset(callback)) callback(); } -/****** 经过路障 ******/ +////// 经过一个路障 ////// events.prototype.passNet = function (data) { // 有鞋子 if (core.hasItem('shoes')) return; @@ -659,6 +653,7 @@ events.prototype.passNet = function (data) { core.updateStatusBar(); } +////// 改变亮灯(感叹号)的事件 ////// events.prototype.changeLight = function(x, y) { var block = core.getBlock(x, y); if (block==null) return; @@ -675,32 +670,33 @@ events.prototype.changeLight = function(x, y) { this.afterChangeLight(x,y); } -// 改变灯后的事件 +////// 改变亮灯之后,可以触发的事件 ////// events.prototype.afterChangeLight = function(x,y) { } -// 使用炸弹/圣锤后的事件 +////// 使用炸弹/圣锤后的事件 ////// events.prototype.afterUseBomb = function () { } -// 存档事件前一刻的处理 +////// 即将存档前可以执行的操作 ////// events.prototype.beforeSaveData = function(data) { } -// 读档事件后,载入事件前,对数据的处理 +////// 读档事件后,载入事件前,可以执行的操作 ////// events.prototype.afterLoadData = function(data) { } -/******************************************/ -/*********** 界面上的点击事件 ***************/ -/******************************************/ +/****************************************/ +/********** 点击事件、键盘事件 ************/ +/****************************************/ +////// 按下Ctrl键时(快捷跳过对话) ////// events.prototype.keyDownCtrl = function () { if (core.status.event.id=='text') { core.drawText(); @@ -712,6 +708,7 @@ events.prototype.keyDownCtrl = function () { } } +////// 点击确认框时 ////// events.prototype.clickConfirmBox = function (x,y) { if ((x == 4 || x == 5) && y == 7 && core.isset(core.status.event.data.yes)) core.status.event.data.yes(); @@ -719,6 +716,7 @@ events.prototype.clickConfirmBox = function (x,y) { core.status.event.data.no(); } +////// 键盘操作确认框时 ////// events.prototype.keyUpConfirmBox = function (keycode) { if (keycode==37) { core.status.event.selection=0; @@ -742,7 +740,7 @@ events.prototype.keyUpConfirmBox = function (keycode) { } } -// 正在处理事件时的点击操作... +////// 自定义事件时的点击操作 ////// events.prototype.clickAction = function (x,y) { if (core.status.event.data.type=='text') { @@ -765,6 +763,7 @@ events.prototype.clickAction = function (x,y) { } } +////// 自定义事件时,按下某个键的操作 ////// events.prototype.keyDownAction = function (keycode) { if (core.status.event.data.type=='choices') { var data = core.status.event.data.current; @@ -784,6 +783,7 @@ events.prototype.keyDownAction = function (keycode) { } } +////// 自定义事件时,放开某个键的操作 ////// events.prototype.keyUpAction = function (keycode) { if (core.status.event.data.type=='text' && (keycode==13 || keycode==32 || keycode==67)) { this.doAction(); @@ -801,48 +801,49 @@ events.prototype.keyUpAction = function (keycode) { } } -// 怪物手册 +////// 怪物手册界面的点击操作 ////// events.prototype.clickBook = function(x,y) { // 上一页 if ((x == 3 || x == 4) && y == 12) { - core.ui.drawEnemyBook(core.status.event.data - 6); + core.ui.drawBook(core.status.event.data - 6); return; } // 下一页 if ((x == 8 || x == 9) && y == 12) { - core.ui.drawEnemyBook(core.status.event.data + 6); + core.ui.drawBook(core.status.event.data + 6); return; } // 返回 if (x>=10 && x<=12 && y==12) { - core.ui.closePanel(true); + core.ui.closePanel(); return; } // 怪物信息 - // var index = parseInt(y/2); var data = core.status.event.data; if (core.isset(data) && y<12) { var page=parseInt(data/6); var index=6*page+parseInt(y/2); - core.ui.drawEnemyBook(index); + core.ui.drawBook(index); core.ui.drawBookDetail(index); } return; } +////// 怪物手册界面时,按下某个键的操作 ////// events.prototype.keyDownBook = function (keycode) { - if (keycode==37) core.ui.drawEnemyBook(core.status.event.data-6); - if (keycode==38) core.ui.drawEnemyBook(core.status.event.data-1); - if (keycode==39) core.ui.drawEnemyBook(core.status.event.data+6); - if (keycode==40) core.ui.drawEnemyBook(core.status.event.data+1); - if (keycode==33) core.ui.drawEnemyBook(core.status.event.data-6); - if (keycode==34) core.ui.drawEnemyBook(core.status.event.data+6); + if (keycode==37) core.ui.drawBook(core.status.event.data-6); + if (keycode==38) core.ui.drawBook(core.status.event.data-1); + if (keycode==39) core.ui.drawBook(core.status.event.data+6); + if (keycode==40) core.ui.drawBook(core.status.event.data+1); + if (keycode==33) core.ui.drawBook(core.status.event.data-6); + if (keycode==34) core.ui.drawBook(core.status.event.data+6); return; } +////// 怪物手册界面时,放开某个键的操作 ////// events.prototype.keyUpBook = function (keycode) { if (keycode==27 || keycode==88) { - core.ui.closePanel(true); + core.ui.closePanel(); return; } if (keycode==13 || keycode==32 || keycode==67) { @@ -854,13 +855,13 @@ events.prototype.keyUpBook = function (keycode) { } } -events.prototype.clickBookDetail = function (x,y) { +////// 怪物手册属性显示界面时的点击操作 ////// +events.prototype.clickBookDetail = function () { core.clearMap('data', 0, 0, 416, 416); - core.status.event.id = 'book'; - } +////// 楼层传送器界面时的点击操作 ////// events.prototype.clickFly = function(x,y) { if ((x==10 || x==11) && y==9) core.ui.drawFly(core.status.event.data-1); if ((x==10 || x==11) && y==5) core.ui.drawFly(core.status.event.data+1); @@ -875,12 +876,14 @@ events.prototype.clickFly = function(x,y) { return; } +////// 楼层传送器界面时,按下某个键的操作 ////// events.prototype.keyDownFly = function (keycode) { if (keycode==37 || keycode==38) core.ui.drawFly(core.status.event.data+1); else if (keycode==39 || keycode==40) core.ui.drawFly(core.status.event.data-1); return; } +////// 楼层传送器界面时,放开某个键的操作 ////// events.prototype.keyUpFly = function (keycode) { if (keycode==71 || keycode==27 || keycode==88) core.ui.closePanel(); @@ -889,7 +892,7 @@ events.prototype.keyUpFly = function (keycode) { return; } -// 商店 +////// 商店界面时的点击操作 ////// events.prototype.clickShop = function(x,y) { var shop = core.status.event.data.shop; var choices = shop.choices; @@ -936,6 +939,7 @@ events.prototype.clickShop = function(x,y) { } } +////// 商店界面时,按下某个键的操作 ////// events.prototype.keyDownShop = function (keycode) { var shop = core.status.event.data.shop; var choices = shop.choices; @@ -951,6 +955,7 @@ events.prototype.keyDownShop = function (keycode) { } } +////// 商店界面时,放开某个键的操作 ////// events.prototype.keyUpShop = function (keycode) { if (keycode==27 || keycode==88) { if (core.status.event.data.fromList) { @@ -971,7 +976,7 @@ events.prototype.keyUpShop = function (keycode) { return; } -// 快捷商店 +////// 快捷商店界面时的点击操作 ////// events.prototype.clickQuickShop = function(x, y) { var shopList = core.status.shops, keys = Object.keys(shopList); if (x >= 5 && x <= 7) { @@ -992,6 +997,7 @@ events.prototype.clickQuickShop = function(x, y) { } } +////// 快捷商店界面时,按下某个键的操作 ////// events.prototype.keyDownQuickShop = function (keycode) { var shopList = core.status.shops, keys = Object.keys(shopList); if (keycode==38) { @@ -1006,6 +1012,7 @@ events.prototype.keyDownQuickShop = function (keycode) { } } +////// 快捷商店界面时,放开某个键的操作 ////// events.prototype.keyUpQuickShop = function (keycode) { if (keycode==27 || keycode==75 || keycode==88) { core.ui.closePanel(); @@ -1019,11 +1026,11 @@ events.prototype.keyUpQuickShop = function (keycode) { return; } -// 工具栏 +////// 工具栏界面时的点击操作 ////// events.prototype.clickToolbox = function(x,y) { // 返回 if (x>=10 && x<=12 && y==12) { - core.ui.closePanel(false); + core.ui.closePanel(); return; } var index=0; @@ -1033,6 +1040,7 @@ events.prototype.clickToolbox = function(x,y) { this.clickToolboxIndex(index); } +////// 选择工具栏界面中某个Index后的操作 ////// events.prototype.clickToolboxIndex = function(index) { var items = null; var ii=index; @@ -1053,6 +1061,7 @@ events.prototype.clickToolboxIndex = function(index) { } } +////// 工具栏界面时,按下某个键的操作 ////// events.prototype.keyDownToolbox = function (keycode) { if (!core.isset(core.status.event.data)) return; @@ -1116,6 +1125,7 @@ events.prototype.keyDownToolbox = function (keycode) { } } +////// 工具栏界面时,放开某个键的操作 ////// events.prototype.keyUpToolbox = function (keycode) { if (keycode==84 || keycode==27 || keycode==88) { core.ui.closePanel(); @@ -1129,7 +1139,7 @@ events.prototype.keyUpToolbox = function (keycode) { } } -// 存读档 +////// 存读档界面时的点击操作 ////// events.prototype.clickSL = function(x,y) { // 上一页 if ((x == 3 || x == 4) && y == 12) { @@ -1141,7 +1151,7 @@ events.prototype.clickSL = function(x,y) { } // 返回 if (x>=10 && x<=12 && y==12) { - core.ui.closePanel(false); + core.ui.closePanel(); if (!core.isPlaying()) { core.showStartAnimate(); } @@ -1162,6 +1172,7 @@ events.prototype.clickSL = function(x,y) { } } +////// 存读档界面时,按下某个键的操作 ////// events.prototype.keyDownSL = function(keycode) { if (keycode==37) { // left core.ui.drawSLPanel(core.status.event.data - 1); @@ -1189,6 +1200,7 @@ events.prototype.keyDownSL = function(keycode) { } } +////// 存读档界面时,放开某个键的操作 ////// events.prototype.keyUpSL = function (keycode) { if (keycode==27 || keycode==88 || (core.status.event.id == 'save' && keycode==83) || (core.status.event.id == 'load' && keycode==68)) { core.ui.closePanel(); @@ -1203,6 +1215,7 @@ events.prototype.keyUpSL = function (keycode) { } } +////// 系统设置界面时的点击操作 ////// events.prototype.clickSwitchs = function (x,y) { if (x<5 || x>7) return; var choices = [ @@ -1256,6 +1269,7 @@ events.prototype.clickSwitchs = function (x,y) { } } +////// 系统设置界面时,按下某个键的操作 ////// events.prototype.keyDownSwitchs = function (keycode) { var choices = [ "背景音乐", "背景音效", "战斗动画", "怪物显伤", "领域显伤", "返回主菜单" @@ -1272,6 +1286,7 @@ events.prototype.keyDownSwitchs = function (keycode) { } } +////// 系统设置界面时,放开某个键的操作 ////// events.prototype.keyUpSwitchs = function (keycode) { if (keycode==27 || keycode==88) { core.status.event.selection=0; @@ -1288,7 +1303,7 @@ events.prototype.keyUpSwitchs = function (keycode) { } -// 菜单栏 +////// 系统菜单栏界面时的点击事件 ////// events.prototype.clickSettings = function (x,y) { if (x<5 || x>7) return; var choices = [ @@ -1335,6 +1350,7 @@ events.prototype.clickSettings = function (x,y) { return; } +////// 系统菜单栏界面时,按下某个键的操作 ////// events.prototype.keyDownSettings = function (keycode) { var choices = [ "系统设置", "快捷商店", "同步存档", "重新开始", "操作帮助", "关于本塔", "返回游戏" @@ -1351,6 +1367,7 @@ events.prototype.keyDownSettings = function (keycode) { } } +////// 系统菜单栏界面时,放开某个键的操作 ////// events.prototype.keyUpSettings = function (keycode) { if (keycode==27 || keycode==88) { core.ui.closePanel(); @@ -1365,6 +1382,7 @@ events.prototype.keyUpSettings = function (keycode) { } } +////// 同步存档界面时的点击操作 ////// events.prototype.clickSyncSave = function (x,y) { if (x<5 || x>7) return; var choices = [ @@ -1400,6 +1418,7 @@ events.prototype.clickSyncSave = function (x,y) { return; } +////// 同步存档界面时,按下某个键的操作 ////// events.prototype.keyDownSyncSave = function (keycode) { var choices = [ "同步存档到服务器", "从服务器加载存档", "清空本地存档", "返回主菜单" @@ -1416,6 +1435,7 @@ events.prototype.keyDownSyncSave = function (keycode) { } } +////// 同步存档界面时,放开某个键的操作 ////// events.prototype.keyUpSyncSave = function (keycode) { if (keycode==27 || keycode==88) { core.status.event.selection=2; @@ -1431,11 +1451,11 @@ events.prototype.keyUpSyncSave = function (keycode) { } } +////// “关于”界面时的点击操作 ////// events.prototype.clickAbout = function () { if (core.isPlaying()) - core.ui.closePanel(false); + core.ui.closePanel(); else core.showStartAnimate(); } -/*********** 点击事件 END ***************/ diff --git a/libs/floors/MT0.js b/libs/floors/MT0.js index c8d90ad4..fad21c7d 100644 --- a/libs/floors/MT0.js +++ b/libs/floors/MT0.js @@ -8,6 +8,8 @@ main.floors.MT0 = { "canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器) "canUseQuickShop": true, // 该层是否允许使用快捷商店 "defaultGround": "ground", // 默认地面的图块ID(terrains中) + // "color": [0,0,0,0.3], // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。 + // "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。 "map": [ // 地图数据,需要是13x13,建议使用地图生成器来生成 ], diff --git a/libs/floors/sample0.js b/libs/floors/sample0.js index 1fab84e8..17e80550 100644 --- a/libs/floors/sample0.js +++ b/libs/floors/sample0.js @@ -8,6 +8,8 @@ main.floors.sample0 = { "canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器) "canUseQuickShop": true, // 该层是否允许使用快捷商店 "defaultGround": "ground", // 默认地面的图块ID(terrains中) + // "color": [0,0,0,0.3] // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。 + "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。 "map": [ // 地图数据,需要是13x13,建议使用地图生成器来生成 [0, 0, 220, 0, 0, 20, 87, 3, 65, 64, 44, 43, 42], [0, 246, 0, 246, 0, 20, 0, 3, 58, 59, 60, 61, 41], diff --git a/libs/floors/sample1.js b/libs/floors/sample1.js index 3934514b..153b1732 100644 --- a/libs/floors/sample1.js +++ b/libs/floors/sample1.js @@ -8,6 +8,8 @@ main.floors.sample1 = { "canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器) "canUseQuickShop": true, // 该层是否允许使用快捷商店 "defaultGround": "grass", // 默认地面的图块ID(terrains中) + // "color": [0,0,0,0.3] // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。 + // "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。 "map": [ // 地图数据,需要是13x13,建议使用地图生成器来生成 [7, 131, 8, 152, 9, 130, 10, 152, 166, 165, 132, 165, 166], [0, 0, 0, 0, 0, 0, 0, 152, 165, 164, 0, 162, 165], diff --git a/libs/floors/sample2.js b/libs/floors/sample2.js index 0dcff5ab..a312ec93 100644 --- a/libs/floors/sample2.js +++ b/libs/floors/sample2.js @@ -8,7 +8,8 @@ main.floors.sample2 = { "canFlyTo": false, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器) "canUseQuickShop": true, // 该层是否允许使用快捷商店 "defaultGround": "snowGround", // 默认地面的图块ID(terrains中) - "color": [255,0,0,0.3], // 可以设置该层的默认背景色调(RGBA);本项可省略 + "color": [255,0,0,0.3], // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。 + "bgm": "qianjin.mid", // 到达该层后默认播放的BGM。本项可忽略。 "map": [ // 地图数据,需要是13x13,建议使用地图生成器来生成 [5, 5, 5, 5, 5, 5, 87, 5, 5, 5, 5, 5, 5], [5, 4, 4, 4, 4, 1, 0, 1, 4, 4, 4, 4, 5], diff --git a/libs/items.js b/libs/items.js index ae21b209..e603d3a4 100644 --- a/libs/items.js +++ b/libs/items.js @@ -2,6 +2,7 @@ function items() { } +////// 初始化 ////// items.prototype.init = function () { this.items = { // 钥匙 @@ -59,7 +60,7 @@ items.prototype.init = function () { } } -// 初始化道具 +////// 获得所有道具 ////// items.prototype.getItems = function () { // 大黄门钥匙?钥匙盒? if (core.flags.bigKeyIsBox) @@ -74,7 +75,7 @@ items.prototype.getItems = function () { main.instance.items = new items(); - +////// “即捡即用类”道具的使用效果 ////// items.prototype.getItemEffect = function(itemId, itemNum) { var itemCls = core.material.items[itemId].cls; // 消耗品 @@ -115,6 +116,7 @@ items.prototype.getItemEffect = function(itemId, itemNum) { } } +////// “即捡即用类”道具的文字提示 ////// items.prototype.getItemEffectTip = function(itemId) { if (itemId === 'redJewel') return ",攻击+"+core.values.redJewel; if (itemId === 'blueJewel') return ",防御+"+core.values.blueJewel; @@ -140,14 +142,12 @@ items.prototype.getItemEffectTip = function(itemId) { return ""; } - - +////// 使用道具 ////// items.prototype.useItem = function (itemId) { - // 使用道具 if (!this.canUseItem(itemId)) return; var itemCls = core.material.items[itemId].cls; - if (itemId=='book') core.ui.drawEnemyBook(0); + if (itemId=='book') core.ui.drawBook(0); if (itemId=='fly') core.ui.drawFly(core.status.hero.flyRange.indexOf(core.status.floorId)); if (itemId == 'earthquake' || itemId == 'bomb' || itemId == 'pickaxe' || itemId=='icePickaxe' || itemId == 'snow' || itemId == 'hammer' || itemId=='bigKey') { @@ -198,12 +198,11 @@ items.prototype.useItem = function (itemId) { delete core.status.hero.items[itemCls][itemId]; } +////// 当前能否使用道具 ////// items.prototype.canUseItem = function (itemId) { // 没有道具 if (!core.hasItem(itemId)) return false; - var itemCls = core.material.items[itemId].cls; - if (itemId == 'book') return true; if (itemId == 'fly') return core.status.hero.flyRange.indexOf(core.status.floorId)>=0; if (itemId == 'pickaxe') { diff --git a/libs/maps.js b/libs/maps.js index 0557f07a..6c9e8453 100644 --- a/libs/maps.js +++ b/libs/maps.js @@ -1,6 +1,7 @@ function maps() {} maps.prototype.init = function() {} +////// 加载某个楼层(从剧本或存档中) ////// maps.prototype.loadFloor = function (floorId, map) { var floor = core.floors[floorId]; var content = {}; @@ -44,6 +45,7 @@ maps.prototype.loadFloor = function (floorId, map) { return content; } +////// 数字和ID的对应关系 ////// maps.prototype.getBlock = function (x, y, id) { var enable=null; id = ""+id; @@ -80,11 +82,11 @@ maps.prototype.getBlock = function (x, y, id) { if (id == 14) tmp.event = {'cls': 'animates', 'id': 'curseNet', 'noPass': false, 'trigger': 'passNet'}; // 咒网 if (id == 15) tmp.event = {'cls': 'animates', 'id': 'water', 'noPass': true}; // 水 // 在这里添加更多地形 - // 如果空地不足,可以从180以后开始继续放,只要不和现有的数字冲突即可 + // 如果空位不足,可以从180以后开始继续放,只要不和现有的数字冲突即可 // Autotile if (id == 20) tmp.event = {'cls': 'autotile', 'id': 'autotile', 'noPass': true}; // autotile - // 更多的autotile从151到160,只要不和现有的数字冲突即可 + // 更多的autotile从151到160等,只要不和现有的数字冲突即可 if (id == 151) tmp.event = {'cls': 'autotile', 'id': 'autotile1', 'noPass': true}; if (id == 152) tmp.event = {'cls': 'autotile', 'id': 'autotile2', 'noPass': true}; if (id == 153) tmp.event = {'cls': 'autotile', 'id': 'autotile3', 'noPass': true}; @@ -256,6 +258,7 @@ maps.prototype.getBlock = function (x, y, id) { return tmp; } +////// 向该楼层添加剧本的自定义事件 ////// maps.prototype.addEvent = function (block, x, y, event, ground) { if (!core.isset(event)) return; if (!core.isset(block.event)) { // 本身是空地? @@ -291,11 +294,13 @@ maps.prototype.addEvent = function (block, x, y, event, ground) { } } +////// 向该楼层添加剧本的楼层转换事件 ////// maps.prototype.addChangeFloor = function (block, x, y, event, ground) { if (!core.isset(event)) return; this.addEvent(block, x, y, {"trigger": "changeFloor", "data": event}, ground); } +////// 初始化所有地图 ////// maps.prototype.initMaps = function (floorIds) { var maps = {}; for (var i=0;i', 270, top+height-13, '#CCCCCC', '13px Verdana'); } -// 绘制选项事件 +////// 绘制一个选项界面 ////// ui.prototype.drawChoices = function(content, choices) { var background = core.canvas.ui.createPattern(core.material.ground, "repeat"); @@ -273,12 +263,7 @@ ui.prototype.drawChoices = function(content, choices) { return; } -/** - * 绘制确认/取消警告 - * @param text - * @param yesCallback - * @param noCallback - */ +////// 绘制一个确认/取消的警告页面 ////// ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) { core.lockControl(); @@ -327,10 +312,8 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) { } -////// 绘制开关界面 ////// +////// 绘制系统设置界面 ////// ui.prototype.drawSwitchs = function() { - // 背景音乐、背景音效、战斗动画、怪物显伤、领域显伤、返回 - core.status.event.id = 'switchs'; var choices = [ @@ -345,10 +328,7 @@ ui.prototype.drawSwitchs = function() { } -/** - * 绘制菜单栏 - * @param need - */ +////// 绘制系统菜单栏 ////// ui.prototype.drawSettings = function (need) { if (!core.checkStatus('settings', need)) return; @@ -358,6 +338,7 @@ ui.prototype.drawSettings = function (need) { ]); } +////// 绘制快捷商店选择栏 ////// ui.prototype.drawQuickShop = function (need) { if (core.isset(need) && !core.checkStatus('selectShop', need)) return; @@ -374,7 +355,7 @@ ui.prototype.drawQuickShop = function (need) { this.drawChoices(null, choices); } - +////// 绘制战斗动画 ////// ui.prototype.drawBattleAnimate = function(monsterId, callback) { // UI层 @@ -662,10 +643,7 @@ ui.prototype.drawBattleAnimate = function(monsterId, callback) { }, 500); } -/** - * 绘制“请等候...” - * @param text - */ +////// 绘制等待界面 ////// ui.prototype.drawWaiting = function(text) { core.lockControl(); @@ -685,9 +663,7 @@ ui.prototype.drawWaiting = function(text) { } -/** - * 绘制“存档同步”选项 - */ +////// 绘制存档同步界面 ////// ui.prototype.drawSyncSave = function () { core.status.event.id = 'syncSave'; @@ -698,11 +674,7 @@ ui.prototype.drawSyncSave = function () { } -/** - * 绘制“分页” - * @param page - * @param totalPage - */ +////// 绘制分页 ////// ui.prototype.drawPagination = function (page, totalPage) { core.setFont('ui', 'bold 15px Verdana'); @@ -724,11 +696,8 @@ ui.prototype.drawPagination = function (page, totalPage) { } -/** - * 绘制怪物手册 - * @param index 怪物索引 - */ -ui.prototype.drawEnemyBook = function (index) { +////// 绘制怪物手册 ////// +ui.prototype.drawBook = function (index) { var enemys = core.enemys.getCurrentEnemys(); var background = core.canvas.ui.createPattern(core.material.ground, "repeat"); @@ -844,6 +813,7 @@ ui.prototype.drawEnemyBook = function (index) { this.drawPagination(page, totalPage); } +////// 绘制怪物属性的详细信息 ////// ui.prototype.drawBookDetail = function (index) { var enemys = core.enemys.getCurrentEnemys(); if (enemys.length==0) return; @@ -906,10 +876,7 @@ ui.prototype.drawBookDetail = function (index) { core.fillText('data', '<点击任意位置继续>', 270, top+height-13, '#CCCCCC', '13px Verdana'); } -/** - * 绘制楼传器 - * @param page - */ +////// 绘制楼层传送器 ////// ui.prototype.drawFly = function(page) { if (page<0) page=0; @@ -935,6 +902,7 @@ ui.prototype.drawFly = function(page) { this.drawThumbnail(floorId, 'ui', core.status.maps[floorId].blocks, 20, 100, 273); } +////// 绘制道具栏 ////// ui.prototype.drawToolbox = function(index) { var tools = Object.keys(core.status.hero.items.tools).sort(); @@ -1049,7 +1017,7 @@ ui.prototype.drawToolbox = function(index) { core.fillText('ui', '返回游戏', 370, 403,'#DDDDDD', 'bold 15px Verdana'); } - +////// 绘制存档/读档界面 ////// ui.prototype.drawSLPanel = function(index) { if (!core.isset(index)) index=1; if (index<=0) index=1; @@ -1103,6 +1071,7 @@ ui.prototype.drawSLPanel = function(index) { this.drawPagination(page+1, 30); } +////// 绘制一个缩略图 ////// ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, heroLoc) { core.clearMap(canvas, x, y, size, size); var groundId = core.floors[floorId].defaultGround || "ground"; @@ -1140,9 +1109,7 @@ ui.prototype.drawThumbnail = function(floorId, canvas, blocks, x, y, size, heroL } } -/** - * 绘制"关于" - */ +////// 绘制“关于”界面 ////// ui.prototype.drawAbout = function() { if (!core.isPlaying()) { @@ -1168,18 +1135,9 @@ ui.prototype.drawAbout = function() { core.fillText('ui', "作者: 艾之葵", text_start, top + 80, "#FFFFFF", "bold 17px Verdana"); core.fillText('ui', 'HTML5魔塔交流群:539113091', text_start, top+112); // TODO: 写自己的“关于”页面 - /* - core.fillText('ui', "原作: ss433_2", text_start, top + 112, "#FFFFFF", "bold 17px Verdana"); - core.fillText('ui', "制作工具: WebStorm", text_start, top + 144, "#FFFFFF", "bold 17px Verdana"); - core.fillText('ui', "测试平台: Chrome/微信/iOS", text_start, top + 176, "#FFFFFF", "bold 17px Verdana"); - core.fillText('ui', '特别鸣谢: ss433_2', text_start, top+208); - var len = core.canvas.ui.measureText('特别鸣谢: ').width; - core.fillText('ui', 'iEcho', text_start+len, top+240); - core.fillText('ui', '打Dota的喵', text_start+len, top+272); - core.fillText('ui', 'HTML5魔塔交流群:539113091', text_start, top+304); - */ } +////// 绘制帮助页面 ////// ui.prototype.drawHelp = function () { core.drawText([ "\t[键盘快捷键列表]"+ diff --git a/更新说明.txt b/更新说明.txt index 83a62ff8..6437085b 100644 --- a/更新说明.txt +++ b/更新说明.txt @@ -1,4 +1,5 @@ 全键盘操作 √ +便捷PS工具支持更改图片色相 √ 经验升级(进阶) √ 增加阻击、多连击等属性;属性显示;加点; √ 九宫格领域、大范围领域 √