Merge remote-tracking branch 'refs/remotes/ckcz123/v2.0' into refactoring-editor
This commit is contained in:
commit
28c678d1c4
689
_docs/_api.md
Normal file
689
_docs/_api.md
Normal file
@ -0,0 +1,689 @@
|
||||
# 附录: API列表
|
||||
|
||||
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
**这里只列出所有可能会被造塔者用到的常用API,更多的有关内容请在代码内进行查询。**
|
||||
|
||||
如有任何疑问,请联系小艾寻求帮助。
|
||||
|
||||
可以在chrome浏览器的控制台中(`ctrl+shift+I`,找到Console)中直接进行调用,以查看效果。
|
||||
|
||||
**以下所有异步API都会加上[异步]的说明,存在此说明的请勿在事件处理的自定义脚本中使用。**
|
||||
|
||||
!> 最常用的新手向命令,强烈建议每个人了解
|
||||
|
||||
``` text
|
||||
|
||||
core.status.floorId
|
||||
获得当前层的floorId。
|
||||
|
||||
|
||||
core.status.maps
|
||||
获得所有楼层的地图信息。
|
||||
|
||||
|
||||
core.status.thisMap
|
||||
获得当前楼层信息,其等价于core.status.maps[core.status.floorId]。
|
||||
|
||||
|
||||
core.floors
|
||||
获得所有楼层的信息。例如core.floors[core.status.floorId].events可获得本楼层的所有自定义事件。
|
||||
|
||||
|
||||
core.status.hero
|
||||
获得当前勇士状态信息。例如core.status.hero.atk就是当前勇士的攻击力数值。
|
||||
|
||||
|
||||
core.material.enemys
|
||||
获得所有怪物信息。例如core.material.enemys.greenSlime就是获得绿色史莱姆的属性数据。
|
||||
|
||||
|
||||
core.material.items
|
||||
获得所有道具的信息。
|
||||
|
||||
|
||||
core.debug()
|
||||
开启调试模式。此模式下可以按Ctrl键进行穿墙,并忽略一切事件。
|
||||
此模式下不可回放录像和上传成绩。
|
||||
|
||||
|
||||
core.updateStatusBar()
|
||||
立刻刷新状态栏和地图显伤。
|
||||
|
||||
|
||||
core.setStatus('atk', 1000)
|
||||
将攻击力设置为1000;这里把atk可以改成hp, def, mdef, money, experience等等。
|
||||
本句等价于 core.status.hero.atk = 1000
|
||||
|
||||
|
||||
core.getStatus('atk')
|
||||
返回当前攻击力数值。本句等价于 core.status.hero.atk。
|
||||
|
||||
|
||||
core.setHeroLoc('x', 5)
|
||||
设置勇士位置。这句话的意思是将勇士当前位置的横坐标设置为5。
|
||||
同理可以设置勇士纵坐标 core.setHeroLoc('y', 3)。
|
||||
值得注意的是,这句话虽然会使勇士改变位置,但并不会使界面重新绘制;如需立刻重新绘制地图还需调用:
|
||||
core.clearMap('hero'); core.drawHero();
|
||||
来对界面进行更新。
|
||||
|
||||
|
||||
core.setItem('pickaxe', 10)
|
||||
将破墙镐个数设置为10个。这里可以写任何道具的ID。
|
||||
|
||||
|
||||
core.addItem('pickaxe', 2)
|
||||
将破墙镐的个数增加2个,无任何特效。这里可以写任何道具的ID。
|
||||
|
||||
|
||||
core.getItem('pickaxe', 4)
|
||||
令勇士获得4个破墙镐。这里可以写任何道具的ID。
|
||||
和addItem相比,使用getItem会播放获得道具的音效,也会在左上角绘制获得提示。
|
||||
|
||||
|
||||
core.removeItem('pickaxe', 3)
|
||||
删除3个破墙镐。第二项可忽略,默认值为1。
|
||||
|
||||
|
||||
core.itemCount('pickaxe')
|
||||
返回当前破墙镐的个数。这里可以写任何道具的ID。
|
||||
|
||||
|
||||
core.hasItem('pickaxe')
|
||||
返回当前是否存在某个道具。等价于 core.itemCount('pickaxe')>0 。
|
||||
|
||||
|
||||
core.getEquip(0)
|
||||
获得0号装备类型(武器)的当前装备的itemId。如果不存在则返回null。
|
||||
这里可以写任意装备类型,从0开始和全塔属性中的equipName一一对应。
|
||||
|
||||
|
||||
core.hasEquip('sword1')
|
||||
获得当前某个具体的装备是否处于正在被装备状态。
|
||||
|
||||
|
||||
core.setFlag('xyz', 2)
|
||||
设置某个flag/变量的值为2。这里可以写任何的flag变量名。
|
||||
|
||||
|
||||
core.getFlag('xyz', 7)
|
||||
获得某个flag/变量的值;如果该变量不存在,则返回第二个参数。
|
||||
比如 core.getFlag('point', 2) 则获得变量point的值;如果该变量从未定义过则返回2。
|
||||
|
||||
|
||||
core.hasFlag('xyz')
|
||||
返回是否存在某个变量且不为0。等价于 core.getFlag('xyz', 0)!=0 。
|
||||
|
||||
|
||||
core.removeFlag('xyz')
|
||||
删除某个flag/变量。
|
||||
|
||||
|
||||
core.insertAction(list, x, y, callback)
|
||||
插入并执行一段自定义事件。在这里你可以写任意的自定义事件列表,有关详细写法请参见文档-事件。
|
||||
x和y如果设置则覆盖"当前事件点"的坐标,callback如果设置则覆盖事件执行完毕后的回调函数。
|
||||
例如: core.insertAction(["楼层切换", {"type":"changeFloor", "floorId": "MT3"}])
|
||||
将依次显示剧情文本,并执行一个楼层切换的自定义事件。
|
||||
--------
|
||||
从V2.5.4开始提出了“公共事件”的说法,这里也可以插入一个公共事件名。
|
||||
例如:core.insertAction("毒衰咒处理") 将插入公共事件“毒衰咒处理”。
|
||||
|
||||
|
||||
core.changeFloor(floorId, stair, heroLoc, time, callback) [异步]
|
||||
立刻切换到指定楼层。
|
||||
floorId为目标楼层ID,stair为到达的目标楼梯,heroLoc为到达的指定点,time为动画时间,callback为切换完毕后的回调。
|
||||
例如:
|
||||
core.changeFloor('MT2', 'upFloor', null, 600) 切换到MT2层的上楼点,动画事件600ms
|
||||
core.changeFloor('MT5', null, {'x': 3, 'y': 6}, 0) 无动画切换到MT5层的(3,6)位置。
|
||||
|
||||
|
||||
core.resetMap()
|
||||
重置当前楼层地图和楼层属性。
|
||||
此函数参数有三种形式:
|
||||
- 不加任何参数,表示重置当前层:core.resetMap()
|
||||
- 加上一个floorId,表示重置某一层:core.resetMap("MT1")
|
||||
- 使用一个数组,表示重置若干层:core.resetMap(["MT1", "MT2", "MT3"])
|
||||
---------------------------
|
||||
** 说明:从V2.5.5开始存档方式发生了改变,在编辑器修改了地图后现在将直接生效,无需再重置地图。
|
||||
|
||||
R
|
||||
录像回放的快捷键;这不是一个控制台命令,但是也把它放在这里供使用。
|
||||
录像回放在修改地图或新增数据后会很有用。
|
||||
|
||||
```
|
||||
|
||||
!> 一些相对高级的命令,针对有一定脚本经验的人
|
||||
|
||||
``` text
|
||||
|
||||
========== 可直接从core中调用的,最常被使用的函数 ==========
|
||||
core.js实际上是所有API的入口(路由),核心API的实现在其他几个文件中,core.js主要进行转发操作。
|
||||
|
||||
|
||||
core.nextX(n)
|
||||
获得勇士面向的第n个位置的x坐标,n可以省略默认为1(即正前方)
|
||||
|
||||
|
||||
core.nextY(n)
|
||||
获得勇士面向的第n个位置的y坐标,n可以省略默认为1(即正前方)
|
||||
|
||||
|
||||
core.nearHero(x, y)
|
||||
判断某个点是否和勇士的距离不超过1。
|
||||
|
||||
|
||||
core.openDoor(id, x, y, needKey, callback) [异步]
|
||||
尝试开门操作。id为目标点的ID,x和y为坐标,needKey表示是否需要使用钥匙,callback为开门完毕后的回调函数。
|
||||
id可为null代表使用地图上的值。
|
||||
例如:core.openDoor('yellowDoor', 10, 3, false, function() {console.log("1")})
|
||||
此函数返回true代表成功开门,并将执行callback回调;返回false代表无法开门,且不会执行回调函数。
|
||||
|
||||
|
||||
core.battle(id, x, y, force, callback) [异步]
|
||||
执行战斗事件。id为怪物的id,x和y为坐标,force为bool值表示是否是强制战斗,callback为战斗完毕后的回调函数。
|
||||
id可为null代表使用地图上的值。
|
||||
例如:core.battle('greenSlime', null, null, true)
|
||||
|
||||
|
||||
core.trigger(x, y) [异步]
|
||||
触发某个地点的事件。
|
||||
|
||||
|
||||
core.isReplaying()
|
||||
当前是否正在录像播放中
|
||||
|
||||
|
||||
core.drawBlock(block)
|
||||
重绘某个图块。block应为core.status.thisMap.blocks中的一项。
|
||||
|
||||
|
||||
core.drawMap(floorId, callback)
|
||||
重绘某一层的地图。floorId为要绘制楼层的floorId,callback为绘制完毕后的回调函数。
|
||||
|
||||
|
||||
core.terrainExists(x, y, id, floorId)
|
||||
检测某个点是否存在(指定的)地形。
|
||||
x和y为坐标;id为地形ID,可为null表示任意地形;floorId为楼层ID,可忽略表示当前楼层。
|
||||
|
||||
|
||||
core.enemyExists(x, y, id, floorId)
|
||||
检测某个点是否存在(指定的)怪物。
|
||||
x和y为坐标;id为怪物ID,可为null表示任意怪物;floorId为楼层ID,可忽略表示当前楼层。
|
||||
|
||||
|
||||
core.getBlock(x, y, floorId, showDisable)
|
||||
获得某个点的当前图块信息。
|
||||
x和y为坐标;floorId为楼层ID,可忽略或null表示当前楼层。
|
||||
showDisable如果为true,则对于禁用的点和事件也会进行返回。
|
||||
如果该点不存在图块,则返回null。
|
||||
否则,返回值如下: {"index": xxx, "block": xxx}
|
||||
其中index为该点在该楼层blocks数组中的索引,block为该图块实际内容。
|
||||
|
||||
|
||||
core.getBlockId(x, y, floorId, showDisable)
|
||||
获得某个点的图块ID。
|
||||
x和y为坐标;floorId为楼层ID,可忽略或null表示当前楼层。
|
||||
showDisable如果为true,则对于禁用的点和事件也会进行返回。
|
||||
如果该点不存在图块,则返回null,否则返回该点的图块ID。
|
||||
|
||||
|
||||
core.getBlockCls(x, y, floorId, showDisable)
|
||||
获得某个点的图块cls。
|
||||
x和y为坐标;floorId为楼层ID,可忽略或null表示当前楼层。
|
||||
showDisable如果为true,则对于禁用的点和事件也会进行返回。
|
||||
如果该点不存在图块,则返回null,否则返回该点的图块cls。
|
||||
|
||||
|
||||
core.showBlock(x, y, floorId)
|
||||
将某个点从禁用变成启用状态。
|
||||
|
||||
|
||||
core.hideBlock(x, y, floorId)
|
||||
将某个点从启用变成禁用状态,但不会对其进行删除。
|
||||
此函数不会实际将该块从地图中进行删除,而是将该点设置为禁用,以供以后可能的启用事件。
|
||||
|
||||
|
||||
core.removeBlock(x, y, floorId)
|
||||
将从启用变成禁用状态,并尽可能将其从地图上删除。
|
||||
和hideBlock相比,如果该点不存在自定义事件(比如门或普通的怪物),则将直接从地图中删除。
|
||||
如果存在自定义事件,则简单的禁用它,以供以后可能的启用事件。
|
||||
|
||||
|
||||
core.setBlock(number, x, y, floorId)
|
||||
改变图块。number为要改变到的图块数字,x和y为坐标,floorId为楼层ID,可忽略表示当前楼层。
|
||||
|
||||
|
||||
core.useItem(itemId, noRoute, callback)
|
||||
尝试使用某个道具。itemId为道具ID,noRoute如果为真则该道具的使用不计入录像。
|
||||
callback为成功或失败后的回调。
|
||||
|
||||
|
||||
core.canUseItem(itemId)
|
||||
返回当前能否使用某个道具。
|
||||
|
||||
|
||||
core.loadEquip(itemId, callback)
|
||||
装备上某个装备。itemId为装备的ID,callback为成功或失败后的回调。
|
||||
|
||||
|
||||
core.unloadEquip(equipType, callback)
|
||||
卸下某个部位的装备。equipType为装备类型,从0开始;callback为成功或失败后的回调。
|
||||
|
||||
|
||||
core.getNextItem()
|
||||
轻按。
|
||||
|
||||
|
||||
core.drawTip(text, itemIcon)
|
||||
在左上角绘制一段提示信息,2秒后消失。itemIcon为道具图标的索引。
|
||||
|
||||
|
||||
core.drawText(contents, callback) [异步]
|
||||
绘制一段文字。
|
||||
不推荐使用此函数,尽量使用core.insertAction(contents)来显示剧情文本。
|
||||
|
||||
|
||||
core.closePanel()
|
||||
结束一切事件和绘制,关闭UI窗口,返回游戏进程。
|
||||
|
||||
|
||||
core.replaceText(text)
|
||||
将一段文字中的${}进行计算并替换。
|
||||
|
||||
|
||||
core.calValue(value, prefix, need, times)
|
||||
计算表达式的实际值。这个函数可以传入status:atk等这样的参数。
|
||||
|
||||
|
||||
core.getLocalStorage(key, defaultValue)
|
||||
从localStorage中获得某个数据(已被parse);如果对应的key不存在则返回defaultValue。
|
||||
|
||||
|
||||
core.getLocalForage(key, defaultValue, successCallback, errorCallback)
|
||||
从localForage中获得某个数据(已被parse),如果对应的key不存在则返回defaultValue。
|
||||
如果成功则通过successCallback回调,失败则通过errorCallback回调。
|
||||
|
||||
|
||||
core.hasSave(index)
|
||||
判定当前某个存档位是否存在存档,返回true/false。
|
||||
index为存档编号,0代表自动存档,大于0则为正常的存档位。
|
||||
|
||||
|
||||
core.clone(data)
|
||||
深拷贝某个对象。
|
||||
|
||||
|
||||
core.isset(x)
|
||||
测试x是否不为null,不为undefined也不为NaN。
|
||||
|
||||
|
||||
core.rand(num)
|
||||
使用伪种子生成伪随机数。该随机函数能被录像支持。
|
||||
num如果设置大于0,则生成一个[0, num-1]之间的数;否则生成一个0到1之间的浮点数。
|
||||
此函数为伪随机算法,SL大法无效。(即多次SL后调用的该函数返回的值都是相同的。)
|
||||
|
||||
|
||||
core.rand2(num)
|
||||
使用系统的随机数算法得到的随机数。该随机函数能被录像支持。
|
||||
num如果设置大于0,则生成一个[0, num-1]之间的数;否则生成一个0到2147483647之间的整数。
|
||||
此函数使用了系统的Math.random()函数,支持SL大法。
|
||||
但是,此函数会将生成的随机数值存入录像,因此如果调用次数太多则会导致录像文件过大。
|
||||
|
||||
|
||||
core.restart() [异步]
|
||||
返回标题界面。
|
||||
|
||||
|
||||
========== core.actions.XXX 和游戏控制相关的函数 ==========
|
||||
actions.js主要用来进行用户交互行为的处理。
|
||||
所有用户行为,比如按键、点击、滑动等等,都会被此文件接收并进行操作。
|
||||
|
||||
|
||||
========== core.control.XXX 和游戏控制相关的函数 ==========
|
||||
control.js主要用来进行游戏控制,比如行走控制、自动寻路、存读档等等游戏核心内容。
|
||||
|
||||
core.control.setGameCanvasTranslate(canvasId, x, y)
|
||||
设置大地图的偏移量
|
||||
|
||||
|
||||
core.control.updateViewport()
|
||||
更新大地图的可见区域
|
||||
|
||||
|
||||
core.control.gatherFollowers()
|
||||
立刻聚集所有的跟随者
|
||||
|
||||
|
||||
core.control.replay()
|
||||
回放下一个操作
|
||||
|
||||
|
||||
========== core.enemys.XXX 和怪物相关的函数 ==========
|
||||
enemys.js主要用来进行怪物相关的内容,比如怪物的特殊属性,伤害和临界计算等。
|
||||
|
||||
|
||||
core.enemys.hasSpecial(special, test)
|
||||
测试怪物是否含有某个特殊属性。
|
||||
常见用法: core.enemys.hasSpecial(monster.special, 3) ## 测试是否拥有坚固
|
||||
|
||||
|
||||
core.enemys.getSpecialText(enemyId)
|
||||
返回一个列表,包含该怪物ID对应的所有特殊属性。
|
||||
|
||||
|
||||
core.enemys.getSpecialHint(enemy, special)
|
||||
获得怪物某个(或全部)特殊属性的文字说明。
|
||||
|
||||
|
||||
core.enemys.canBattle(enemyId, x, y, floorId)
|
||||
返回当前能否战胜某个怪物。
|
||||
后面三个参数是怪物坐标和楼层。
|
||||
|
||||
|
||||
core.enemys.getDamage(enemyId, x, y, floorId)
|
||||
返回当前对某个怪物的战斗伤害。如果无法战斗,返回null。
|
||||
后面三个参数是怪物坐标和楼层。
|
||||
|
||||
|
||||
core.enemys.getExtraDamage(enemyId)
|
||||
返回某个怪物会对勇士造成的额外伤害(不可被魔防抵消),例如仇恨、固伤等等。
|
||||
|
||||
|
||||
core.enemys.nextCriticals(enemyId, number, x, y, floorId)
|
||||
返回一个列表,为接下来number(可忽略,默认为1)个该怪物的临界值和临界减伤。
|
||||
列表每一项类似 [x,y] 表示临界值为x,且临界减伤为y。
|
||||
如果无临界值,则返回空列表。
|
||||
|
||||
|
||||
core.enemys.getDefDamage(enemyId, k, x, y, floorId)
|
||||
获得k(可忽略,默认为1)防减伤值。
|
||||
|
||||
|
||||
core.enemys.getDamageInfo(enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId)
|
||||
获得实际战斗信息,比如伤害,回合数,每回合伤害等等。
|
||||
此函数是实际战斗过程的计算。
|
||||
|
||||
|
||||
core.enemys.calDamage(enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId)
|
||||
获得在某个勇士属性下怪物伤害;实际返回的是上面getDamageInfo中伤害的数值。
|
||||
|
||||
|
||||
core.enemys.getCurrentEnemys(floorId)
|
||||
获得某一层楼剩余所有怪物的信息(供怪物手册使用)
|
||||
|
||||
|
||||
========== core.events.XXX 和事件相关的函数 ==========
|
||||
events.js主要用来进行事件处理,比如自定义事件,以及某些条件下可能会被触发的事件。
|
||||
大多数事件API都在脚本编辑中存在,这里只列出部分比较重要的脚本编辑中不存在的API。
|
||||
|
||||
|
||||
core.events.gameOver(ending, fromReplay)
|
||||
游戏结束并上传的事件。
|
||||
该函数将提问是否上传和是否下载录像,并返回标题界面。
|
||||
|
||||
|
||||
core.events.doEvents(list, x, y, callback) [异步]
|
||||
开始执行某个事件。
|
||||
请不要执行此函数,尽量使用 core.insertAction(list, x, y, callback) 来开始执行一段事件。
|
||||
|
||||
|
||||
core.events.doAction()
|
||||
执行下一个事件。此函数中将对所有自定义事件类型分别处理。
|
||||
|
||||
|
||||
core.events.getCommonEvent(name)
|
||||
根据名称获得一个公共事件;如果不存在对应的公共事件则返回null。
|
||||
|
||||
|
||||
core.events.openShop(shopId, needVisited) [异步]
|
||||
打开一个全局商店。needVisited表示是否需要该商店已被打开过。
|
||||
|
||||
|
||||
core.events.disableQuickShop(shopId)
|
||||
禁用一个全局商店
|
||||
|
||||
|
||||
core.events.canUseQuickShop(shopId)
|
||||
当前能否使用某个快捷商店
|
||||
|
||||
|
||||
core.events.setHeroIcon(name)
|
||||
设置勇士行走图
|
||||
|
||||
|
||||
========== core.items.XXX 和道具相关的函数 ==========
|
||||
items.js将处理和道具相关的内容,比如道具的使用,获取和删除等等。
|
||||
|
||||
|
||||
core.items.compareEquipment(equipId1, equipId2)
|
||||
比较两个装备的属性变化值
|
||||
|
||||
|
||||
========== core.loader.XXX 和游戏加载相关的函数 ==========
|
||||
loader.js将主要用来进行资源的加载,比如加载音乐、图片、动画等等。
|
||||
|
||||
|
||||
========== core.maps.XXX 和地图处理相关的函数 ==========
|
||||
maps.js主要用来进行地图相关的的操作。包括绘制地图,获取地图上的点等等。
|
||||
|
||||
|
||||
core.maps.getNumberById(id)
|
||||
根据ID来获得对应的数字。如果该ID不存在对应的数字则返回0。
|
||||
|
||||
|
||||
core.maps.canMoveHero(x,y,direction,floorId)
|
||||
判断能否前往某个方向。x,y为坐标,可忽略为当前点;direction为方向,可忽略为当前方向。
|
||||
floorId为楼层ID,可忽略为当前楼层。
|
||||
|
||||
|
||||
core.maps.canMoveDirectly(destX, destY)
|
||||
判断当前能否瞬间移动到某个点。
|
||||
该函数如果返回0则不可瞬间移动,大于0则可以瞬间移动,且返回值是跨度(即少走的步数)。
|
||||
|
||||
|
||||
core.maps.removeBlockById(index, floorId)
|
||||
根据索引删除或禁用某块。
|
||||
|
||||
|
||||
core.maps.removeBlockByIds(floorId, ids)
|
||||
根据索引删除或禁用若干块。
|
||||
|
||||
|
||||
core.maps.drawAnimate(name, x, y, callback)
|
||||
播放一段动画,name为动画名(需在全塔属性注册),x和y为坐标(0-12之间),callback可选,为播放完毕的回调函数。
|
||||
播放过程是异步的,如需等待播放完毕请使用insertAction插入一条type:waitAsync事件。
|
||||
此函数将随机返回一个数字id,为此异步动画的唯一标识符。
|
||||
|
||||
|
||||
core.maps.stopAnimate(id, doCallback)
|
||||
立刻停止一个异步动画。
|
||||
id为该动画的唯一标识符(由drawAnimate函数返回),doCallback可选,若为true则会执行该动画所绑定的回调函数。
|
||||
|
||||
|
||||
========== core.ui.XXX 和对话框绘制相关的函数 ==========
|
||||
ui.js主要用来进行UI窗口的绘制,比如对话框、怪物手册、楼传器、存读档界面等等。
|
||||
|
||||
|
||||
core.ui.getContextByName(canvas)
|
||||
根据画布名找到一个画布的context;支持系统画布和自定义画布。如果不存在画布返回null。
|
||||
也可以传画布的context自身,则返回自己。
|
||||
|
||||
|
||||
core.clearMap(name)
|
||||
清空某个画布图层。
|
||||
name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名;还可以直接传画布的context本身。(下同)
|
||||
如果name也可以是'all',若为all则为清空所有系统画布。
|
||||
|
||||
|
||||
core.ui.fillText(name, text, x, y, style, font)
|
||||
在某个画布上绘制一段文字。
|
||||
text为要绘制的文本,x,y为要绘制的坐标,style可选为绘制的样式,font可选为绘制的字体。(下同)
|
||||
|
||||
|
||||
core.ui.fillBoldText(name, text, x, y, style, font)
|
||||
在某个画布上绘制一个描黑边的文字。
|
||||
|
||||
|
||||
core.ui.fillRect(name, x, y, width, height, style)
|
||||
绘制一个矩形。style可选为绘制样式。
|
||||
|
||||
|
||||
core.ui.strokeRect(name, x, y, width, height, style)
|
||||
绘制一个矩形的边框。
|
||||
|
||||
|
||||
core.ui.drawLine(name, x1, y1, x2, y2, style, lineWidth)
|
||||
绘制一条线。lineWidth可选为线宽。
|
||||
|
||||
|
||||
core.ui.drawArrow(name, x1, y1, x2, y2, style, lineWidth)
|
||||
绘制一个箭头。
|
||||
|
||||
|
||||
core.ui.setFont(name, font) / core.ui.setLineWidth(name, lineWidth)
|
||||
设置一个画布的字体/线宽。
|
||||
|
||||
|
||||
core.ui.setAlpha(name, font) / core.ui.setOpacity(name, font)
|
||||
设置一个画布的绘制不透明度和画布本身的不透明度。
|
||||
两者区别如下:
|
||||
- setAlpha是设置"接下来绘制的内容的不透明度",不会对已经绘制的内容产生影响。比如setAlpha('ui', 0.5)则会在接下来的绘制中使用0.5的不透明度。
|
||||
- setOpacity是设置"画布本身的不透明度",已经绘制的内容也会产生影响。比如我已经在UI层绘制了一段文字,再setOpacity则也会看起来变得透明。
|
||||
尽量不要对系统画布使用setOpacity(因为会对已经绘制的内容产生影响),自定义创建的画布则不受此限制。
|
||||
|
||||
|
||||
core.ui.setFillStyle(name, style) / core.ui.setStrokeStyle(name, style)
|
||||
设置一个画布的填充样式/描边样式。
|
||||
|
||||
|
||||
core.ui.setTextAlign(name, align)
|
||||
设置一个画布的文字对齐模式。
|
||||
|
||||
|
||||
core.ui.calWidth(name, text, font)
|
||||
计算一段文字在画布上的绘制宽度
|
||||
font可选,如果存在则会先设置该画布上的字体。
|
||||
|
||||
|
||||
core.ui.drawImage(name, image, x, y, w, h, x1, y1, w1, h1)
|
||||
在一个画布上绘制图片。
|
||||
name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名;还可以直接传画布的context本身。
|
||||
image为要绘制的图片,可以是一个全塔属性中定义的图片名(会从images中去获取),图片本身,或者一个画布。
|
||||
后面的8个坐标参数与canvas的drawImage的八个参数完全相同。
|
||||
请查看 http://www.w3school.com.cn/html5/canvas_drawimage.asp 了解更多。
|
||||
|
||||
|
||||
core.ui.createCanvas(name, x, y, width, height, zIndex)
|
||||
动态创建一个画布。name为要创建的画布名,如果已存在则会直接取用当前存在的。
|
||||
x,y为创建的画布相对窗口左上角的像素坐标,width,height为创建的长宽。
|
||||
zIndex为创建的纵向高度(关系到画布之间的覆盖),z值高的将覆盖z值低的;系统画布的z值可在个性化中查看。
|
||||
返回创建的画布的context,也可以通过core.dymCanvas[name]调用。
|
||||
|
||||
|
||||
core.ui.relocateCanvas(name, x, y)
|
||||
重新定位一个自定义画布。
|
||||
|
||||
|
||||
core.ui.resizeCanvas(name, x, y)
|
||||
重新设置一个自定义画布的大小。
|
||||
|
||||
|
||||
core.ui.deleteCanvas(name)
|
||||
删除一个自定义画布。
|
||||
|
||||
|
||||
core.ui.deleteAllCanvas()
|
||||
清空所有的自定义画布。
|
||||
|
||||
|
||||
core.ui.drawThumbnail(floorId, canvas, blocks, x, y, size, heroLoc, heroIcon)
|
||||
绘制一个缩略图,比如楼传器界面,存读档界面等情况。
|
||||
floorId为目标楼层ID,canvas为要绘制到的图层,blocks为要绘制的所有图块。
|
||||
x,y为该图层开始绘制的起始点坐标,size为每一格的像素,heroLoc为勇士坐标,heroIcon为勇士图标。
|
||||
|
||||
|
||||
========== core.utils.XXX 工具类的辅助函数 ==========
|
||||
utils.js主要用来进行一些辅助函数的计算。
|
||||
|
||||
|
||||
core.utils.splitLines(canvas, text, maxLength, font)
|
||||
自动切分长文本的换行。
|
||||
canvas为图层,text为要自动换行的内容,maxLength为每行最长像素,font为文本的字体。
|
||||
|
||||
|
||||
core.utils.cropImage(image, size)
|
||||
纵向对图片进行切分(裁剪)。
|
||||
|
||||
|
||||
core.utils.push(a,b)
|
||||
向某个数组后插入另一个数组或元素
|
||||
|
||||
|
||||
core.utils.unshift(a, b)
|
||||
向某个数组前插入另一个数组或元素
|
||||
|
||||
|
||||
core.utils.encodeBase64(str)
|
||||
Base64加密字符串
|
||||
|
||||
|
||||
core.utils.decodeBase64(str)
|
||||
Base64解密字符串
|
||||
|
||||
|
||||
core.utils.formatBigNumber(x, onMap)
|
||||
大数据的格式化
|
||||
|
||||
|
||||
core.utils.subarray(a, b)
|
||||
检查b是否是a的从头开始子串。
|
||||
如果是,则返回a删去b的一段;否则返回null。
|
||||
|
||||
|
||||
core.utils.same(a, b)
|
||||
比较a和b两个对象是否相同
|
||||
|
||||
|
||||
core.utils.clamp(x, a, b)
|
||||
将x限制在[a,b]之间的范围内
|
||||
|
||||
|
||||
core.utils.arrayToRGB(color)
|
||||
将形如[255,0,0]之类的数组转成#FF0000这样的RGB形式。
|
||||
|
||||
|
||||
core.utils.arrayToRGBA(color)
|
||||
将形如[255,0,0,1]之类的数组转成rgba(255,0,0,1)这样的RGBA形式。
|
||||
|
||||
|
||||
core.utils.encodeRoute(list)
|
||||
压缩加密路线。可以使用core.encodeRoute(core.status.route)来压缩当前路线。
|
||||
|
||||
|
||||
core.utils.decodeRoute(route)
|
||||
解压缩(解密)路线。
|
||||
|
||||
|
||||
core.utils.readFile(success, error, readType) [异步]
|
||||
尝试请求读取一个本地文件内容。
|
||||
success和error为成功/失败后的回调,readType不设置则以文本读取,否则以DataUrl形式读取。
|
||||
|
||||
|
||||
core.utils.readFileContent(content) [异步]
|
||||
文件读取完毕后的内容处理。
|
||||
|
||||
|
||||
core.utils.download(filename, content)
|
||||
尝试生成并下载一个文件。
|
||||
|
||||
|
||||
core.utils.copy(data)
|
||||
尝试复制一段文本到剪切板。
|
||||
|
||||
|
||||
core.utils.http(type, url, formData, success, error) [异步]
|
||||
发送一个异步HTTP请求。
|
||||
type为'GET'或者'POST';url为目标地址;formData如果是POST请求则为表单数据。
|
||||
success为成功后的回调,error为失败后的回调。
|
||||
|
||||
```
|
||||
@ -3,4 +3,5 @@
|
||||
- [元件说明](element)
|
||||
- [事件](event)
|
||||
- [个性化](personalization)
|
||||
- [脚本](script)
|
||||
- [附录:API列表](api)
|
||||
|
||||
2457
_docs/api.md
2457
_docs/api.md
File diff suppressed because it is too large
Load Diff
716
_docs/event.md
716
_docs/event.md
File diff suppressed because it is too large
Load Diff
BIN
_docs/img/console.jpg
Normal file
BIN
_docs/img/console.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
_docs/img/console1.jpg
Normal file
BIN
_docs/img/console1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
BIN
_docs/img/elements.jpg
Normal file
BIN
_docs/img/elements.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 171 KiB |
BIN
_docs/img/plugin.jpg
Normal file
BIN
_docs/img/plugin.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
_docs/img/sources.jpg
Normal file
BIN
_docs/img/sources.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 116 KiB |
@ -1,6 +1,6 @@
|
||||
# 个性化
|
||||
|
||||
?> 目前版本**v2.5.5**,上次更新时间:* {docsify-updated} *
|
||||
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。
|
||||
|
||||
@ -21,10 +21,14 @@ HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们
|
||||
- route**[D]**:路线层;主要用来绘制勇士的行走路线图。 (z-index: 95)
|
||||
- paint**[D]**:绘图层;主要用来进行绘图模式。(z-index: 95)
|
||||
- curtain:色调层;用来控制当前楼层的画面色调 (z-index: 125)
|
||||
- image1\~50**[D]**:图片层;用来绘制图片等操作。(z-index: 100+code, 101~150;也就是图片编号在1~25的在色调层之下,26~50的在色调层之上)
|
||||
- ui:UI层;用来绘制一切UI窗口,如剧情文本、怪物手册、楼传器、系统菜单等等 (z-index: 160)
|
||||
- image1\~50**[D]**:图片层;用来绘制图片等操作。(z-index: 100+code, 101~150)
|
||||
- ui:UI层;用来绘制一切UI窗口,如剧情文本、怪物手册、楼传器、系统菜单等等 (z-index: 140)
|
||||
- data:数据层;用来绘制一些顶层的或更新比较快的数据,如左上角的提示,战斗界面中数据的变化等等。 (z-index: 170)
|
||||
|
||||
请注意:显示图片事件将自动创建一个图片层,z-index是100+图片编号。
|
||||
|
||||
而,色调层的z-index是25,ui层的z-index是140;因此,图片编号在1~24的将被色调层遮挡,25~40的将被ui层遮挡,41~50的将遮挡UI层。
|
||||
|
||||
### 动态创建canvas
|
||||
|
||||
从V2.5.3开始,可以在H5样板中任意动态创建canvas并进行使用。
|
||||
@ -104,11 +108,11 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana');
|
||||
从V2.5.4开始,贴图也允许进行帧动画,只要设置第五项的数值。
|
||||
|
||||
``` js
|
||||
"images": [[96,120,"bg.jpg",0]], // 背景图;你可以选择一张或多张图片来作为背景/前景素材。
|
||||
"images": [], // 无任何背景图
|
||||
"images": [[32,32,"house.png",0], [160,170,"bed.png",1]] // 在(32,32)放一个house.png在背景层,且(160,170)放bed.png在前景层
|
||||
"images": [[96,120,"tree.png",2]] // 如果写2,则会自动调节遮挡效果
|
||||
"images": [[64,0,"x.png",1,4]] // 这是一个前景层的4帧动画贴图
|
||||
[[96,120,"bg.jpg",0]] // 背景图;你可以选择一张或多张图片来作为背景/前景素材。
|
||||
[] // 无任何背景图
|
||||
[[32,32,"house.png",0], [160,170,"bed.png",1]] // 在(32,32)放一个house.png在背景层,且(160,170)放bed.png在前景层
|
||||
[[96,120,"tree.png",2]] // 如果写2,则会自动调节遮挡效果
|
||||
[[64,0,"x.png",1,4]] // 这是一个前景层的4帧动画贴图
|
||||
```
|
||||
|
||||
images为一个数组,代表当前层所有作为背景素材的图片信息。每一项为一个五元组,分别为该背景素材的x,y,图片名,遮挡方式和帧数。
|
||||
@ -129,18 +133,21 @@ images为一个数组,代表当前层所有作为背景素材的图片信息
|
||||
|
||||
关于楼层贴图和前景、背景层的层叠覆盖关系,默认是:**地板 - 背景贴图 - 背景图块 - 事件 - 勇士 - 前景贴图 - 前景图块**。
|
||||
|
||||
可以通过修改`libs/maps.js`的`drawMap`函数中下面三行的顺序来改变其覆盖关系。
|
||||
可以通过修改`libs/maps.js`的`drawBg`和`drawFg`函数来改变其覆盖关系。
|
||||
|
||||
``` js
|
||||
// ----- 可以调整这三行的顺序来修改覆盖关系;同层画布上,后绘制的覆盖先绘制的
|
||||
// ----- ui.js的drawThumbnail函数也需要对应进行修改。
|
||||
|
||||
// 绘制楼层贴图
|
||||
core.maps.drawFloorImages(floorId, images);
|
||||
// 绘制背景层图块
|
||||
core.maps.drawBgFgMap(floorId, core.canvas.bg, "bg", true);
|
||||
// 绘制前景层图块
|
||||
core.maps.drawBgFgMap(floorId, core.canvas.fg, "fg", true);
|
||||
////// 绘制背景层 //////
|
||||
maps.prototype.drawBg = function (floorId, ctx) {
|
||||
var onMap = ctx == null;
|
||||
if (onMap) {
|
||||
ctx = core.canvas.bg;
|
||||
core.clearMap(ctx);
|
||||
}
|
||||
this._drawBg_drawBackground(floorId, ctx);
|
||||
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。
|
||||
this._drawFloorImages(floorId, ctx, 'bg');
|
||||
this._drawBgFgMap(floorId, ctx, 'bg', onMap);
|
||||
}
|
||||
```
|
||||
|
||||
楼层贴图可以被事件隐藏和显示,详见[隐藏贴图](event#hideFloorImg:隐藏贴图)的写法。
|
||||
@ -192,7 +199,7 @@ ID必须由数字字母下划线组成,数字在1000以内,且均不能和
|
||||
|
||||
之后刷新编辑器即可。
|
||||
|
||||
对于怪物和道具,我们也可以进行自动注册,只需要点击“自动注册”按钮,将对该栏下所有未注册的素材进行自动注册(自动分配ID和数字)。
|
||||
我们也可以进行自动注册,只需要点击“自动注册”按钮,将对该栏下所有未注册的素材进行自动注册(自动分配ID和数字)。
|
||||
|
||||
素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。
|
||||
|
||||
@ -206,85 +213,6 @@ ID必须由数字字母下划线组成,数字在1000以内,且均不能和
|
||||
2. 下拉框选择autotile,然后点“追加”
|
||||
3. 看到成功的提示后刷新编辑器即可。
|
||||
|
||||
<!--
|
||||
|
||||
1. 将新的Autotile图片复制到images目录下。文件名必须是字母数字和下划线组成。
|
||||
2. 进入icons.js,在autotile分类下进行添加该文件的名称,索引简单的写0。
|
||||
3. 指定一个数字,在maps.js中类似进行添加。
|
||||
|
||||
!> Autotile的ID和文件名应确保完全相同!
|
||||
|
||||
-->
|
||||
<!--
|
||||
#### 新添加自定义地形(路面、墙壁等)
|
||||
|
||||
如果你在terrains.png中新增了一行:
|
||||
|
||||
1. 指定一个唯一的英文ID,不能和现有的重复。
|
||||
2. 进入icons.js,在terrains分类下进行添加索引(对应图标在图片上的位置,即index)
|
||||
|
||||
**如果你无须在游戏内使用本地形,而仅仅是将其作为“背景图”使用,则操作如下:**
|
||||
3. 修改对应楼层的剧本文件的`defaultGround`项,改成新的ID。
|
||||
|
||||
**如果你要在游戏内使用本地形,则操作如下:**
|
||||
3. 指定一个数字,在maps.js中类似进行添加。
|
||||
|
||||
#### 新添加Autotile
|
||||
|
||||
如果你需要新增一个Autotile:
|
||||
|
||||
1. 将新的Autotile图片复制到images目录下。
|
||||
2. 进入icons.js,在autotile分类下进行添加该文件的名称,索引简单的写0。
|
||||
3. 指定一个数字,在maps.js中类似进行添加。
|
||||
|
||||
!> Autotile的ID和文件名完全相同!且其ID/文件名不能含有中文、空格或特殊字符。
|
||||
|
||||
!> V2.0版本不能在地图编辑器中添加Autotile,请按上面的操作来执行。
|
||||
|
||||
#### 新添加道具
|
||||
|
||||
如果你需要新增一个未被定义的道具:
|
||||
|
||||
1. 指定一个唯一的英文ID,不能和现有的重复。
|
||||
2. 进入icons.js,在items分类下进行添加索引(对应图标在图片上的位置,即index)
|
||||
3. 指定一个数字,在maps.js中类似进行添加。
|
||||
4. 在items.js中仿照其他道具,来添加道具的信息。
|
||||
|
||||
有关如何自行实现一个道具的效果,参见[自定义道具效果](#自定义道具效果)。
|
||||
|
||||
#### 新添加怪物
|
||||
|
||||
如果我们需要新添加怪物,请在enemys.png中新增一行。
|
||||
|
||||
你可以通过便捷PS工具的“更改色相”来将红头怪变成橙头怪等。
|
||||
|
||||
然后执行如下操作:
|
||||
|
||||
1. 指定一个唯一的英文ID,不能和enemys中现有的重复。
|
||||
2. 进入icons.js,在enemys分类下进行添加索引(对应图标在图片上的位置,即index)
|
||||
3. 在maps.js中继续进行添加。
|
||||
4. 在enemys.js中仿照其他怪物,来添加怪物的信息。
|
||||
|
||||
!> 如果是48x32的怪物素材,请放在enemy48.png中,然后在icons.js的enemy48下添加索引。
|
||||
|
||||
有关如何自行实现一个怪物的特殊属性或伤害计算公式,参见[怪物的特殊属性](#怪物的特殊属性)。
|
||||
|
||||
#### 新添加NPC
|
||||
|
||||
1. 指定一个唯一的英文ID,不能和现有的重复。
|
||||
2. 进入icons.js,在npcs分类下进行添加索引(对应图标在图片上的位置,即index)
|
||||
3. 指定一个数字,在maps.js的getBlock下类似进行添加。
|
||||
|
||||
!> 如果是48x32的怪物素材,请放在npc48.png中,然后在icons.js的npc48下添加索引。
|
||||
|
||||
-->
|
||||
|
||||
### 地图生成器使用自定义素材
|
||||
|
||||
地图生成器是直接从js文件中读取数字-图标对应关系的。
|
||||
|
||||
因此,在你修改了icons.js和maps.js两个文件,也就是将素材添加到游戏后,地图生成器的对应关系也将同步更新。
|
||||
|
||||
### 额外素材
|
||||
|
||||
从V2.4.2开始,HTML5魔塔样板开始支持额外素材。
|
||||
@ -300,6 +228,7 @@ ID必须由数字字母下划线组成,数字在1000以内,且均不能和
|
||||
**该素材的宽高必须都是32的倍数,且图片上的总图块数不超过1000(即最多有1000个32*32的图块在该图片上)。**
|
||||
|
||||
```js
|
||||
// 在全塔属性中的tilesets导入素材
|
||||
"tilesets": ["1.png", "2.png"] // 导入两个额外素材,文件名分别是1.png和2.png
|
||||
```
|
||||
|
||||
@ -350,19 +279,6 @@ core.status.hero.atk += core.values.redJewel + 2*ratio
|
||||
|
||||
具体过程比较复杂,需要一定的JS能力,在这里就不多说了,有需求可以找`艾之葵`进行了解。
|
||||
|
||||
但值得一提的是,我们可以使用`core.hasItem(name)` 来判断是否某个道具是否存在。例如下面是passNet(通过路障处理)的一部分:
|
||||
|
||||
``` js
|
||||
/****** 经过路障 ******/
|
||||
events.prototype.passNet = function (data) {
|
||||
// 有鞋子
|
||||
if (core.hasItem('shoes')) return;
|
||||
if (data.event.id=='lavaNet') { // 血网
|
||||
// ... 下略
|
||||
```
|
||||
|
||||
我们进行了一个简单的判断,如果拥有绿鞋,则不进行任何路障的处理。
|
||||
|
||||
### 实战!拿到神圣盾后免疫吸血、领域、夹击效果
|
||||
|
||||
1. 在itemEffect中修改拿到神圣盾时的效果,标记一个自定义Flag。
|
||||
@ -421,109 +337,20 @@ function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) {
|
||||
|
||||
对于特殊的塔,我们可以考虑修改楼传事件来完成一些特殊的要求,比如镜子可以按楼传来切换表里。
|
||||
|
||||
要修改楼传事件,需要进行如下几步:
|
||||
要修改楼传事件,需要进行如下两步:
|
||||
|
||||
1. 截获楼传的点击事件。在control.js中找到useFly函数,并将其替换成如下内容:
|
||||
``` js
|
||||
////// 点击楼层传送器时的打开操作 //////
|
||||
control.prototype.useFly = function (need) {
|
||||
if (core.isMoving()) {
|
||||
core.drawTip("请先停止勇士行动");
|
||||
return;
|
||||
}
|
||||
if (core.status.lockControl || core.status.event.id != null) return;
|
||||
|
||||
if (core.canUseItem('fly')) core.useItem('fly');
|
||||
else core.drawTip("当前无法使用"+core.material.items.fly.name);
|
||||
}
|
||||
```
|
||||
1. 重写楼传的点击事件。在插件中对`core.control.useFly进行重写`。详细代码参见[重写点击楼传事件](script#重写点击楼传事件)。
|
||||
2. 修改楼传的使用事件。和其他永久道具一样,在地图编辑器的图块属性中修改楼传的useItemEffect和canUseItemEffect两个内容。例如:
|
||||
``` js
|
||||
"useItemEffect": "core.insertAction([...])" // 执行某段自定义事件,或者其他脚本
|
||||
"canUseItemEffect": "true" // 任何时候可用
|
||||
```
|
||||
修改时,请先把`null`改成空字符串`""`,然后再双击进行编辑。
|
||||
|
||||
<!--
|
||||
|
||||
## 自定义装备
|
||||
|
||||
由于HTML5魔塔并不像RM那样存在一个装备界面可供我们对装备进行调整,但是我们也可以使用一个替代的方式实现这个目标。
|
||||
|
||||
### 装备的实现原理
|
||||
|
||||
在HTML5中,装备将全部看成是永久道具(constants),同时对于每个装备位置,勇士都定义一个flag域表示正在装备的内容。
|
||||
|
||||
例如:当勇士获得银剑时,将获得一个永久道具“银剑”;当使用这个银剑,首先检查勇士当前是否装备了武器(比如铁剑),如果
|
||||
装备了则先脱掉装备(减去已装备的铁剑所加的属性,并获得永久道具铁剑),然后再穿上新的银剑。
|
||||
|
||||
同时由于脱剑术和脱盾术的存在,我们还需要一个“脱掉装备”的永久道具(比如sword0),使用它可以脱掉对应位置的装备。
|
||||
|
||||
### 装备加值的修改
|
||||
|
||||
要启用装备,首先需要在data.js(全塔属性)中设置`'equipment': true`。此时,游戏内将自动将剑盾变成装备的存在,其
|
||||
所加的数值就是全塔属性中对应的数值(比如铁剑sword1就加的全塔属性中sword1的值)。
|
||||
|
||||
有时候,我们还会有一个装备加多种属性的需求,此时需要将对应的项从数值改变成一个对象。
|
||||
|
||||
``` js
|
||||
"sword1": {"atk": 10, "def": 0, "mdef": 5}, // 铁剑加10攻和5魔防
|
||||
"shield1": {"atk": 0, "def": 10, "mdef": 10}, // 铁盾加10防和10魔防
|
||||
```
|
||||
|
||||
通过这种方式,当穿上装备时,将会给你的三围分别加上对应项的数值(支持负数,比如装剑减防御)。
|
||||
|
||||
### 新增剑盾
|
||||
|
||||
样板默认提供了铁剑(盾),银剑(盾),骑士剑(盾),圣剑(盾)和神圣剑(盾)这五类装备。但有时候,五类是不够的,
|
||||
我们可能还需要更多的剑盾。
|
||||
|
||||
要增加更多的剑盾,我们需要进行如下步骤:(以新增剑为例)
|
||||
|
||||
1. 新注册一个素材到游戏;**其ID必须是sword+数字的形式,比如sword6等。**(同理如果是盾就必须是shield+数字的形式比如shield6。)
|
||||
2. 将其cls设置为`constants`,`useItemEffect`和`canUseItem`直接复制其他几个剑盾的内容。
|
||||
(即:`useItemEffect`必须为`"core.plugin.useEquipment(itemId)"`,`canUseItemEffect`必须为`"true"`)。
|
||||
3. 使用VSCode或其他文本编辑器直接打开`data.js`文件,并在`"values"`中仿照已有的内容添加剑盾的属性。
|
||||
(例如:`"sword6": 100`,或者`"sword6": `{"atk": 100, "def": 0, "mdef": 50}`)
|
||||
|
||||
!> 请注意:新的剑的ID必须是sword+数字,新的盾的ID必须是shield+数字的形式,不然装备将无效!
|
||||
|
||||
### 新增其他部位的装备
|
||||
|
||||
如果我们还需要新增更多部位的装备,比如戒指、首饰等等,也是可以的,只需要依次进行如下步骤:(以新建戒指为例)
|
||||
|
||||
1. 选择一个装备的部位的ID;比如假设我们的装备部位为戒指,那么我们可以选择"ring"作为装备的部位。
|
||||
2. 定义一个空戒指,相当于脱掉戒指。注册一个素材到游戏,**其ID必须是ring0**(即部位ID+数字0)。
|
||||
3. 同上述新建剑盾的方式来设置ring0这个空戒指的属性。请注意打开data.js后,设置的其值必须为0。
|
||||
(即:必须是`"ring0": 0`)
|
||||
3. 创建更多的戒指;每加一个新的戒指到游戏,其ID必须是**ring+数字**的形式,比如`ring1`, `ring2`,等等。
|
||||
4. 对于每一个创建的戒指,按照上述新建剑盾的方式设置属性(图块属性,打开data.js直接编辑)。
|
||||
(例如:`"ring2": {"atk": 3, "def": 5, "mdef": 8}`)
|
||||
5. **切换到脚本编辑 - 自定义插件编写,在`this.useEquipment`中仿照着新增一行代表戒指的使用。**
|
||||
|
||||
``` js
|
||||
this.useEquipment = function (itemId) { // 使用装备
|
||||
_useEquipment(itemId, "sword", "atk"); // 剑
|
||||
_useEquipment(itemId, "shield", "def"); // 盾
|
||||
_useEquipment(itemId, "ring", "mdef"); // 新增的戒指
|
||||
}
|
||||
```
|
||||
|
||||
我们仿照着新增一行`_useEquipment(itemId, "ring", "mdef")`。
|
||||
|
||||
其中第二项为装备部位的ID,比如我们上述定义的是ring;第三项表示“如果values中该值为数字,则加到什么属性上”。
|
||||
比如如果我们这里写mdef,那么我们假设在data.js的values中设置`"ring1": 20`,则使用该戒指会增加20点魔防。
|
||||
|
||||
如果你定义的是对象`{"atk": xxx, "def": xxx, "mdef": xxx}`的形式,则不会受到第三项的影响。
|
||||
|
||||
!> 必须对于每一个装备部位定义唯一一个不同的ID;脱掉装备(空装备)必须是该ID加数字0的形式,其他有效装备必须是
|
||||
该ID+正整数的形式,不然会出错!
|
||||
|
||||
-->
|
||||
除了覆盖楼传事件外,对于快捷商店、虚拟键盘等等也可以进行覆盖,只不过是仿照上述代码重写对应的函数(`openQuickShop`,`openKeyBoard`)即可。
|
||||
|
||||
## 自定义怪物属性
|
||||
|
||||
如果你对现有的怪物不满意,想自行添加怪物属性也是可以的。具体参见脚本编辑-getSpecials。
|
||||
如果你对现有的怪物不满意,想自行添加怪物属性也是可以的。具体参见脚本编辑的getSpecials。
|
||||
|
||||
你需自己指定一个special数字,修改属性名和属性提示文字。后两者可以直接写字符串,或写个函数传入怪物。
|
||||
|
||||
@ -552,7 +379,8 @@ case 89: // 使用该按键的keyCode,比如Y键就是89
|
||||
// ... 在这里写你要执行脚本
|
||||
// **强烈建议所有新增的自定义快捷键均能给个对应的道具可点击,以方便手机端的行为**
|
||||
if (core.hasItem('...')) {
|
||||
core.useItem('...');
|
||||
core.status.route.push("key:0"); // 记录按键到录像中
|
||||
core.useItem('...', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像
|
||||
}
|
||||
|
||||
break;
|
||||
@ -560,6 +388,10 @@ case 89: // 使用该按键的keyCode,比如Y键就是89
|
||||
|
||||
强烈建议所有新增的自定义快捷键均给个对应的永久道具可点击,以方便手机端的行为。
|
||||
|
||||
使用`core.status.route.push("key:"+keyCode)`可以将这次按键记录在录像中。
|
||||
|
||||
!> 如果记录了按键,且使用道具的话,需要将useItem的第二个参数设为true,避免重复记录!
|
||||
|
||||
可以使用altKey来判断Alt键是否被同时按下。
|
||||
|
||||
## 公共事件
|
||||
@ -574,13 +406,9 @@ case 89: // 使用该按键的keyCode,比如Y键就是89
|
||||
|
||||
## 插件系统
|
||||
|
||||
在H5中,提供了“插件”系统。具体参见“脚本编辑 - 插件编写”。
|
||||
在H5中,提供了“插件”系统。在V2.6中提供了一个插件下拉框,用户可以自行创建和写插件。
|
||||
|
||||

|
||||
|
||||
当我们在这上面定义了自己需要的函数(插件后),就可以通过任何方式进行调用。
|
||||
|
||||
在这个插件编写的过程中,我们可以使用任何[常见API](api)里面的代码调用;也可以通过`core.insertAction`来插入自定义事件执行。
|
||||
在插件编写的过程中,我们可以使用任何[常见API](api)里面的代码调用;也可以通过`core.insertAction`来插入自定义事件执行。
|
||||
|
||||
下面是一个很简单的例子,我编写一个插件函数,其效果是让勇士生命值变成原来的x倍,并令面前的图块消失。
|
||||
|
||||
@ -599,11 +427,13 @@ this.myfunc = function(x) {
|
||||
|
||||
网站上也提供了一个[插件库](https://h5mota.com/plugins/),欢迎大家把自己写的插件进行共享。
|
||||
|
||||
从V2.6开始,在插件中用`this.xxx`定义的函数将会被转发到core中。例如上述的`myfunc`除了`core.plugin.myfunc`外也可以直接`core.myfunc`调用。
|
||||
|
||||
详见[函数的转发](script#函数的转发)。
|
||||
|
||||
## 标题界面事件化
|
||||
|
||||
从V2.5.3开始,我们可以将标题界面的绘制和游戏开始用事件来完成。可以通过绘制画布、
|
||||
|
||||
全塔属性,flags中的startUsingCanvas可以决定是否开启标题界面事件化。
|
||||
从V2.5.3开始,我们可以将标题界面的绘制和游戏开始用事件来完成。可以通过绘制画布、全塔属性,flags中的startUsingCanvas可以决定是否开启标题界面事件化。
|
||||
|
||||
然后就可以使用“事件流”的形式来绘制标题界面、提供选项等等。
|
||||
|
||||
@ -619,36 +449,70 @@ this.myfunc = function(x) {
|
||||
|
||||
从V2.5.3以后,我们可以给手机端增加按键了,这样将非常有利于技能的释放。
|
||||
|
||||
当用户在竖屏模式下点击工具栏,就会在工具栏按钮和快捷键模式之间进行切换。
|
||||
用户在菜单栏打开“拓展键盘”后,在竖屏模式下点击工具栏,就会在工具栏按钮和快捷键模式之间进行切换。
|
||||
|
||||
切换到快捷键模式后,可以点1-7,分别等价于在电脑端按键1-7。
|
||||
切换到快捷键模式后,可以点1-8,分别等价于在电脑端按键1-8。
|
||||
|
||||
可以在脚本编辑的onKeyUp中定义每个快捷键的使用效果,比如使用道具或释放技能等。
|
||||
|
||||
默认值下,1使用破,2使用炸,3使用飞,4使用其他存在的道具,5-7未定义。可以相应修改成自己的效果。
|
||||
默认值下,1使用破,2使用炸,3使用飞,4使用其他存在的道具,5-8未定义。可以相应修改成自己的效果。
|
||||
|
||||
也可以替换icons.png中的对应图标,以及修改main.js中`main.statusBar.image.btn1~7`中的onclick事件来自定义按钮和对应按键。
|
||||
也可以替换icons.png中的对应图标,以及修改main.js中`main.statusBar.image.btn1~8`中的onclick事件来自定义按钮和对应按键。
|
||||
|
||||
非竖屏模式下、回放录像中、隐藏状态栏中,将不允许进行切换。
|
||||
|
||||
## 自定义状态栏(新增显示项)
|
||||
## 自绘状态栏
|
||||
|
||||
从V2.5.3开始允许自绘状态栏。要自绘状态栏,则应该打开全塔属性中的`statusCanvas`开关。
|
||||
|
||||
自绘模式下,全塔属性中的`statusCanvasRowsOnMobile`将控制竖屏模式下的状态栏行数。
|
||||
|
||||
开启自绘模式后,可以在脚本编辑的`drawStatusBar`中自行进行绘制。
|
||||
|
||||
横屏模式下的状态栏为`129x416`(15x15则是`149x480`);竖屏模式下的状态栏为`416*(32*rows+9)`(15x15是480)。
|
||||
|
||||
具体可详见脚本编辑的`drawStatusBar`函数。
|
||||
|
||||
## 自定义状态栏的显示项
|
||||
|
||||
在V2.2以后,我们可以自定义状态栏背景图(全塔属性 - statusLeftBackground)等等。
|
||||
|
||||
但是,如果我们还想新增其他项目的显示,比如攻速或者暴击,该怎么办?
|
||||
|
||||
需要进行如下几个操作:
|
||||
我们可以[自绘状态栏](#自绘状态栏),或者采用下面两个方式之一来新增。
|
||||
|
||||
### 利用已有项目
|
||||
|
||||
一个最为简单的方式是,直接利用已有项目。
|
||||
|
||||
例如,如果本塔中没有技能栏,则可以使用技能栏所对应的显示项。
|
||||
|
||||
1. 覆盖project/icons.png中技能的图标
|
||||
2. 打开全塔属性的enableSkill开关
|
||||
3. 在脚本编辑-updateStatusBar中可以直接替换技能栏的显示内容
|
||||
|
||||
```
|
||||
// 设置技能栏
|
||||
if (core.flags.enableSkill) {
|
||||
// 替换成你想显示的内容,比如你定义的一个flag:abc。
|
||||
core.setStatusBarInnerHTML('skill', core.getFlag("abc", 0));
|
||||
}
|
||||
```
|
||||
|
||||
### 额外新增新项目
|
||||
|
||||
如果是在需要给状态栏新定义项目,则需要进行如下几个操作:
|
||||
|
||||
1. 定义ID;比如攻速我就定义speed,暴击可以简单的定义baoji;你也可以定义其他的ID,但是不能和已有的重复。这里以speed为例。
|
||||
2. 在index.html的statusBar中(44行起),进行该状态栏项的定义。仿照其他几项,插在其应当显示的位置,注意替换掉相应的ID。
|
||||
2. 在index.html的statusBar中(46行起),进行该状态栏项的定义。仿照其他几项,插在其应当显示的位置,注意替换掉相应的ID。
|
||||
``` html
|
||||
<div class="status" id="speedCol">
|
||||
<img id="img-speed">
|
||||
<p class='statusLabel' id='speed'></p>
|
||||
</div>
|
||||
```
|
||||
3. 在editor.html中的statusBar(323行起),仿照第二点同样添加;这一项如果不进行则会地图编辑器报错。editor-mobile.html同理。
|
||||
4. 使用便捷PS工具,打开icons.png,新增一行并将魔力的图标P上去;记下其索引比如37(从0开始数)。
|
||||
3. 在editor.html中的statusBar(383行起),仿照第二点同样添加;这一项如果不进行则会地图编辑器报错。editor-mobile.html同理。
|
||||
4. 使用便捷PS工具,打开project/icons.png,新增一行并将魔力的图标P上去;记下其索引比如37(从0开始数)。
|
||||
5. 在main.js的this.statusBar中增加图片、图标和内容的定义。
|
||||
``` js
|
||||
this.statusBar = {
|
||||
@ -674,17 +538,15 @@ core.statusBar.speed.innerHTML = core.getFlag('speed', 0);
|
||||
|
||||
## 技能塔的支持
|
||||
|
||||
其实,在HTML5上制作技能塔是完全可行的。
|
||||
|
||||
要支持技能塔,可能需要如下几个方面:
|
||||
|
||||
从V2.5开始,内置了"二倍斩"技能,可以仿照其制作自己的技能。
|
||||
|
||||
- 魔力(和上限)的添加;技能的定义
|
||||
- 状态栏的显示
|
||||
- 技能的触发(按键与录像问题)
|
||||
- 技能的效果
|
||||
|
||||
从V2.5开始,内置了"二倍斩"技能,可以仿照其制作自己的技能。
|
||||
|
||||
### 魔力的定义添加;技能的定义
|
||||
|
||||
从V2.5开始,提供了status:mana选项,可以直接代表当前魔力值。
|
||||
@ -697,6 +559,8 @@ core.statusBar.speed.innerHTML = core.getFlag('speed', 0);
|
||||
|
||||
如果flag:skill不为0,则代表当前处于某个技能开启状态,且状态栏显示flag:skillName值。伤害计算函数中只需要对flag:skill进行处理即可。
|
||||
|
||||
!> 关于魔力上限:样板中默认没有提供status:manamax
|
||||
|
||||
### 状态栏的显示
|
||||
|
||||
从V2.5开始,魔力值和技能名的状态栏项目已经被添加,可以直接使用。
|
||||
@ -706,9 +570,14 @@ core.statusBar.speed.innerHTML = core.getFlag('speed', 0);
|
||||
``` js
|
||||
// 设置魔力值
|
||||
if (core.flags.enableMana) {
|
||||
// 也可以使用flag:manaMax来表示最大魔力值
|
||||
// core.status.hero.mana = Math.max(core.status.hero.mana, core.getFlag('manaMax', 10));
|
||||
// core.statusBar.mana.innerHTML = core.status.hero.mana + "/" + core.getFlag('manaMax', 10);
|
||||
// status:manamax 只有在非负时才生效。
|
||||
if (core.status.hero.manamax != null && core.status.hero.manamax >= 0) {
|
||||
core.status.hero.mana = Math.min(core.status.hero.mana, core.status.hero.manamax);
|
||||
core.setStatusBarInnerHTML('mana', core.status.hero.mana + "/" + core.status.hero.manamax);
|
||||
}
|
||||
else {
|
||||
core.setStatusBarInnerHTML("mana", core.status.hero.mana);
|
||||
}
|
||||
}
|
||||
// 设置技能栏
|
||||
if (core.flags.enableSkill) {
|
||||
@ -761,14 +630,15 @@ else { // 关闭技能
|
||||
case 87: // W:开启技能“二倍斩”
|
||||
// 检测技能栏是否开启,是否拥有“二倍斩”这个技能道具
|
||||
if (core.flags.enableSkill && core.hasItem('skill1')) {
|
||||
core.useItem('skill1');
|
||||
core.status.route.push("key:87");
|
||||
core.useItem('skill1', true);
|
||||
}
|
||||
break;
|
||||
```
|
||||
|
||||
在勇士处于停止的条件下,按下W键时,判断技能的道具是否存在,如果存在再使用它。
|
||||
|
||||
!> 1,2,3这三个键被默认绑定到了破炸飞;如果想用的话也是一样,只不过是把已有的实现进行替换。
|
||||
!> 由于现在手机端存在拓展键盘,也强烈建议直接覆盖1-8的使用效果,这样手机端使用也非常方便。
|
||||
|
||||
### 技能的效果
|
||||
|
||||
@ -816,141 +686,6 @@ if (core.flags.enableSkill) {
|
||||
|
||||
通过上述这几种方式,我们就能成功的让H5支持技能啦!
|
||||
|
||||
## 成就系统
|
||||
|
||||
我们还可以给HTML5魔塔增加成就系统。注意到成就是和游戏相关,因此需要使用getLocalStorage而不是getFlag判定。
|
||||
|
||||
可将下面的代码粘贴到脚本编辑 - 插件编写中。
|
||||
|
||||
``` js
|
||||
// 所有成就项的定义
|
||||
this.achievements = [
|
||||
// 每行一个,分别定义flag、名称、描述、是否存在提示、成就点数
|
||||
{"flag": "a1", "name": "成就1", "text": "成就1的达成描述", "hint": false, "point": 1},
|
||||
// 可以继续往后新增其他的。
|
||||
];
|
||||
|
||||
// 达成成就;如 core.plugin.achieve("a1") 即达成a1对应的成就
|
||||
this.achieve = function (flag) {
|
||||
// 获得已达成的成就;如果跟存档而不是跟游戏则改成getFlag
|
||||
var achieved = core.getLocalStorage("achievements", []);
|
||||
var point = core.getLocalStorage("achievePoint", 0);
|
||||
// 已经获得该成就
|
||||
if (achieved.indexOf(flag)>=0) return;
|
||||
// 尝试达成成就;找到对应的成就项
|
||||
this.achievements.forEach(function (one) {
|
||||
if (one.flag == flag) {
|
||||
// 执行达成成就的操作;也可以自行在上面加上达成成就后的事件
|
||||
core.insertAction("\t[达成成就:"+one.name+"]"+one.text);
|
||||
point += one.point || 0;
|
||||
}
|
||||
});
|
||||
achieved.push(flag);
|
||||
// 存入localStorage中;如果跟存档走则使用setFlag
|
||||
core.setLocalStorage("achievements", achieved);
|
||||
core.setLocalStorage("achievePoint", point);
|
||||
}
|
||||
|
||||
// 获得所有成就说明;这里简单使用两个insertAction,你也可以修改成自己的实现
|
||||
// 简单一点的可以使用insertAction+剧情文本;稍微复杂一点的可以使用图片化文本等;更复杂的可以自绘UI。
|
||||
this.getAchievements = function () {
|
||||
var achieved = core.getLocalStorage("achievements", []);
|
||||
var yes = [], no = [];
|
||||
// 对所有成就进行遍历
|
||||
this.achievements.forEach(function (one) {
|
||||
// 检测是否达成
|
||||
if (achieved.indexOf(one.flag)>=0) {
|
||||
yes.push(one.name+":"+one.text);
|
||||
}
|
||||
else {
|
||||
no.push(one.name+":"+(one.hint?one.text:"达成条件请自行探索"));
|
||||
}
|
||||
});
|
||||
core.insertAction([
|
||||
"\t[已达成的成就]"+(yes.length==0?"暂无":yes.join("\n")),
|
||||
"\t[尚未达成的成就]"+(no.length==0?"暂无":no.join("\n"))
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 多角色的支持
|
||||
|
||||
其实,我们的样板还能支持多角色的制作。比如《黑·白·间》之类的塔也是完全可以刻的。
|
||||
|
||||
你只需要如下几步来达到多角色的效果。
|
||||
|
||||
1. 每个角色弄一张行走图。相关信息参见[自定义事件:setHeroIcon](event#setHeroIcon:更改角色行走图)。
|
||||
2. [覆盖楼传事件](#覆盖楼传事件),这样可以通过点工具栏的楼层传送按钮来切换角色。当然你也完全可以自己写一个道具,或[自定义快捷键](#自定义快捷键)来进行绑定。
|
||||
3. 将下述代码直接贴入脚本编辑 - 插件编写中。
|
||||
``` js
|
||||
// 所有需要保存的内容;这些保存的内容不会多角色共用,在切换时会进行恢复。
|
||||
// 你也可以自行新增或删除,比如不共用金币则可以加上"money"的初始化,不共用道具则可以加上"items"的初始化,
|
||||
// 多角色共用hp的话则删除hp,等等。总之,不共用的属性都在这里进行定义就好。
|
||||
var hero1 = { // 1号勇士(默认的是0号)
|
||||
"floorId": "MT0", // 该角色楼层ID
|
||||
"icon": "hero1.png", // 角色的行走图名称
|
||||
"name": "1号角色",
|
||||
"lv": 1,
|
||||
"hp": 1000,
|
||||
"atk": 10,
|
||||
"def": 10,
|
||||
"mdef": 0,
|
||||
"loc": {"x": 0, "y": 0, "direction": "up"},
|
||||
// 如果道具不共用就将下面这句话取消注释
|
||||
// "items": {"keys":{"yellowKey":0,"blueKey":0,"redKey":0},"tools":{},"constants":{}}
|
||||
}
|
||||
// 也可以类似新增其他勇士
|
||||
// var hero2 = { ...
|
||||
|
||||
var heroCount = 2; // 包含默认的在内总共多少个勇士,该值需手动修改。
|
||||
|
||||
// 初始化该勇士
|
||||
this.initHeros = function () {
|
||||
core.status.hero.icon = "hero.png";
|
||||
core.setFlag("hero1", core.clone(hero1)); // 将属性值存到变量中
|
||||
// core.setFlag("hero2", core.clone(hero2)); // 更多的勇士...
|
||||
}
|
||||
|
||||
// 切换勇士
|
||||
this.changeHero = function (toHeroId) {
|
||||
var currHeroId = core.getFlag("heroId", 0); // 获得当前角色ID
|
||||
if (!core.isset(toHeroId)) {
|
||||
toHeroId = (currHeroId+1)%heroCount;
|
||||
}
|
||||
if (currHeroId == toHeroId) return;
|
||||
|
||||
var saveList = Object.keys(hero1);
|
||||
|
||||
// 保存当前内容
|
||||
var toSave = {};
|
||||
saveList.forEach(function(name) {
|
||||
if (name=='floorId') toSave[name] = core.status.floorId; // 楼层单独设置
|
||||
else toSave[name] = core.clone(core.status.hero[name]); // 使用core.clone()来创建新对象
|
||||
})
|
||||
|
||||
core.setFlag("hero"+currHeroId, toSave); // 将当前角色信息进行保存
|
||||
var data = core.getFlag("hero"+toHeroId); // 获得要切换的角色保存内容
|
||||
|
||||
// 设置角色的属性值
|
||||
saveList.forEach(function(name) {
|
||||
if (name != 'floorId')
|
||||
core.status.hero[name] = core.clone(data[name]);
|
||||
})
|
||||
|
||||
// 插入事件:改变角色行走图并进行楼层切换
|
||||
core.insertAction([
|
||||
{"type": "setHeroIcon", "name": data.icon||"hero.png"}, // 改变行走图
|
||||
{"type": "changeFloor", "floorId": data.floorId, "loc": [data.loc.x, data.loc.y],
|
||||
"direction": data.loc.direction, "time": 0} // 楼层切换事件
|
||||
])
|
||||
core.setFlag("heroId", toHeroId); // 保存切换到的角色ID
|
||||
}
|
||||
```
|
||||
3. 在脚本编辑 - setInitData中加上`core.plugin.initHeros()`来初始化新勇士。(写在`core.events.afterLoadData()`后,反大括号之前。)
|
||||
4. 如果需要切换角色(包括事件、道具或者快捷键等),可以直接调用自定义JS脚本:`core.plugin.changeHero();`进行切换。也可以指定参数调用`core.plugin.changeHero(1)`来切换到某个具体的勇士上。
|
||||
|
||||
## 系统使用的flag变量
|
||||
|
||||
众所周知,自定义flag变量都可以任意定义并取用(未定义直接取用的flag默认值为0)。
|
||||
@ -979,4 +714,4 @@ this.getAchievements = function () {
|
||||
|
||||
==========================================================================================
|
||||
|
||||
[继续阅读附录:所有API列表](api)
|
||||
[继续阅读脚本](script)
|
||||
|
||||
324
_docs/script.md
Normal file
324
_docs/script.md
Normal file
@ -0,0 +1,324 @@
|
||||
# 脚本
|
||||
|
||||
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
|
||||
|
||||
在V2.6版本中,基本对整个项目代码进行了重写,更加方便造塔者的使用和复写函数。
|
||||
|
||||
## 控制台的使用
|
||||
|
||||
在Chrome浏览器中,按(Ctrl+Shift+I)可打开控制台。
|
||||
|
||||

|
||||
|
||||
控制台中有很多的标签,最常用的是`Console`, `Sources`和`Elements`。
|
||||
|
||||
有关更详尽的控制台使用可自行搜索[Chrome开发者工具](https://www.baidu.com/s?wd=chrome%20%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7)了解更多。
|
||||
|
||||
### Console:命令行
|
||||
|
||||
Console页为命令行。可以在这里输入一些命令进行调试。
|
||||
|
||||
比如,进入游戏后,输入`core.status.hero.atk`即可获得勇士的当前攻击力数值。`core.status.hero.atk=100`可以设置攻击力为100。
|
||||
|
||||
更多的API可参见[附录:API列表](#附录:API列表)。
|
||||
|
||||
除此以外,游戏中的报错等信息也是可以在Console中进行查看的。
|
||||
|
||||

|
||||
|
||||
### Sources:断点调试
|
||||
|
||||
Sources页可以查看JS源代码,并进行断点调试等。
|
||||
|
||||
例如,如果相对脚本编辑中的伤害计算函数进行断点调试:
|
||||
1. 在左边找到`project/functions.js`,单击打开文件
|
||||
2. 并找到对应的行(可以Ctrl+F搜索),比如搜索`getDamageInfo`
|
||||
3. 在行号上点一下打断点,会出现一个蓝色标签
|
||||
|
||||
之后,当代码运行到你的断点处时,将自动停止运行。
|
||||
|
||||

|
||||
|
||||
可以将鼠标移动到变量上,将弹窗形式显示这个变量的各项数值,从而查看变量值是否符合预期。
|
||||
|
||||
图中红色框内有几个按钮,从左到右分别是:**继续执行**,**执行到下一行**,**进入当前函数**,**跳出当前函数**,**单步执行**。
|
||||
|
||||
通过这几个按钮,可以一行一行的对代码进行执行,执行过程中能不断查看各个变量的数值变化,从而定位问题所在。
|
||||
|
||||
红圈下方是Call Stack,即当前的函数调用链(从哪些地方调用过来的)。
|
||||
|
||||
Sources还有更多有趣的功能,在此不做介绍,有兴趣的可自行网上搜索了解。
|
||||
|
||||
### Elements:网页元素查看
|
||||
|
||||
Elements页可以查看网页的源代码,调整css布局等。
|
||||
|
||||

|
||||
|
||||
不过对魔塔样板来说,最重要的是红圈中的按钮。点击此按钮可以进入**手机模式**。
|
||||
|
||||
手机模式下,左边可以对屏幕分辨率进行调整和模拟。
|
||||
|
||||
这可以很有效的帮我们进行测试样板在手机端的表现。
|
||||
|
||||
## 整体项目架构
|
||||
|
||||
``` text
|
||||
├── /_server/ # 为可视化地图编辑器提供一些支持的目录
|
||||
├── /libs/ # ---- 系统库目录 ----
|
||||
│ ├─ /thirdparty/ # 游戏所用到的第三方库文件
|
||||
│ ├─ actions.js # 用户交互处理
|
||||
│ ├─ core.js # 系统核心文件(游戏入口,接口&转发)
|
||||
│ ├─ control.js # 游戏逻辑控制
|
||||
│ ├─ data.js # 全塔属性等
|
||||
│ ├─ enemys.js # 怪物相关处理
|
||||
│ ├─ events.js # 各个事件的执行
|
||||
│ ├─ icons.js # 图标和素材
|
||||
│ ├─ items.js # 道具效果
|
||||
│ ├─ loader.js # 各个资源加载
|
||||
│ ├─ maps.js # 地图数据和绘制
|
||||
│ ├─ ui.js # UI窗口绘制
|
||||
│ └─ utils.js # 工具类函数
|
||||
├── /project/ # ---- 项目目录 ----
|
||||
│ ├─ /animates/ # 动画目录
|
||||
│ ├─ /floors/ # 楼层文件
|
||||
│ ├─ /images/ # 图片素材
|
||||
│ ├─ /sounds/ # bgm和音效
|
||||
│ ├─ data.js # 全塔属性
|
||||
│ ├─ enemys.js # 怪物属性
|
||||
│ ├─ events.js # 公共事件
|
||||
│ ├─ functions.js # 脚本编辑
|
||||
│ ├─ icons.js # 素材和ID的对应关系定义
|
||||
│ ├─ items.js # 道具的定义和效果
|
||||
│ ├─ maps.js # 地图和数字的对应关系
|
||||
│ └─ plugins.js # 自定义插件
|
||||
├── /常用工具/ # 辅助造塔的小工具
|
||||
├── editor.html # 地图编辑器
|
||||
├── editor-mobile.html # 手机版的地图编辑器
|
||||
├── index.html # 主程序,游戏的入口
|
||||
├── main.js # JS程序的入口,将动态对所需JS进行加载
|
||||
├── style.css # 游戏所需要用到的样式表
|
||||
└── 启动服务.exe # 一个本地的HTTP服务器,通过它来运行游戏
|
||||
```
|
||||
|
||||
`_server`为**地图编辑器目录**,里面存放了地图编辑器相关的各项内容。
|
||||
|
||||
`libs`为**系统库目录**,里面存放了各个系统核心函数。
|
||||
|
||||
从V2.6开始,请勿直接修改libs下的代码,如有需要修改系统库函数请尝试在插件中[复写函数](#复写函数)。
|
||||
|
||||
`project`为**项目目录**,你所造的塔的数据全部存放在project下。在不同样板之间接档也是直接迁移project目录即可。
|
||||
|
||||
## 函数的转发
|
||||
|
||||
在本样板中,`core.js`里面基本是没有定义什么函数的,所有的游戏内函数都在其他几个文件中实现。
|
||||
|
||||
例如,常见的获得某个变量值`getFlag`是定义在`control.js`中的:
|
||||
|
||||
```js
|
||||
////// 获得某个自定义变量或flag //////
|
||||
control.prototype.getFlag = function(name, defaultValue) {
|
||||
if (!core.status.hero) return defaultValue;
|
||||
var value = core.status.hero.flags[name];
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
```
|
||||
|
||||
也就是,我们可以通过`core.control.getFlag(name, value)`来调用此函数。
|
||||
|
||||
但是这样会十分不便,我们希望能直接调用`core.getFlag(name, value)`,而不需要中间的control。
|
||||
|
||||
为了达到这个目的,样板设置了**函数转发**,即**将其他文件中定义的函数,转发到core中执行**。
|
||||
|
||||
上述`getFlag`代码的转发实际上是增加了如下函数:
|
||||
|
||||
```js
|
||||
////// getFlag函数的转发 //////
|
||||
core.getFlag = function (name, defaultValue) {
|
||||
return core.control.getFlag(name, defaultValue);
|
||||
}
|
||||
// 转发后,即可通过 core.getFlag() 来实际调用 core.control.getFlag()
|
||||
```
|
||||
|
||||
转发是自动完成的,其满足如下两条规则:
|
||||
- **在libs中其他文件定义的函数,如果不以下划线`_`开头,就会进行转发。**
|
||||
- **如果core中已经存在同名函数,则会在控制台中打出一条报错信息,并不转发该函数。**
|
||||
|
||||
具体函数的转发实现代码可参见`core.js`的`_forwardFunc`函数。
|
||||
|
||||
!> 除此以外,插件中以`this.xxx`来定义的函数也会被转发!
|
||||
|
||||
例如,你可以直接调用`core.drawLight()`来实际调用插件中的`core.plugin.drawLight`。
|
||||
|
||||
## 插件编写
|
||||
|
||||
插件编写是H5魔塔的一个重大特点,从V2.0.1引入,并逐渐发扬光大。
|
||||
|
||||
对于有一定脚本经验的人来说,可以编写插件来实现各种各样的功能,包括且不仅限于拓展功能的实现,系统代码的复写等等。
|
||||
|
||||
在V2.5.5以前,插件位置都在脚本编辑中;从V2.6开始则迁移到了新的下拉框中,并进行了切分。
|
||||
|
||||
你也可以创建自己的插件。
|
||||
|
||||

|
||||
|
||||
新的插件切分和原来的单插件使用方法完全一致,单纯进行了切分而已。可参见已有的`init`和`drawLight`的样例。
|
||||
|
||||
拆分的意义主要是将各个可能的功能独立出来,避免单个框内内容太长,过大和混杂等。
|
||||
|
||||
在V2.6中,应当每个独立的额外功能实现都新建一个自己的插件,这样也方便进行拓展,例如打包迁移到别的塔上,或发布在网页插件库中。
|
||||
|
||||
另外一点需要注意的是,所有插件的初始化都会在系统资源加载之前,此时图片等资源尚未进行加载。
|
||||
|
||||
在所有资源加载完毕时,将会执行init插件中的_afterLoadResources函数,可以在这里对资源进行一些操作,比如切分图片等。
|
||||
|
||||
```js
|
||||
function () {
|
||||
console.log("插件编写测试");
|
||||
|
||||
// 可以写一些直接执行的代码
|
||||
// 在这里写的代码将会在【资源加载前】被执行,此时图片等资源尚未被加载。
|
||||
// 请勿在这里对包括bgm,图片等资源进行操作。
|
||||
|
||||
|
||||
this._afterLoadResources = function () {
|
||||
// 本函数将在所有资源加载完毕后,游戏开启前被执行
|
||||
// 可以在这个函数里面对资源进行一些操作,比如切分图片等。
|
||||
|
||||
// 这是一个将assets.png拆分成若干个32x32像素的小图片并保存的样例。
|
||||
// var arr = core.splitImage("assets.png", 32, 32);
|
||||
// for (var i = 0; i < arr.length; i++) {
|
||||
// core.material.images.images["asset"+i+".png"] = arr[i];
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx();
|
||||
// 从V2.6开始,插件中用this.XXX方式定义的函数也会被转发到core中,详见文档-脚本-函数的转发。
|
||||
}
|
||||
```
|
||||
|
||||
网站上提供了一个插件库,[https://h5mota.com/plugins/](https://h5mota.com/plugins/),上面有一些大家分享的插件,可供使用。
|
||||
|
||||
可以查看附录中的[API列表](api)来查看所有的系统API内容。
|
||||
|
||||
## 复写函数
|
||||
|
||||
样板的功能毕竟是写死的,有时候我们也需要修改样板的一些行为。
|
||||
|
||||
在V2.6以前,需要直接打开libs目录下的对应文件并进行修改。但是开libs下的文件就会出现各种问题:
|
||||
|
||||
- 不容易记得自己修改过什么,而且如果改错了很麻烦
|
||||
- 例如,直接修改了某函数加了新功能,结果过段时间发现不需要,想删掉,但是这时候已经很难找到自己改过了什么了。
|
||||
- 或者,如果代码改错了,不断往上面打补丁,也只会使得libs越来越乱,最后连自己做过什么都不记得。
|
||||
- 不容易随着新样板接档进行迁移
|
||||
- 不方便能整理成新的插件在别的塔使用(总不能让别的塔也去修改libs吧)
|
||||
- ……
|
||||
|
||||
好消息的是,从V2.6开始,我们再也不需要开文件了,而是可以直接在插件中对原始函数进行复写。
|
||||
|
||||
函数复写的好处如下:
|
||||
|
||||
- 不会影响系统原有代码。
|
||||
- 即使写错了或不需要了,也只用把插件中的函数注释或删除即可,不会对原来的系统代码产生任何影响。
|
||||
- 清晰明了。很容易方便知道自己修改过什么,尤其是可以和系统原有代码进行对比。
|
||||
- 方便整理成新的插件,给其他的塔使用。
|
||||
|
||||
如果我想对xxx文件中的yyy函数进行重写,其模式一般是:`core.xxx.yyy = function (参数列表) { ... }`
|
||||
|
||||
下面是几个例子,从简单到复杂。
|
||||
|
||||
### 重写怪物手册的背景图绘制,使用winskin而不是默认的黑色
|
||||
|
||||
直接重写怪物手册的背景图绘制,使用`core.drawBackground`来用winskin绘制一个背景图。
|
||||
|
||||
```js
|
||||
// 重写ui.js中的_drawBook_drawBackground函数
|
||||
core.ui._drawBook_drawBackground = function () {
|
||||
// core.__PIXELS__为定义的一个宏,对于13x13的值是416,对于15x15的值是480
|
||||
core.drawBackground(0, 0, core.__PIXELS__, core.__PIXELS__);
|
||||
}
|
||||
```
|
||||
|
||||
### 重写点击楼传事件
|
||||
|
||||
重写点击楼传事件,使得点击楼传按钮时能使用一个道具(比如item:fly)。
|
||||
|
||||
```js
|
||||
// 重写events.js的useFly函数,即点击楼传按钮时的事件
|
||||
core.events.useFly = function (fromUserAction) {
|
||||
if (core.isMoving()) {
|
||||
core.drawTip("请先停止勇士行动");
|
||||
return;
|
||||
}
|
||||
if (core.status.lockControl || core.status.event.id != null) return;
|
||||
|
||||
if (core.canUseItem('fly')) core.useItem('fly');
|
||||
else core.drawTip("当前无法使用"+core.material.items.fly.name);
|
||||
}
|
||||
```
|
||||
|
||||
其他的几个按钮,如快捷商店`openQuickShop`,虚拟键盘`openKeyBoard`的重写也几乎完全一样。
|
||||
|
||||
### 楼层切换时根据flag来播放不同的音效
|
||||
|
||||
整体复制并重写整个楼传切换前的函数,将`core.playSound('floor.mp3')`替换成根据flag来判定。
|
||||
|
||||
```js
|
||||
// 复制重写events.js中的_changeFloor_beforeChange,修改音效
|
||||
core.events._changeFloor_beforeChange = function (info, callback) {
|
||||
// 直接替换原始函数中的 core.playSound('floor.mp3');
|
||||
if (core.getFlag("floorSound") == 0) core.playSound('floor0.mp3');
|
||||
if (core.getFlag("floorSound") == 1) core.playSound('floor1.mp3');
|
||||
if (core.getFlag("floorSound") == 2) core.playSound('floor2.mp3');
|
||||
// ...
|
||||
|
||||
// 下面是原始函数中的剩余代码,保持不变
|
||||
window.setTimeout(function () {
|
||||
if (info.time == 0)
|
||||
core.events._changeFloor_changing(info, callback);
|
||||
else
|
||||
core.showWithAnimate(core.dom.floorMsgGroup, info.time / 2, function () {
|
||||
core.events._changeFloor_changing(info, callback);
|
||||
});
|
||||
}, 25)
|
||||
}
|
||||
```
|
||||
|
||||
### 每次打开全局商店时播放一个音效
|
||||
|
||||
打开全局商店是在`events.js`中的`openShop`函数,因此需要对其进行重写。
|
||||
|
||||
然而,我们只需要在这个函数执行之前插一句音效播放,所以并不需要重写整个函数,而是直接插入一行就行。
|
||||
|
||||
```js
|
||||
var openShop = core.events.openShop; // 先把原始函数用一个变量记录下来
|
||||
core.events.openShop = function (shopId, needVisited) {
|
||||
core.playSound("shop.mp3"); // 播放一个音效
|
||||
return openShop(shopId, needVisited); // 直接调用原始函数
|
||||
}
|
||||
```
|
||||
|
||||
### 每次绘制地图前在控制台打出一条信息
|
||||
|
||||
绘制地图在`maps.js`的`drawMap`函数,因此需要对其进行重写。
|
||||
|
||||
由于只需要额外在函数执行前增加一句控制台输出,所以直接插入一行即可。
|
||||
|
||||
但是需要注意的是,`drawMap`中使用了`this._drawMap_drawAll()`,因此使用函数时需要用`call`或者`apply`来告知this是什么。
|
||||
|
||||
```js
|
||||
var drawMap = core.maps.drawMap; // 先把原始函数用一个变量记录下来
|
||||
core.maps.drawMap = function (floorId, callback) {
|
||||
console.log("drawMap..."); // 控制台打出一条信息
|
||||
return drawMap.call(core.maps, floorId, callback); // 需要使用`call`来告知this是core.maps
|
||||
}
|
||||
```
|
||||
|
||||
详见[call和apply的用法](https://www.jianshu.com/p/80ea0d1c04f8)。
|
||||
|
||||
==========================================================================================
|
||||
|
||||
[继续阅读下一章:API列表](api)
|
||||
|
||||
|
||||
@ -305,8 +305,8 @@ action
|
||||
| moveImage_s
|
||||
| showGif_0_s
|
||||
| showGif_1_s
|
||||
| setFg_0_s
|
||||
| setFg_1_s
|
||||
| setCurtain_0_s
|
||||
| setCurtain_1_s
|
||||
| screenFlash_s
|
||||
| setWeather_s
|
||||
| move_s
|
||||
@ -324,6 +324,7 @@ action
|
||||
| win_s
|
||||
| lose_s
|
||||
| if_s
|
||||
| if_1_s
|
||||
| switch_s
|
||||
| while_s
|
||||
| break_s
|
||||
@ -1278,35 +1279,35 @@ var code = '{"type": "moveImage", "code": '+Int_0+toloc+EvalString_0+',"time": '
|
||||
return code;
|
||||
*/;
|
||||
|
||||
setFg_0_s
|
||||
setCurtain_0_s
|
||||
: '更改画面色调' EvalString Colour '动画时间' Int? '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* setFg_0_s
|
||||
tooltip : setFg: 更改画面色调,动画时间可不填
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/event?id=setfg%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83
|
||||
/* setCurtain_0_s
|
||||
tooltip : setCurtain: 更改画面色调,动画时间可不填
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/event?id=setcurtain%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83
|
||||
default : ["255,255,255,1",'rgba(255,255,255,1)',500,false]
|
||||
colour : this.soundColor
|
||||
var colorRe = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/;
|
||||
if (!colorRe.test(EvalString_0))throw new Error('颜色格式错误,形如:0~255,0~255,0~255,0~1');
|
||||
Int_0 = Int_0!=='' ?(', "time": '+Int_0):'';
|
||||
var async = Bool_0?', "async": true':'';
|
||||
var code = '{"type": "setFg", "color": ['+EvalString_0+']'+Int_0 +async+'},\n';
|
||||
var code = '{"type": "setCurtain", "color": ['+EvalString_0+']'+Int_0 +async+'},\n';
|
||||
return code;
|
||||
*/;
|
||||
|
||||
setFg_1_s
|
||||
setCurtain_1_s
|
||||
: '恢复画面色调' '动画时间' Int? '不等待执行完毕' Bool Newline
|
||||
|
||||
|
||||
/* setFg_1_s
|
||||
tooltip : setFg: 恢复画面色调,动画时间可不填
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/event?id=setfg%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83
|
||||
/* setCurtain_1_s
|
||||
tooltip : setCurtain: 恢复画面色调,动画时间可不填
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/event?id=setcurtain%EF%BC%9A%E6%9B%B4%E6%94%B9%E7%94%BB%E9%9D%A2%E8%89%B2%E8%B0%83
|
||||
default : [500,false]
|
||||
colour : this.soundColor
|
||||
Int_0 = Int_0!=='' ?(', "time": '+Int_0):'';
|
||||
var async = Bool_0?', "async": true':'';
|
||||
var code = '{"type": "setFg"'+Int_0 +async+'},\n';
|
||||
var code = '{"type": "setCurtain"'+Int_0 +async+'},\n';
|
||||
return code;
|
||||
*/;
|
||||
|
||||
@ -1482,15 +1483,16 @@ return code;
|
||||
*/;
|
||||
|
||||
playSound_s
|
||||
: '播放音效' EvalString Newline
|
||||
: '播放音效' EvalString '停止之前音效' Bool? Newline
|
||||
|
||||
|
||||
/* playSound_s
|
||||
tooltip : playSound: 播放音效
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/event?id=playsound%EF%BC%9A%E6%92%AD%E6%94%BE%E9%9F%B3%E6%95%88
|
||||
default : ["item.mp3"]
|
||||
default : ["item.mp3",false]
|
||||
colour : this.soundColor
|
||||
var code = '{"type": "playSound", "name": "'+EvalString_0+'"},\n';
|
||||
Bool_0 = Bool_0 ? ', "stop": true' : '';
|
||||
var code = '{"type": "playSound", "name": "'+EvalString_0+'"'+Bool_0+'},\n';
|
||||
return code;
|
||||
*/;
|
||||
|
||||
@ -1587,6 +1589,20 @@ var code = ['{"type": "if", "condition": "',expression_0,'",\n',
|
||||
return code;
|
||||
*/;
|
||||
|
||||
if_1_s
|
||||
: '如果' ':' expression BGNL? Newline action+ BEND Newline
|
||||
|
||||
|
||||
/* if_1_s
|
||||
tooltip : if: 条件判断
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/event?id=if%EF%BC%9A%E6%9D%A1%E4%BB%B6%E5%88%A4%E6%96%AD
|
||||
colour : this.eventColor
|
||||
var code = ['{"type": "if", "condition": "',expression_0,'",\n',
|
||||
'"true": [\n',action_0,'],\n',
|
||||
'},\n'].join('');
|
||||
return code;
|
||||
*/;
|
||||
|
||||
switch_s
|
||||
: '多重分歧 条件判定' ':' expression BGNL? Newline switchCase+ BEND Newline
|
||||
|
||||
@ -1603,14 +1619,16 @@ return code;
|
||||
*/;
|
||||
|
||||
switchCase
|
||||
: '如果是' expression '的场合' BGNL? Newline action+
|
||||
: '如果是' expression '的场合' '不跳出' Bool BGNL? Newline action+
|
||||
|
||||
|
||||
/* switchCase
|
||||
tooltip : 选项的选择
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/event?id=switch%EF%BC%9A%E5%A4%9A%E9%87%8D%E6%9D%A1%E4%BB%B6%E5%88%86%E6%AD%A7
|
||||
default : ["", false]
|
||||
colour : this.subColor
|
||||
var code = '{"case": "'+expression_0+'", "action": [\n'+action_0+']},\n';
|
||||
Bool_0 = Bool_0?', "nobreak": true':'';
|
||||
var code = '{"case": "'+expression_0+'"'+Bool_0+', "action": [\n'+action_0+']},\n';
|
||||
return code;
|
||||
*/;
|
||||
|
||||
@ -1639,13 +1657,13 @@ return code;
|
||||
*/;
|
||||
|
||||
choicesContext
|
||||
: '子选项' EvalString '图标' IdString? '颜色' EvalString? Colour '不跳出' Bool BGNL? Newline action+
|
||||
: '子选项' EvalString '图标' IdString? '颜色' EvalString? Colour BGNL? Newline action+
|
||||
|
||||
|
||||
/* choicesContext
|
||||
tooltip : 选项的选择
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/event?id=choices%EF%BC%9A%E7%BB%99%E7%94%A8%E6%88%B7%E6%8F%90%E4%BE%9B%E9%80%89%E9%A1%B9
|
||||
default : ["提示文字:红钥匙","","",null,false]
|
||||
default : ["提示文字:红钥匙","",""]
|
||||
colour : this.subColor
|
||||
if (EvalString_1) {
|
||||
var colorRe = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/;
|
||||
@ -1655,19 +1673,19 @@ if (EvalString_1) {
|
||||
EvalString_1 = ', "color": "'+EvalString_1+'"';
|
||||
}
|
||||
IdString_0 = IdString_0?(', "icon": "'+IdString_0+'"'):'';
|
||||
var nobreak = Bool_0?', "nobreak": true':'';
|
||||
var code = '{"text": "'+EvalString_0+'"'+IdString_0+EvalString_1+', "action": [\n'+action_0+']'+nobreak+'},\n';
|
||||
var code = '{"text": "'+EvalString_0+'"'+IdString_0+EvalString_1+', "action": [\n'+action_0+']},\n';
|
||||
return code;
|
||||
*/;
|
||||
|
||||
confirm_s
|
||||
: '显示确认框' ':' EvalString BGNL? '确定' ':' BGNL? Newline action+ '取消' ':' BGNL? Newline action+ BEND Newline
|
||||
: '显示确认框' ':' EvalString BGNL? '确定的场合' ':' '(默认选中' Bool ')' BGNL? Newline action+ '取消的场合' ':' BGNL? Newline action+ BEND Newline
|
||||
|
||||
/* confirm_s
|
||||
tooltip : 弹出确认框
|
||||
helpUrl : https://h5mota.com/games/template/docs/#/
|
||||
default : ["确认要???吗?"]
|
||||
var code = ['{"type": "confirm", "text": "',EvalString_0,'",\n',
|
||||
default : ["确认要xxx吗?",false]
|
||||
Bool_0 = Bool_0?', "default": true':''
|
||||
var code = ['{"type": "confirm"'+Bool_0+', "text": "',EvalString_0,'",\n',
|
||||
'"yes": [\n',action_0,'],\n',
|
||||
'"no": [\n',action_1,']\n',
|
||||
'},\n'].join('');
|
||||
@ -2448,11 +2466,12 @@ ActionParser.prototype.parseAction = function() {
|
||||
}
|
||||
break;
|
||||
case "setFg": // 颜色渐变
|
||||
case "setCurtain":
|
||||
if(this.isset(data.color)){
|
||||
this.next = MotaActionBlocks['setFg_0_s'].xmlText([
|
||||
this.next = MotaActionBlocks['setCurtain_0_s'].xmlText([
|
||||
data.color,'rgba('+data.color+')',data.time||0,data.async||false,this.next]);
|
||||
} else {
|
||||
this.next = MotaActionBlocks['setFg_1_s'].xmlText([
|
||||
this.next = MotaActionBlocks['setCurtain_1_s'].xmlText([
|
||||
data.time||0,data.async||false,this.next]);
|
||||
}
|
||||
break;
|
||||
@ -2511,7 +2530,7 @@ ActionParser.prototype.parseAction = function() {
|
||||
break;
|
||||
case "playSound":
|
||||
this.next = MotaActionBlocks['playSound_s'].xmlText([
|
||||
data.name,this.next]);
|
||||
data.name,data.stop,this.next]);
|
||||
break;
|
||||
case "playBgm":
|
||||
this.next = MotaActionBlocks['playBgm_s'].xmlText([
|
||||
@ -2579,16 +2598,23 @@ ActionParser.prototype.parseAction = function() {
|
||||
data.text,this.next]);
|
||||
break;
|
||||
case "if": // 条件判断
|
||||
this.next = MotaActionBlocks['if_s'].xmlText([
|
||||
// MotaActionBlocks['evalString_e'].xmlText([data.condition]),
|
||||
this.tryToUseEvFlag_e('evalString_e', [data.condition]),
|
||||
this.insertActionList(data["true"]),
|
||||
this.insertActionList(data["false"]),
|
||||
this.next]);
|
||||
if (data["false"]) {
|
||||
this.next = MotaActionBlocks['if_s'].xmlText([
|
||||
this.tryToUseEvFlag_e('evalString_e', [data.condition]),
|
||||
this.insertActionList(data["true"]),
|
||||
this.insertActionList(data["false"]),
|
||||
this.next]);
|
||||
}
|
||||
else {
|
||||
this.next = MotaActionBlocks['if_1_s'].xmlText([
|
||||
this.tryToUseEvFlag_e('evalString_e', [data.condition]),
|
||||
this.insertActionList(data["true"]),
|
||||
this.next]);
|
||||
}
|
||||
break;
|
||||
case "confirm": // 显示确认框
|
||||
this.next = MotaActionBlocks['confirm_s'].xmlText([
|
||||
this.EvalString(data.text),
|
||||
this.EvalString(data.text), data["default"],
|
||||
this.insertActionList(data["yes"]),
|
||||
this.insertActionList(data["no"]),
|
||||
this.next]);
|
||||
@ -2597,7 +2623,7 @@ ActionParser.prototype.parseAction = function() {
|
||||
var case_caseList = null;
|
||||
for(var ii=data.caseList.length-1,caseNow;caseNow=data.caseList[ii];ii--) {
|
||||
case_caseList=MotaActionBlocks['switchCase'].xmlText([
|
||||
this.isset(caseNow.case)?MotaActionBlocks['evalString_e'].xmlText([caseNow.case]):"值",this.insertActionList(caseNow.action),case_caseList]);
|
||||
this.isset(caseNow.case)?MotaActionBlocks['evalString_e'].xmlText([caseNow.case]):"值",caseNow.nobreak,this.insertActionList(caseNow.action),case_caseList]);
|
||||
}
|
||||
this.next = MotaActionBlocks['switch_s'].xmlText([
|
||||
// MotaActionBlocks['evalString_e'].xmlText([data.condition]),
|
||||
@ -2608,7 +2634,7 @@ ActionParser.prototype.parseAction = function() {
|
||||
var text_choices = null;
|
||||
for(var ii=data.choices.length-1,choice;choice=data.choices[ii];ii--) {
|
||||
text_choices=MotaActionBlocks['choicesContext'].xmlText([
|
||||
choice.text,choice.icon,choice.color,'rgba('+choice.color+')',choice.nobreak,this.insertActionList(choice.action),text_choices]);
|
||||
choice.text,choice.icon,choice.color,'rgba('+choice.color+')',this.insertActionList(choice.action),text_choices]);
|
||||
}
|
||||
this.next = MotaActionBlocks['choices_s'].xmlText([
|
||||
this.isset(data.text)?this.EvalString(data.text):null,'','',text_choices,this.next]);
|
||||
|
||||
@ -187,6 +187,11 @@ var data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc =
|
||||
"_type": "textarea",
|
||||
"_data": "初始生命值"
|
||||
},
|
||||
"manamax": {
|
||||
"_leaf": true,
|
||||
"_type": "textarea",
|
||||
"_data": "魔力上限;此项非负才会生效(null或小于0都不会生效)"
|
||||
},
|
||||
"mana": {
|
||||
"_leaf": true,
|
||||
"_type": "textarea",
|
||||
|
||||
@ -70,9 +70,9 @@ editor_blockly = function () {
|
||||
MotaActionBlocks['lose_s'].xmlText(),
|
||||
MotaActionBlocks['choices_s'].xmlText([
|
||||
'选择剑或者盾','流浪者','man',MotaActionBlocks['choicesContext'].xmlText([
|
||||
'剑','','',null,null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]),
|
||||
'剑','','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]),
|
||||
MotaActionBlocks['choicesContext'].xmlText([
|
||||
'盾','','',null,null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]),
|
||||
'盾','','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]),
|
||||
])
|
||||
])
|
||||
]),
|
||||
@ -111,9 +111,10 @@ editor_blockly = function () {
|
||||
],
|
||||
'事件控制':[
|
||||
MotaActionBlocks['if_s'].xmlText(),
|
||||
MotaActionBlocks['if_1_s'].xmlText(),
|
||||
MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别值", "caseList": [
|
||||
{"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]},
|
||||
{"action": []},
|
||||
{"action": [], "nobreak": true},
|
||||
{"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行default事件"}]},
|
||||
]}),
|
||||
MotaActionBlocks['while_s'].xmlText(),
|
||||
@ -142,8 +143,8 @@ editor_blockly = function () {
|
||||
MotaActionBlocks['animate_s'].xmlText(),
|
||||
MotaActionBlocks['showStatusBar_s'].xmlText(),
|
||||
MotaActionBlocks['hideStatusBar_s'].xmlText(),
|
||||
MotaActionBlocks['setFg_0_s'].xmlText(),
|
||||
MotaActionBlocks['setFg_1_s'].xmlText(),
|
||||
MotaActionBlocks['setCurtain_0_s'].xmlText(),
|
||||
MotaActionBlocks['setCurtain_1_s'].xmlText(),
|
||||
MotaActionBlocks['screenFlash_s'].xmlText(),
|
||||
MotaActionBlocks['setWeather_s'].xmlText(),
|
||||
MotaActionBlocks['playBgm_s'].xmlText(),
|
||||
|
||||
@ -105,7 +105,7 @@ actions.prototype.doRegisteredAction = function (action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
actions.prototype.checkReplaying = function () {
|
||||
actions.prototype._checkReplaying = function () {
|
||||
if (core.isReplaying() && core.status.event.id != 'save'
|
||||
&& (core.status.event.id || "").indexOf('book') != 0 && core.status.event.id != 'viewMaps')
|
||||
return true;
|
||||
@ -114,7 +114,7 @@ actions.prototype.checkReplaying = function () {
|
||||
|
||||
////// 检查是否在录像播放中,如果是,则停止交互
|
||||
actions.prototype._sys_checkReplay = function () {
|
||||
if (this.checkReplaying()) return true;
|
||||
if (this._checkReplaying()) return true;
|
||||
}
|
||||
|
||||
////// 按下某个键时 //////
|
||||
@ -145,7 +145,7 @@ actions.prototype.onkeyUp = function (e) {
|
||||
}
|
||||
|
||||
actions.prototype._sys_onkeyUp_replay = function (e) {
|
||||
if (this.checkReplaying()) {
|
||||
if (this._checkReplaying()) {
|
||||
if (e.keyCode == 27) // ESCAPE
|
||||
core.stopReplay();
|
||||
else if (e.keyCode == 90) // Z
|
||||
@ -286,7 +286,7 @@ actions.prototype.keyUp = function (keyCode, altKey, fromReplay) {
|
||||
}
|
||||
|
||||
actions.prototype._sys_keyUp_replay = function (keyCode, altKey, fromReplay) {
|
||||
if (!fromReplay && this.checkReplaying()) return true;
|
||||
if (!fromReplay && this._checkReplaying()) return true;
|
||||
}
|
||||
|
||||
actions.prototype._sys_keyUp_lockControl = function (keyCode, altKey) {
|
||||
@ -389,7 +389,7 @@ actions.prototype._sys_keyUp = function (keyCode, altKey) {
|
||||
if (core.status.automaticRoute && core.status.automaticRoute.autoHeroMove) {
|
||||
core.stopAutomaticRoute();
|
||||
}
|
||||
core.stopHero();
|
||||
core.status.heroStop = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -539,8 +539,8 @@ actions.prototype._sys_onup = function () {
|
||||
return true;
|
||||
}
|
||||
|
||||
////// 获得点击事件相对左上角的坐标(0到12之间) //////
|
||||
actions.prototype.getClickLoc = function (x, y) {
|
||||
////// 获得点击事件相对左上角的坐标 //////
|
||||
actions.prototype._getClickLoc = function (x, y) {
|
||||
|
||||
var statusBar = {'x': 0, 'y': 0};
|
||||
var size = 32;
|
||||
@ -663,7 +663,7 @@ actions.prototype.onmousewheel = function (direct) {
|
||||
actions.prototype._sys_onmousewheel = function (direct) {
|
||||
// 向下滚动是 -1 ,向上是 1
|
||||
|
||||
if (this.checkReplaying()) {
|
||||
if (this._checkReplaying()) {
|
||||
// 滚轮控制速度
|
||||
if (direct == 1) core.speedUpReplay();
|
||||
if (direct == -1) core.speedDownReplay();
|
||||
@ -891,6 +891,21 @@ actions.prototype._clickAction = function (x, y) {
|
||||
core.doAction();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (core.status.event.data.type == 'confirm') {
|
||||
if ((x == this.HSIZE-2 || x == this.HSIZE-1) && y == this.HSIZE+1) {
|
||||
core.status.route.push("choices:0");
|
||||
core.insertAction(core.status.event.ui.yes);
|
||||
core.doAction();
|
||||
}
|
||||
if ((x == this.HSIZE+2 || x == this.HSIZE+1) && y == this.HSIZE+1) {
|
||||
core.status.route.push("choices:1");
|
||||
core.insertAction(core.status.event.ui.no);
|
||||
core.doAction();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -898,6 +913,12 @@ actions.prototype._clickAction = function (x, y) {
|
||||
actions.prototype._keyDownAction = function (keycode) {
|
||||
if (core.status.event.data.type == 'choices') {
|
||||
this._keyDownChoices(keycode);
|
||||
return;
|
||||
}
|
||||
if (core.status.event.data.type == 'confirm' && (keycode == 37 || keycode == 39)) {
|
||||
core.status.event.selection = 1 - core.status.event.selection;
|
||||
core.drawConfirmBox(core.status.event.ui.text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -924,6 +945,15 @@ actions.prototype._keyUpAction = function (keycode) {
|
||||
if (choices.length > 0) {
|
||||
this._selectChoices(choices.length, keycode, this._clickAction);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (core.status.event.data.type == 'confirm'&& (keycode == 13 || keycode == 32 || keycode == 67)) {
|
||||
core.status.route.push("choices:" + core.status.event.selection);
|
||||
if (core.status.event.selection == 0)
|
||||
core.insertAction(core.status.event.ui.yes);
|
||||
else core.insertAction(core.status.event.ui.no);
|
||||
core.doAction();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,6 +988,7 @@ actions.prototype._clickBook = function (x, y) {
|
||||
var index = this.HSIZE * page + parseInt(y / 2);
|
||||
core.ui.drawBook(index);
|
||||
core.ui.drawBookDetail(index);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -1101,17 +1132,20 @@ actions.prototype._clickViewMaps = function (x, y) {
|
||||
index++;
|
||||
if (index < core.floorIds.length)
|
||||
core.ui.drawMaps(index);
|
||||
return;
|
||||
}
|
||||
else if (y >= this.HSIZE + 2 && (mh == this.SIZE || (x >= per && x <= this.LAST - per))) {
|
||||
if (y >= this.HSIZE + 2 && (mh == this.SIZE || (x >= per && x <= this.LAST - per))) {
|
||||
index--;
|
||||
while (index >= 0 && index != now && core.status.maps[core.floorIds[index]].cannotViewMap)
|
||||
index--;
|
||||
if (index >= 0)
|
||||
core.ui.drawMaps(index);
|
||||
return;
|
||||
}
|
||||
else if (x >= per && x <= this.LAST - per && y >= this.HSIZE - 1 && y <= this.HSIZE + 1) {
|
||||
if (x >= per && x <= this.LAST - per && y >= this.HSIZE - 1 && y <= this.HSIZE + 1) {
|
||||
core.clearMap('data');
|
||||
core.ui.closePanel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1217,7 +1251,9 @@ actions.prototype._clickQuickShop = function (x, y) {
|
||||
// 离开
|
||||
else if (y == topIndex + keys.length)
|
||||
core.ui.closePanel();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
////// 快捷商店界面时,放开某个键的操作 //////
|
||||
@ -1255,7 +1291,7 @@ actions.prototype._clickToolbox = function (x, y) {
|
||||
core.ui.drawToolbox(core.status.event.selection);
|
||||
}
|
||||
if (y == this.LAST && constantsPage > 1) {
|
||||
core.status.event.data.toolsPage--;
|
||||
core.status.event.data.constantsPage--;
|
||||
core.ui.drawToolbox(core.status.event.selection);
|
||||
}
|
||||
}
|
||||
@ -1904,11 +1940,11 @@ actions.prototype._clickSettings = function (x, y) {
|
||||
core.ui.drawKeyBoard();
|
||||
break;
|
||||
case 2:
|
||||
core.clearSelector();
|
||||
core.clearUI();
|
||||
core.ui.drawMaps();
|
||||
break;
|
||||
case 3:
|
||||
core.clearSelector();
|
||||
core.clearUI();
|
||||
core.ui.drawPaint();
|
||||
break;
|
||||
case 4:
|
||||
@ -1920,7 +1956,7 @@ actions.prototype._clickSettings = function (x, y) {
|
||||
core.ui.drawGameInfo();
|
||||
break;
|
||||
case 6:
|
||||
return core.confirmRestart(true);
|
||||
return core.confirmRestart();
|
||||
case 7:
|
||||
core.ui.closePanel();
|
||||
break;
|
||||
@ -2065,7 +2101,7 @@ actions.prototype._clickLocalSaveSelect = function (x, y) {
|
||||
var selection = y - topIndex;
|
||||
core.status.event.selection = selection;
|
||||
if (selection < 2) {
|
||||
core.getAllSaves(selection == 0 ? null : core.saves.saveIndex, function (saves) {
|
||||
var callback = function (saves) {
|
||||
if (saves) {
|
||||
var content = {
|
||||
"name": core.firstData.name,
|
||||
@ -2074,7 +2110,9 @@ actions.prototype._clickLocalSaveSelect = function (x, y) {
|
||||
}
|
||||
core.download(core.firstData.name + "_" + core.formatDate2(new Date()) + ".h5save", JSON.stringify(content));
|
||||
}
|
||||
})
|
||||
};
|
||||
if (selection == 0) core.getAllSaves(callback);
|
||||
else core.getSave(core.saves.saveIndex, callback);
|
||||
}
|
||||
|
||||
core.status.event.selection = 2;
|
||||
@ -2209,7 +2247,7 @@ actions.prototype._clickReplay_fromBeginning = function () {
|
||||
actions.prototype._clickReplay_fromLoad = function () {
|
||||
core.status.event.id = 'replayLoad';
|
||||
core.status.event.selection = null;
|
||||
core.ui.clearSelector();
|
||||
core.clearUI();
|
||||
var saveIndex = core.saves.saveIndex;
|
||||
var page = parseInt((saveIndex - 1) / 5), offset = saveIndex - 5 * page;
|
||||
core.ui.drawSLPanel(10 * page + offset);
|
||||
@ -2448,7 +2486,7 @@ actions.prototype._onupPaint = function () {
|
||||
core.status.event.data.x = null;
|
||||
core.status.event.data.y = null;
|
||||
// 保存
|
||||
core.paint[core.status.floorId] = lzw_encode(core.utils.encodeCanvas(core.dymCanvas.paint).join(","));
|
||||
core.paint[core.status.floorId] = lzw_encode(core.utils._encodeCanvas(core.dymCanvas.paint).join(","));
|
||||
}
|
||||
|
||||
actions.prototype.setPaintMode = function (mode) {
|
||||
@ -2496,7 +2534,7 @@ actions.prototype.loadPaint = function () {
|
||||
core.clearMap('paint');
|
||||
var value = core.paint[core.status.floorId];
|
||||
if (value) value = lzw_decode(value).split(",");
|
||||
core.utils.decodeCanvas(value, 32 * core.bigmap.width, 32 * core.bigmap.height);
|
||||
core.utils._decodeCanvas(value, 32 * core.bigmap.width, 32 * core.bigmap.height);
|
||||
core.drawImage('paint', core.bigmap.tempCanvas.canvas, 0, 0);
|
||||
|
||||
core.drawTip("读取绘图文件成功");
|
||||
|
||||
@ -308,7 +308,7 @@ control.prototype.showStartAnimate = function (noAnimate, callback) {
|
||||
this._showStartAnimate_resetDom();
|
||||
if (core.flags.startUsingCanvas || noAnimate)
|
||||
return this._showStartAnimate_finished(core.flags.startUsingCanvas, callback);
|
||||
core.hide(core.dom.startTop, 20, function () {
|
||||
core.hideWithAnimate(core.dom.startTop, 20, function () {
|
||||
core.control._showStartAnimate_finished(false, callback);
|
||||
});
|
||||
}
|
||||
@ -324,8 +324,8 @@ control.prototype._showStartAnimate_resetDom = function () {
|
||||
core.status.played = false;
|
||||
core.clearStatus();
|
||||
core.clearMap('all');
|
||||
core.deleteAllCanvas();
|
||||
core.dom.musicBtn.style.display = 'block';
|
||||
core.setMusicBtn();
|
||||
// 重置音量
|
||||
core.events.setVolume(1, 0);
|
||||
core.updateStatusBar();
|
||||
@ -340,7 +340,7 @@ control.prototype._showStartAnimate_finished = function (start, callback) {
|
||||
|
||||
////// 隐藏游戏开始界面 //////
|
||||
control.prototype.hideStartAnimate = function (callback) {
|
||||
core.hide(core.dom.startPanel, 20, callback);
|
||||
core.hideWithAnimate(core.dom.startPanel, 20, callback);
|
||||
}
|
||||
|
||||
////// 游戏是否已经开始 //////
|
||||
@ -348,30 +348,6 @@ control.prototype.isPlaying = function() {
|
||||
return core.status.played;
|
||||
}
|
||||
|
||||
////// 重新开始游戏;此函数将回到标题页面 //////
|
||||
control.prototype.restart = function() {
|
||||
this.showStartAnimate();
|
||||
core.playBgm(main.startBgm);
|
||||
}
|
||||
|
||||
////// 询问是否需要重新开始 //////
|
||||
control.prototype.confirmRestart = function (fromSettings) {
|
||||
core.status.event.selection = 1;
|
||||
core.ui.drawConfirmBox("你确定要返回标题页面吗?", function () {
|
||||
core.ui.closePanel();
|
||||
core.restart();
|
||||
}, function () {
|
||||
if (fromSettings) {
|
||||
core.status.event.selection = 3;
|
||||
core.ui.drawSettings();
|
||||
}
|
||||
else {
|
||||
core.ui.closePanel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
////// 清除游戏状态和数据 //////
|
||||
control.prototype.clearStatus = function() {
|
||||
// 停止各个Timeout和Interval
|
||||
@ -424,7 +400,7 @@ control.prototype.stopAutomaticRoute = function () {
|
||||
core.status.automaticRoute.destX=null;
|
||||
core.status.automaticRoute.destY=null;
|
||||
core.status.automaticRoute.lastDirection = null;
|
||||
core.stopHero();
|
||||
core.status.heroStop = true;
|
||||
if (core.status.automaticRoute.moveStepBeforeStop.length==0)
|
||||
core.deleteCanvas('route');
|
||||
}
|
||||
@ -472,8 +448,10 @@ control.prototype.setAutomaticRoute = function (destX, destY, stepPostfix) {
|
||||
if (this._setAutomaticRoute_isTurning(destX, destY, stepPostfix)) return;
|
||||
if (this._setAutomaticRoute_clickMoveDirectly(destX, destY, stepPostfix)) return;
|
||||
// 找寻自动寻路路线
|
||||
var moveStep = core.automaticRoute(destX, destY).concat(stepPostfix);
|
||||
if (moveStep.length == 0) return core.deleteCanvas('route');
|
||||
var moveStep = core.automaticRoute(destX, destY);
|
||||
if (moveStep.length == 0 && (destX != core.status.hero.loc.x || destY != core.status.hero.loc.y || stepPostfix.length == 0))
|
||||
return;
|
||||
moveStep = moveStep.concat(stepPostfix);
|
||||
core.status.automaticRoute.destX=destX;
|
||||
core.status.automaticRoute.destY=destY;
|
||||
this._setAutomaticRoute_drawRoute(moveStep);
|
||||
@ -659,7 +637,7 @@ control.prototype._moveAction_moving = function (callback) {
|
||||
core.updateStatusBar();
|
||||
|
||||
// 检查该点是否是滑冰
|
||||
if (core.getBgFgNumber('bg') == 167) {
|
||||
if (core.getBgNumber() == 167) {
|
||||
core.insertAction("滑冰事件", null, null, null, true);
|
||||
}
|
||||
|
||||
@ -749,11 +727,6 @@ control.prototype.waitHeroToStop = function(callback) {
|
||||
}
|
||||
}
|
||||
|
||||
////// 停止勇士的移动状态 //////
|
||||
control.prototype.stopHero = function () {
|
||||
core.status.heroStop = true;
|
||||
}
|
||||
|
||||
////// 转向 //////
|
||||
control.prototype.turnHero = function(direction) {
|
||||
if (direction) {
|
||||
@ -1272,7 +1245,12 @@ control.prototype._doReplayAction = function (action) {
|
||||
control.prototype._replay_finished = function () {
|
||||
core.status.replay.replaying = false;
|
||||
core.status.event.selection = 0;
|
||||
core.ui.drawConfirmBox("录像播放完毕,你想退出播放吗?", function () {
|
||||
var str = "录像播放完毕,你想退出播放吗?";
|
||||
if (core.status.route.length != core.status.replay.totalList.length
|
||||
|| core.subarray(core.status.route, core.status.replay.totalList) == null) {
|
||||
str = "录像播放完毕,但记录不一致。\n请检查录像播放时的二次记录问题。\n你想退出播放吗?";
|
||||
}
|
||||
core.ui.drawConfirmBox(str, function () {
|
||||
core.ui.closePanel();
|
||||
core.stopReplay(true);
|
||||
}, function () {
|
||||
@ -1460,6 +1438,7 @@ control.prototype._replayAction_moveDirectly = function (action) {
|
||||
// 忽略连续的瞬移事件
|
||||
while (core.status.replay.toReplay.length>0 &&
|
||||
core.status.replay.toReplay[0].indexOf('move:')==0) {
|
||||
core.status.route.push(action);
|
||||
action = core.status.replay.toReplay.shift();
|
||||
}
|
||||
|
||||
@ -1615,13 +1594,15 @@ control.prototype._doSL_replayLoad_afterGet = function (id, data) {
|
||||
////// 同步存档到服务器 //////
|
||||
control.prototype.syncSave = function (type) {
|
||||
core.ui.drawWaiting("正在同步,请稍后...");
|
||||
core.getAllSaves(type=='all'?null:core.saves.saveIndex, function (saves) {
|
||||
if (!saves) return core.drawText("没有要同步的存档");
|
||||
var callback = function (saves) {
|
||||
core.control._syncSave_http(type, saves);
|
||||
})
|
||||
}
|
||||
if (type == 'all') core.getAllSaves(callback);
|
||||
else core.getSave(core.saves.saveIndex, callback);
|
||||
}
|
||||
|
||||
control.prototype._syncSave_http = function (type, saves) {
|
||||
if (!saves) return core.drawText("没有要同步的存档");
|
||||
var formData = new FormData();
|
||||
formData.append('type', 'save');
|
||||
formData.append('name', core.firstData.name);
|
||||
@ -1635,7 +1616,7 @@ control.prototype._syncSave_http = function (type, saves) {
|
||||
else {
|
||||
core.drawText((type=='all'?"所有存档":"存档"+core.saves.saveIndex)+"同步成功!\n\n您的存档编号: "
|
||||
+response.code+"\n您的存档密码: "+response.msg
|
||||
+"\n\n请牢记以上两个信息(如截图等),在从服务器\n同步存档时使用。")
|
||||
+"\n\n请牢记以上两个信息(如截图等),在从服务器\n同步存档时使用。\n\r[yellow]另外请注意,存档同步只会保存一个月的时间。\r")
|
||||
}
|
||||
}, function (e) {
|
||||
core.drawText("出错啦!\n无法同步存档到服务器。\n错误原因:"+e);
|
||||
@ -1746,8 +1727,7 @@ control.prototype.getSaves = function (ids, callback) {
|
||||
}
|
||||
}
|
||||
|
||||
control.prototype.getAllSaves = function (id, callback) {
|
||||
if (id != null) return this.getSave(id, callback);
|
||||
control.prototype.getAllSaves = function (callback) {
|
||||
var ids = Object.keys(core.saves.ids).filter(function(x){return x!=0;})
|
||||
.sort(function(a,b) {return a-b;}), saves = [];
|
||||
this.getSaves(ids, function (data) {
|
||||
@ -1790,7 +1770,7 @@ control.prototype.hasSave = function (index) {
|
||||
return core.saves.ids[index] || false;
|
||||
}
|
||||
|
||||
////// 删除一个或多个存档
|
||||
////// 删除某个存档
|
||||
control.prototype.removeSave = function (index, callback) {
|
||||
if (index == 0 || index == "autoSave") {
|
||||
index = "autoSave";
|
||||
@ -1825,8 +1805,6 @@ control.prototype._updateFavoriteSaves = function () {
|
||||
core.setLocalStorage("favoriteName", core.saves.favoriteName);
|
||||
}
|
||||
|
||||
////// 加载某个存档
|
||||
|
||||
// ------ 属性,状态,位置,buff,变量,锁定控制等 ------ //
|
||||
|
||||
////// 设置勇士属性 //////
|
||||
@ -2017,7 +1995,7 @@ control.prototype._setWeather_createNodes = function (type, level) {
|
||||
}
|
||||
|
||||
////// 更改画面色调 //////
|
||||
control.prototype.setFg = function(color, time, callback) {
|
||||
control.prototype.setCurtain = function(color, time, callback) {
|
||||
if (time == null) time=750;
|
||||
if (time<=0) time=0;
|
||||
if (!core.status.curtainColor)
|
||||
@ -2035,10 +2013,10 @@ control.prototype.setFg = function(color, time, callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._setFg_animate(core.status.curtainColor, color, time, callback);
|
||||
this._setCurtain_animate(core.status.curtainColor, color, time, callback);
|
||||
}
|
||||
|
||||
control.prototype._setFg_animate = function (nowColor, color, time, callback) {
|
||||
control.prototype._setCurtain_animate = function (nowColor, color, time, callback) {
|
||||
var per_time = 10, step = parseInt(time / per_time);
|
||||
var animate = setInterval(function() {
|
||||
nowColor = [
|
||||
@ -2066,8 +2044,8 @@ control.prototype.screenFlash = function (color, time, times, callback) {
|
||||
times = times || 1;
|
||||
time = time / 3;
|
||||
var nowColor = core.clone(core.status.curtainColor);
|
||||
core.setFg(color, time, function() {
|
||||
core.setFg(nowColor, time * 2, function() {
|
||||
core.setCurtain(color, time, function() {
|
||||
core.setCurtain(nowColor, time * 2, function() {
|
||||
if (times > 1)
|
||||
core.screenFlash(color, time * 3, times - 1, callback);
|
||||
else {
|
||||
@ -2203,8 +2181,8 @@ control.prototype.stopSound = function () {
|
||||
for (var i in core.musicStatus.playingSounds) {
|
||||
var source = core.musicStatus.playingSounds[i];
|
||||
try {
|
||||
if (source[i].stop) source[i].stop();
|
||||
else if (source[i].noteOff) source[i].noteOff();
|
||||
if (source.stop) source.stop();
|
||||
else if (source.noteOff) source.noteOff();
|
||||
}
|
||||
catch (e) {
|
||||
main.log(e);
|
||||
@ -2353,10 +2331,11 @@ control.prototype.updateGlobalAttribute = function (name) {
|
||||
core.dom.statusBar.style.borderTop = border;
|
||||
core.dom.statusBar.style.borderLeft = border;
|
||||
core.dom.statusBar.style.borderRight = core.domStyle.isVertical?border:'';
|
||||
core.dom.statusBar.style.borderBottom = core.domStyle.isVertical?'':border;
|
||||
core.dom.gameDraw.style.border = border;
|
||||
core.dom.toolBar.style.borderBottom = border;
|
||||
core.dom.toolBar.style.borderLeft = border;
|
||||
core.dom.toolBar.style.borderRight = core.domStyle.isVertical?border:'';
|
||||
core.dom.toolBar.style.borderBottom = core.domStyle.isVertical?border:'';
|
||||
break;
|
||||
}
|
||||
case 'statusBarColor':
|
||||
@ -2378,7 +2357,7 @@ control.prototype.updateGlobalAttribute = function (name) {
|
||||
}
|
||||
}
|
||||
|
||||
////// 改变工具栏为按钮1-7 //////
|
||||
////// 改变工具栏为按钮1-8 //////
|
||||
control.prototype.setToolbarButton = function (useButton) {
|
||||
if (!core.domStyle.showStatusBar) {
|
||||
// 隐藏状态栏时检查竖屏
|
||||
@ -2544,7 +2523,7 @@ control.prototype._resize_gameGroup = function (obj) {
|
||||
floorMsgGroup.style.color = obj.globalAttribute.floorChangingTextColor;
|
||||
// musicBtn
|
||||
if (core.domStyle.isVertical || core.domStyle.scale < 1) {
|
||||
core.dom.musicBtn.style.right = core.dom.musicBtn.style.height = "3px";
|
||||
core.dom.musicBtn.style.right = core.dom.musicBtn.style.bottom = "3px";
|
||||
}
|
||||
else {
|
||||
core.dom.musicBtn.style.right = (obj.clientWidth - totalWidth) / 2 + "px";
|
||||
@ -2588,7 +2567,7 @@ control.prototype._resize_statusBar = function (obj) {
|
||||
}
|
||||
else {
|
||||
statusBar.style.width = obj.BAR_WIDTH * core.domStyle.scale + "px";
|
||||
statusBar.style.height = obj.outerSize - 3 + "px";
|
||||
statusBar.style.height = obj.outerSize + "px";
|
||||
statusBar.style.background = obj.globalAttribute.statusLeftBackground;
|
||||
// --- 计算文字大小
|
||||
statusBar.style.fontSize = 16 * Math.min(1, (core.__HALF_SIZE__ + 3) / obj.count) * core.domStyle.scale + "px";
|
||||
@ -2596,6 +2575,7 @@ control.prototype._resize_statusBar = function (obj) {
|
||||
statusBar.style.display = 'block';
|
||||
statusBar.style.borderTop = statusBar.style.borderLeft = obj.border;
|
||||
statusBar.style.borderRight = core.domStyle.isVertical ? obj.border : '';
|
||||
statusBar.style.borderBottom = core.domStyle.isVertical ? '' : obj.border;
|
||||
// 自绘状态栏
|
||||
if (core.domStyle.isVertical) {
|
||||
core.dom.statusCanvas.style.width = obj.outerSize - 6 + "px";
|
||||
@ -2651,8 +2631,8 @@ control.prototype._resize_toolBar = function (obj) {
|
||||
toolBar.style.background = 'transparent';
|
||||
}
|
||||
toolBar.style.display = 'block';
|
||||
toolBar.style.borderLeft = toolBar.style.borderBottom = obj.border;
|
||||
toolBar.style.borderRight = core.domStyle.isVertical ? obj.border : '';
|
||||
toolBar.style.borderLeft = obj.border;
|
||||
toolBar.style.borderRight = toolBar.style.borderBottom = core.domStyle.isVertical ? obj.border : '';
|
||||
toolBar.style.fontSize = 16 * core.domStyle.scale + "px";
|
||||
}
|
||||
|
||||
|
||||
11
libs/core.js
11
libs/core.js
@ -16,8 +16,7 @@ function core() {
|
||||
'ground': null,
|
||||
'items': {},
|
||||
'enemys': {},
|
||||
'icons': {},
|
||||
'events': {}
|
||||
'icons': {}
|
||||
}
|
||||
this.timeout = {
|
||||
'tipTimeout': null,
|
||||
@ -84,8 +83,8 @@ function core() {
|
||||
this.domStyle = {
|
||||
scale: 1.0,
|
||||
isVertical: false,
|
||||
toolbarBtn: false,
|
||||
showStatusBar: true,
|
||||
toolbarBtn: false,
|
||||
}
|
||||
this.bigmap = {
|
||||
canvas: ["bg", "event", "event2", "fg", "damage"],
|
||||
@ -220,6 +219,7 @@ core.prototype.init = function (coreData, callback) {
|
||||
this._init_flags();
|
||||
this._init_platform();
|
||||
this._init_others();
|
||||
this._initPlugins();
|
||||
|
||||
core.loader._load(function () {
|
||||
core._afterLoadResources(callback);
|
||||
@ -342,9 +342,10 @@ core.prototype._init_others = function () {
|
||||
|
||||
core.prototype._afterLoadResources = function (callback) {
|
||||
// 初始化地图
|
||||
core.initStatus.maps = core.maps.initMaps(core.floorIds);
|
||||
core.initStatus.maps = core.maps._initMaps();
|
||||
core.control._setRequestAnimationFrame();
|
||||
core._initPlugins();
|
||||
if (core.plugin._afterLoadResources)
|
||||
core.plugin._afterLoadResources();
|
||||
core.showStartAnimate();
|
||||
if (callback) callback();
|
||||
}
|
||||
|
||||
@ -107,13 +107,13 @@ enemys.prototype.canBattle = function (enemy, x, y, floorId) {
|
||||
////// 获得某个怪物的伤害 //////
|
||||
enemys.prototype.getDamage = function (enemy, x, y, floorId) {
|
||||
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
|
||||
var damage = this.calDamage(enemy, null, x, y, floorId);
|
||||
var damage = this._calDamage(enemy, null, x, y, floorId);
|
||||
if (damage == null) return null;
|
||||
return damage + this.getExtraDamage(enemy);
|
||||
return damage + this.getExtraDamage(enemy, x, y, floorId);
|
||||
}
|
||||
|
||||
////// 获得某个怪物的额外伤害 //////
|
||||
enemys.prototype.getExtraDamage = function (enemy) {
|
||||
enemys.prototype.getExtraDamage = function (enemy, x, y, floorId) {
|
||||
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
|
||||
var extra_damage = 0;
|
||||
if (this.hasSpecial(enemy.special, 17)) { // 仇恨
|
||||
@ -265,8 +265,8 @@ enemys.prototype._nextCriticals_useTurn = function (enemy, info, number, x, y, f
|
||||
enemys.prototype.getDefDamage = function (enemy, k, x, y, floorId) {
|
||||
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
|
||||
k = k || 1;
|
||||
var nowDamage = this.calDamage(enemy, null, x, y, floorId);
|
||||
var nextDamage = this.calDamage(enemy, {"def": core.status.hero.def + k}, x, y, floorId);
|
||||
var nowDamage = this._calDamage(enemy, null, x, y, floorId);
|
||||
var nextDamage = this._calDamage(enemy, {"def": core.status.hero.def + k}, x, y, floorId);
|
||||
if (nowDamage == null || nextDamage == null) return "???";
|
||||
return nowDamage - nextDamage;
|
||||
}
|
||||
@ -284,7 +284,7 @@ enemys.prototype.getDamageInfo = function (enemy, hero, x, y, floorId) {
|
||||
}
|
||||
|
||||
////// 获得在某个勇士属性下怪物伤害 //////
|
||||
enemys.prototype.calDamage = function (enemy, hero, x, y, floorId) {
|
||||
enemys.prototype._calDamage = function (enemy, hero, x, y, floorId) {
|
||||
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
|
||||
|
||||
var info = this.getDamageInfo(enemy, hero, x, y, floorId);
|
||||
@ -357,4 +357,8 @@ enemys.prototype._getCurrentEnemys_sort = function (enemys) {
|
||||
}
|
||||
return a.damage - b.damage;
|
||||
});
|
||||
}
|
||||
|
||||
enemys.prototype.hasEnemyLeft = function (floorId) {
|
||||
return core.getCurrentEnemys(floorId).length > 0;
|
||||
}
|
||||
226
libs/events.js
226
libs/events.js
@ -52,9 +52,6 @@ events.prototype._startGame_start = function (hard, seed, route, callback) {
|
||||
}
|
||||
else core.utils.__init_seed();
|
||||
this.setInitData();
|
||||
|
||||
core.clearMap('all');
|
||||
core.deleteAllCanvas();
|
||||
core.clearStatusBar();
|
||||
|
||||
var todo = [];
|
||||
@ -183,7 +180,7 @@ events.prototype._gameOver_doUpload = function (username, ending, norank) {
|
||||
formData.append('money', core.status.hero.money);
|
||||
formData.append('experience', core.status.hero.experience);
|
||||
formData.append('steps', core.status.hero.steps);
|
||||
formData.append('norank', norank || 0);
|
||||
formData.append('norank', norank ? 1 : 0);
|
||||
formData.append('seed', core.getFlag('__seed__'));
|
||||
formData.append('totalTime', Math.floor(core.status.hero.statistics.totalTime / 1000));
|
||||
formData.append('route', core.encodeRoute(core.status.route));
|
||||
@ -234,6 +231,23 @@ events.prototype._gameOver_askRate = function (ending) {
|
||||
});
|
||||
}
|
||||
|
||||
////// 重新开始游戏;此函数将回到标题页面 //////
|
||||
events.prototype.restart = function() {
|
||||
core.showStartAnimate();
|
||||
core.playBgm(main.startBgm);
|
||||
}
|
||||
|
||||
////// 询问是否需要重新开始 //////
|
||||
events.prototype.confirmRestart = function () {
|
||||
core.status.event.selection = 1;
|
||||
core.ui.drawConfirmBox("你确定要返回标题页面吗?", function () {
|
||||
core.ui.closePanel();
|
||||
core.restart();
|
||||
}, function () {
|
||||
core.ui.closePanel();
|
||||
});
|
||||
}
|
||||
|
||||
// ------ 系统事件的处理 ------ //
|
||||
|
||||
////// 注册一个系统事件 //////
|
||||
@ -279,10 +293,7 @@ events.prototype._trigger = function (x, y) {
|
||||
if (trigger == 'changeFloor' && !noPass && this._trigger_ignoreChangeFloor(block))
|
||||
return;
|
||||
core.status.automaticRoute.moveDirectly = false;
|
||||
this.doSystemEvent(trigger, block, function () {
|
||||
if (trigger == 'openDoor' || trigger == 'changeFloor')
|
||||
core.replay();
|
||||
})
|
||||
this.doSystemEvent(trigger, block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,16 +352,20 @@ events.prototype.afterBattle = function (enemyId, x, y, callback) {
|
||||
}
|
||||
|
||||
events.prototype._sys_openDoor = function (data, callback) {
|
||||
this.openDoor(data.event.id, data.x, data.y, true, callback);
|
||||
this.openDoor(data.x, data.y, true, function () {
|
||||
core.replay();
|
||||
if (callback) callback();
|
||||
});
|
||||
}
|
||||
|
||||
////// 开门 //////
|
||||
events.prototype.openDoor = function (id, x, y, needKey, callback) {
|
||||
id = id || core.getBlockId(x, y);
|
||||
events.prototype.openDoor = function (x, y, needKey, callback) {
|
||||
var id = core.getBlockId(x, y);
|
||||
core.saveAndStopAutomaticRoute();
|
||||
if (!this._openDoor_check(id, x, y, needKey)) {
|
||||
var locked = core.status.lockControl;
|
||||
core.waitHeroToStop(function () {
|
||||
core.unLockControl();
|
||||
if (!locked) core.unLockControl();
|
||||
if (callback) callback();
|
||||
});
|
||||
return;
|
||||
@ -362,7 +377,7 @@ events.prototype.openDoor = function (id, x, y, needKey, callback) {
|
||||
events.prototype._openDoor_check = function (id, x, y, needKey) {
|
||||
// 是否存在门或暗墙
|
||||
if (!core.terrainExists(x, y, id) || !(id.endsWith("Door") || id.endsWith("Wall"))
|
||||
|| !core.material.icons.animates[id]) {
|
||||
|| core.material.icons.animates[id] == null) {
|
||||
core.clearContinueAutomaticRoute();
|
||||
return false;
|
||||
}
|
||||
@ -376,7 +391,7 @@ events.prototype._openDoor_check = function (id, x, y, needKey) {
|
||||
core.clearContinueAutomaticRoute();
|
||||
return false;
|
||||
}
|
||||
core.autosave(true);
|
||||
if (!core.status.event.id) core.autosave(true);
|
||||
core.removeItem(key);
|
||||
}
|
||||
return true;
|
||||
@ -386,6 +401,7 @@ events.prototype._openDoor_animate = function (id, x, y, callback) {
|
||||
var door = core.material.icons.animates[id];
|
||||
var speed = id.endsWith("Door") ? 30 : 70;
|
||||
|
||||
var locked = core.status.lockControl;
|
||||
core.lockControl();
|
||||
core.status.replay.animate = true;
|
||||
var state = 0;
|
||||
@ -394,7 +410,7 @@ events.prototype._openDoor_animate = function (id, x, y, callback) {
|
||||
if (state == 4) {
|
||||
clearInterval(animate);
|
||||
core.removeBlock(x, y);
|
||||
core.unLockControl();
|
||||
if (!locked) core.unLockControl();
|
||||
core.status.replay.animate = false;
|
||||
core.events.afterOpenDoor(id, x, y, callback);
|
||||
return;
|
||||
@ -414,29 +430,33 @@ events.prototype._sys_getItem = function (data, callback) {
|
||||
}
|
||||
|
||||
////// 获得某个物品 //////
|
||||
events.prototype.getItem = function (itemId, itemNum, itemX, itemY, callback) {
|
||||
itemNum = itemNum || 1;
|
||||
var itemCls = core.material.items[itemId].cls;
|
||||
core.items.getItemEffect(itemId, itemNum);
|
||||
core.removeBlock(itemX, itemY);
|
||||
var text = '获得 ' + core.material.items[itemId].name;
|
||||
if (itemNum > 1) text += "x" + itemNum;
|
||||
if (itemCls === 'items') text += core.items.getItemEffectTip(itemId);
|
||||
core.drawTip(text, core.material.icons.items[itemId]);
|
||||
events.prototype.getItem = function (id, num, x, y, callback) {
|
||||
num = num || 1;
|
||||
var itemCls = core.material.items[id].cls;
|
||||
core.items.getItemEffect(id, num);
|
||||
core.removeBlock(x, y);
|
||||
var text = '获得 ' + core.material.items[id].name;
|
||||
if (num > 1) text += "x" + num;
|
||||
if (itemCls === 'items') text += core.items.getItemEffectTip(id);
|
||||
core.drawTip(text, id);
|
||||
core.updateStatusBar();
|
||||
|
||||
this.eventdata.afterGetItem(itemId, itemX, itemY, callback);
|
||||
this.afterGetItem(id, x, y, callback);
|
||||
}
|
||||
|
||||
events.prototype.afterGetItem = function (id, x, y, callback) {
|
||||
this.eventdata.afterGetItem(id, x, y, callback);
|
||||
}
|
||||
|
||||
////// 获得面前的物品(轻按) //////
|
||||
events.prototype.getNextItem = function () {
|
||||
events.prototype.getNextItem = function (noRoute) {
|
||||
if (core.isMoving() || !core.canMoveHero() || !core.flags.enableGentleClick) return false;
|
||||
|
||||
var nextX = core.nextX(), nextY = core.nextY();
|
||||
var block = core.getBlock(nextX, nextY);
|
||||
if (block == null) return false;
|
||||
if (block.block.event.trigger == 'getItem') {
|
||||
core.status.route.push("getNext");
|
||||
if (!noRoute) core.status.route.push("getNext");
|
||||
this.getItem(block.block.event.id, 1, nextX, nextY);
|
||||
return true;
|
||||
}
|
||||
@ -449,7 +469,10 @@ events.prototype._sys_changeFloor = function (data, callback) {
|
||||
if (data.loc) heroLoc = {'x': data.loc[0], 'y': data.loc[1]};
|
||||
if (data.direction) heroLoc.direction = data.direction;
|
||||
if (core.status.event.id != 'action') core.status.event.id = null;
|
||||
core.changeFloor(data.floorId, data.stair, heroLoc, data.time, callback);
|
||||
core.changeFloor(data.floorId, data.stair, heroLoc, data.time, function () {
|
||||
core.replay();
|
||||
if (callback) callback();
|
||||
});
|
||||
}
|
||||
|
||||
////// 楼层切换 //////
|
||||
@ -461,6 +484,7 @@ events.prototype.changeFloor = function (floorId, stair, heroLoc, time, callback
|
||||
}
|
||||
info.fromLoad = fromLoad;
|
||||
floorId = info.floorId;
|
||||
info.locked = core.status.lockControl;
|
||||
|
||||
core.dom.floorNameLabel.innerHTML = core.status.maps[floorId].title;
|
||||
core.lockControl();
|
||||
@ -535,7 +559,7 @@ events.prototype._changeFloor_beforeChange = function (info, callback) {
|
||||
if (info.time == 0)
|
||||
core.events._changeFloor_changing(info, callback);
|
||||
else
|
||||
core.show(core.dom.floorMsgGroup, info.time / 2, function () {
|
||||
core.showWithAnimate(core.dom.floorMsgGroup, info.time / 2, function () {
|
||||
core.events._changeFloor_changing(info, callback);
|
||||
});
|
||||
}, 25)
|
||||
@ -547,13 +571,13 @@ events.prototype._changeFloor_changing = function (info, callback) {
|
||||
if (info.time == 0)
|
||||
this._changeFloor_afterChange(info, callback);
|
||||
else
|
||||
core.hide(core.dom.floorMsgGroup, info.time / 4, function () {
|
||||
core.hideWithAnimate(core.dom.floorMsgGroup, info.time / 4, function () {
|
||||
core.events._changeFloor_afterChange(info, callback);
|
||||
});
|
||||
}
|
||||
|
||||
events.prototype._changeFloor_afterChange = function (info, callback) {
|
||||
core.unLockControl();
|
||||
if (!info.locked) core.unLockControl();
|
||||
core.status.replay.animate = false;
|
||||
core.events.afterChangeFloor(info.floorId, info.fromLoad);
|
||||
|
||||
@ -661,11 +685,6 @@ events.prototype._sys_changeLight = function (data, callback) {
|
||||
events.prototype.changeLight = function (id, x, y) {
|
||||
if (id != null && id != 'light') return;
|
||||
core.setBlock(core.getNumberById('darkLight'), x, y);
|
||||
this.afterChangeLight(x, y);
|
||||
}
|
||||
|
||||
////// 改变亮灯之后,可以触发的事件 //////
|
||||
events.prototype.afterChangeLight = function (x, y) {
|
||||
return this.eventdata.afterChangeLight(x, y);
|
||||
}
|
||||
|
||||
@ -724,8 +743,19 @@ events.prototype.doEvent = function (data, x, y, prefix) {
|
||||
core.doAction();
|
||||
}
|
||||
|
||||
events.prototype.setEvents = function (list, x, y, callback) {
|
||||
var data = core.status.event.data || {};
|
||||
if (list)
|
||||
data.list = [{todo: core.clone(list), total: core.clone(list), condition: "false"}];
|
||||
if (x != null) data.x = x;
|
||||
if (y != null) data.y = y;
|
||||
if (callback) data.callback = callback;
|
||||
core.status.event.id = 'action';
|
||||
core.status.event.data = data;
|
||||
}
|
||||
|
||||
////// 开始执行一系列自定义事件 //////
|
||||
events.prototype.doEvents = function (list, x, y, callback) {
|
||||
events.prototype.startEvents = function (list, x, y, callback) {
|
||||
if (!list) return;
|
||||
if (!(list instanceof Array)) {
|
||||
list = [list];
|
||||
@ -738,24 +768,10 @@ events.prototype.doEvents = function (list, x, y, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
events.prototype.setEvents = function (list, x, y, callback) {
|
||||
var data = core.status.event.data || {};
|
||||
if (list)
|
||||
data.list = [{todo: core.clone(list), total: core.clone(list), condition: "false"}];
|
||||
if (x != null) data.x = x;
|
||||
if (y != null) data.y = y;
|
||||
if (callback) data.callback = callback;
|
||||
core.status.event.id = 'action';
|
||||
core.status.event.data = data;
|
||||
}
|
||||
|
||||
////// 执行当前自定义事件列表中的下一个事件 //////
|
||||
events.prototype.doAction = function () {
|
||||
// 清空boxAnimate和UI层
|
||||
core.status.boxAnimateObjs = [];
|
||||
clearInterval(core.status.event.interval);
|
||||
core.status.event.interval = null;
|
||||
core.clearSelector();
|
||||
core.clearUI();
|
||||
// 判定是否执行完毕
|
||||
if (this._doAction_finishEvents()) return;
|
||||
// 当前点坐标和前缀
|
||||
@ -799,7 +815,7 @@ events.prototype._popEvents = function (current, prefix) {
|
||||
return false;
|
||||
}
|
||||
|
||||
////// 往当前事件列表之前添加一个或多个事件 //////
|
||||
////// 往当前事件列表之前或之后添加一个或多个事件 //////
|
||||
events.prototype.insertAction = function (action, x, y, callback, addToLast) {
|
||||
if (core.hasFlag("__statistics__")) return;
|
||||
if (core.status.gameOver) return;
|
||||
@ -810,7 +826,7 @@ events.prototype.insertAction = function (action, x, y, callback, addToLast) {
|
||||
if (!action) return;
|
||||
|
||||
if (core.status.event.id != 'action') {
|
||||
this.doEvents(action, x, y, callback);
|
||||
this.startEvents(action, x, y, callback);
|
||||
}
|
||||
else {
|
||||
if (addToLast)
|
||||
@ -1022,10 +1038,7 @@ events.prototype._action_jumpHero = function (data, x, y, prefix) {
|
||||
events.prototype._action_changeFloor = function (data, x, y, prefix) {
|
||||
var loc = this.__action_getHeroLoc(data.loc, prefix);
|
||||
var heroLoc = {x: loc[0], y: loc[1], direction: data.direction};
|
||||
core.changeFloor(data.floorId || core.status.floorId, null, heroLoc, data.time, function () {
|
||||
core.lockControl();
|
||||
core.doAction();
|
||||
});
|
||||
core.changeFloor(data.floorId || core.status.floorId, null, heroLoc, data.time, core.doAction);
|
||||
}
|
||||
|
||||
events.prototype._action_changePos = function (data, x, y, prefix) {
|
||||
@ -1068,13 +1081,17 @@ events.prototype._action_moveImage = function (data, x, y, prefix) {
|
||||
}
|
||||
|
||||
events.prototype._action_setFg = function (data, x, y, prefix) {
|
||||
return this._action_setCurtain(data, x, y, prefix);
|
||||
}
|
||||
|
||||
events.prototype._action_setCurtain = function (data, x, y, prefix) {
|
||||
if (data.async) {
|
||||
core.setFg(data.color, data.time);
|
||||
core.setCurtain(data.color, data.time);
|
||||
core.setFlag('__color__', data.color || null);
|
||||
core.doAction();
|
||||
}
|
||||
else {
|
||||
core.setFg(data.color, data.time, function () {
|
||||
core.setCurtain(data.color, data.time, function () {
|
||||
core.setFlag('__color__', data.color || null);
|
||||
core.doAction();
|
||||
});
|
||||
@ -1097,10 +1114,7 @@ events.prototype._action_openDoor = function (data, x, y, prefix) {
|
||||
var loc = this.__action_getLoc(data.loc, x, y, prefix);
|
||||
var floorId = data.floorId || core.status.floorId;
|
||||
if (floorId == core.status.floorId) {
|
||||
core.openDoor(null, loc[0], loc[1], data.needKey, function () {
|
||||
core.lockControl();
|
||||
core.doAction();
|
||||
});
|
||||
core.openDoor(loc[0], loc[1], data.needKey, core.doAction);
|
||||
}
|
||||
else {
|
||||
core.removeBlock(loc[0], loc[1], floorId);
|
||||
@ -1148,14 +1162,10 @@ events.prototype._action_trigger = function (data, x, y, prefix) {
|
||||
if (block != null && block.block.event.trigger) {
|
||||
block = block.block;
|
||||
this.setEvents([], block.x, block.y);
|
||||
var _callback = function () {
|
||||
core.lockControl();
|
||||
core.doAction();
|
||||
}
|
||||
if (block.event.trigger == 'action')
|
||||
this.setEvents(block.event.data);
|
||||
else {
|
||||
core.doSystemEvent(block.event.trigger, block, _callback);
|
||||
core.doSystemEvent(block.event.trigger, block, core.doAction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1213,6 +1223,7 @@ events.prototype._action_freeBgm = function (data, x, y, prefix) {
|
||||
}
|
||||
|
||||
events.prototype._action_playSound = function (data, x, y, prefix) {
|
||||
if (data.stop) core.stopSound();
|
||||
core.playSound(data.name);
|
||||
core.doAction();
|
||||
}
|
||||
@ -1318,13 +1329,16 @@ events.prototype._action_if = function (data, x, y, prefix) {
|
||||
|
||||
events.prototype._action_switch = function (data, x, y, prefix) {
|
||||
var key = core.calValue(data.condition, prefix)
|
||||
var list = [];
|
||||
for (var i = 0; i < data.caseList.length; i++) {
|
||||
var condition = data.caseList[i]["case"];
|
||||
if (condition == "default" || core.calValue(condition, prefix) == key) {
|
||||
this.insertAction(data.caseList[i].action);
|
||||
break;
|
||||
core.push(list, data.caseList[i].action);
|
||||
if (!data.caseList[i].nobreak)
|
||||
break;
|
||||
}
|
||||
}
|
||||
core.insertAction(list);
|
||||
core.doAction();
|
||||
}
|
||||
|
||||
@ -1352,6 +1366,35 @@ events.prototype._action_choices = function (data, x, y, prefix) {
|
||||
core.ui.drawChoices(data.text, data.choices);
|
||||
}
|
||||
|
||||
events.prototype._action_confirm = function (data, x, y, prefix) {
|
||||
core.status.event.ui = {"text": data.text, "yes": data.yes, "no": data.no};
|
||||
if (core.isReplaying()) {
|
||||
var action = core.status.replay.toReplay.shift(), index;
|
||||
// --- 忽略可能的turn事件
|
||||
if (action == 'turn') action = core.status.replay.toReplay.shift();
|
||||
if (action.indexOf("choices:") == 0 && ((index = parseInt(action.substring(8))) >= 0) && index < 2) {
|
||||
core.status.event.selection = index;
|
||||
setTimeout(function () {
|
||||
core.status.route.push("choices:" + index);
|
||||
if (index == 0) core.insertAction(data.yes);
|
||||
else core.insertAction(data.no);
|
||||
core.doAction();
|
||||
}, 750 / Math.max(1, core.status.replay.speed))
|
||||
}
|
||||
else {
|
||||
main.log("录像文件出错!当前需要一个 choices: 项,实际为 " + action);
|
||||
core.stopReplay();
|
||||
core.insertAction(["录像文件出错,请在控制台查看报错信息。", {"type": "exit"}]);
|
||||
core.doAction();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
core.status.event.selection = data["default"] ? 0 : 1;
|
||||
}
|
||||
core.ui.drawConfirmBox(data.text);
|
||||
}
|
||||
|
||||
events.prototype._action_while = function (data, x, y, prefix) {
|
||||
if (core.calValue(data.condition, prefix)) {
|
||||
core.unshift(core.status.event.data.list,
|
||||
@ -1641,7 +1684,6 @@ events.prototype.load = function (fromUserAction) {
|
||||
core.dom.startPanel.style.display = 'none';
|
||||
core.clearStatus();
|
||||
core.clearMap('all');
|
||||
core.deleteAllCanvas();
|
||||
core.status.event = {'id': 'load', 'data': null};
|
||||
core.status.lockControl = true;
|
||||
core.ui.drawSLPanel(10*page+offset);
|
||||
@ -1698,24 +1740,6 @@ events.prototype.unfollow = function (name) {
|
||||
core.drawHero();
|
||||
}
|
||||
|
||||
////// 绘制或取消一张gif图片 //////
|
||||
events.prototype.showGif = function (name, x, y) {
|
||||
var image = core.material.images.images[name];
|
||||
if (image) {
|
||||
var gif = new Image();
|
||||
gif.src = image.src;
|
||||
gif.style.position = 'absolute';
|
||||
gif.style.left = x * core.domStyle.scale + "px";
|
||||
gif.style.top = y * core.domStyle.scale + "px";
|
||||
gif.style.width = image.width * core.domStyle.scale + "px";
|
||||
gif.style.height = image.height * core.domStyle.scale + "px";
|
||||
core.dom.gif2.appendChild(gif);
|
||||
}
|
||||
else {
|
||||
core.dom.gif2.innerHTML = "";
|
||||
}
|
||||
}
|
||||
|
||||
////// 数值操作 //////
|
||||
events.prototype.setValue = function (name, value, prefix, add) {
|
||||
var value = core.calValue(value, prefix);
|
||||
@ -1919,6 +1943,24 @@ events.prototype._moveImage_moving = function (name, moveInfo, callback) {
|
||||
core.animateFrame.asyncId[animate] = true;
|
||||
}
|
||||
|
||||
////// 绘制或取消一张gif图片 //////
|
||||
events.prototype.showGif = function (name, x, y) {
|
||||
var image = core.material.images.images[name];
|
||||
if (image) {
|
||||
var gif = new Image();
|
||||
gif.src = image.src;
|
||||
gif.style.position = 'absolute';
|
||||
gif.style.left = x * core.domStyle.scale + "px";
|
||||
gif.style.top = y * core.domStyle.scale + "px";
|
||||
gif.style.width = image.width * core.domStyle.scale + "px";
|
||||
gif.style.height = image.height * core.domStyle.scale + "px";
|
||||
core.dom.gif2.appendChild(gif);
|
||||
}
|
||||
else {
|
||||
core.dom.gif2.innerHTML = "";
|
||||
}
|
||||
}
|
||||
|
||||
////// 淡入淡出音乐 //////
|
||||
events.prototype.setVolume = function (value, time, callback) {
|
||||
var set = function (value) {
|
||||
@ -2040,7 +2082,7 @@ events.prototype.jumpHero = function (ex, ey, time, callback) {
|
||||
var sx=core.status.hero.loc.x, sy=core.status.hero.loc.y;
|
||||
if (!core.isset(ex)) ex=sx;
|
||||
if (!core.isset(ey)) ey=sy;
|
||||
core.maps.__playJumpSound();
|
||||
core.playSound('jump.mp3');
|
||||
var jumpInfo = core.maps.__generateJumpInfo(sx, sy, ex, ey, time || 500);
|
||||
jumpInfo.icon = core.material.icons.hero[core.getHeroLoc('direction')];
|
||||
jumpInfo.height = core.material.icons.hero.height;
|
||||
@ -2209,7 +2251,7 @@ events.prototype.afterUseBomb = function () {
|
||||
}
|
||||
|
||||
////// 上传当前数据 //////
|
||||
events.prototype.uploadCurrent = function (username) {
|
||||
events.prototype._uploadCurrent = function (username) {
|
||||
var formData = new FormData();
|
||||
|
||||
formData.append('type', 'score');
|
||||
|
||||
@ -196,20 +196,6 @@ items.prototype.setItem = function (itemId, itemNum) {
|
||||
core.updateStatusBar();
|
||||
}
|
||||
|
||||
////// 删除某个物品 //////
|
||||
items.prototype.removeItem = function (itemId, itemNum) {
|
||||
if (itemNum == null) itemNum = 1;
|
||||
if (!core.hasItem(itemId)) return false;
|
||||
var itemCls = core.material.items[itemId].cls;
|
||||
core.status.hero.items[itemCls][itemId] -= itemNum;
|
||||
if (core.status.hero.items[itemCls][itemId] <= 0) {
|
||||
if (itemCls != 'keys') delete core.status.hero.items[itemCls][itemId];
|
||||
else core.status.hero.items[itemCls][itemId] = 0;
|
||||
}
|
||||
core.updateStatusBar();
|
||||
return true;
|
||||
}
|
||||
|
||||
////// 增加某个物品的个数 //////
|
||||
items.prototype.addItem = function (itemId, itemNum) {
|
||||
if (itemNum == null) itemNum = 1;
|
||||
@ -230,15 +216,22 @@ items.prototype.addItem = function (itemId, itemNum) {
|
||||
core.updateStatusBar();
|
||||
}
|
||||
|
||||
// ---------- 装备相关 ------------ //
|
||||
|
||||
items.prototype.getEquipTypeById = function (equipId) {
|
||||
var type = core.material.items[equipId].equip.type;
|
||||
if (typeof type == 'string')
|
||||
type = this.getEquipTypeByName(type);
|
||||
return type;
|
||||
////// 删除某个物品 //////
|
||||
items.prototype.removeItem = function (itemId, itemNum) {
|
||||
if (itemNum == null) itemNum = 1;
|
||||
if (!core.hasItem(itemId)) return false;
|
||||
var itemCls = core.material.items[itemId].cls;
|
||||
core.status.hero.items[itemCls][itemId] -= itemNum;
|
||||
if (core.status.hero.items[itemCls][itemId] <= 0) {
|
||||
if (itemCls != 'keys') delete core.status.hero.items[itemCls][itemId];
|
||||
else core.status.hero.items[itemCls][itemId] = 0;
|
||||
}
|
||||
core.updateStatusBar();
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------- 装备相关 ------------ //
|
||||
|
||||
items.prototype.getEquipTypeByName = function (name) {
|
||||
var names = core.status.globalAttribute.equipName;
|
||||
for (var i = 0; i < names.length; ++i) {
|
||||
@ -249,6 +242,13 @@ items.prototype.getEquipTypeByName = function (name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
items.prototype.getEquipTypeById = function (equipId) {
|
||||
var type = core.material.items[equipId].equip.type;
|
||||
if (typeof type == 'string')
|
||||
type = this.getEquipTypeByName(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
// 当前能否撞上某装备
|
||||
items.prototype.canEquip = function (equipId, hint) {
|
||||
// 装备是否合法
|
||||
@ -365,8 +365,8 @@ items.prototype._realLoadEquip = function (type, loadId, unloadId, callback) {
|
||||
core.status.hero.equipment[type] = loadId || null;
|
||||
|
||||
// --- 提示
|
||||
if (loadId) core.drawTip("已装备上" + loadEquip.name, core.material.icons.items[loadId]);
|
||||
else if (unloadId) core.drawTip("已卸下" + unloadEquip.name, core.material.icons.items[unloadId]);
|
||||
if (loadId) core.drawTip("已装备上" + loadEquip.name, loadId);
|
||||
else if (unloadId) core.drawTip("已卸下" + unloadEquip.name, unloadId);
|
||||
|
||||
if (callback) callback();
|
||||
}
|
||||
|
||||
152
libs/maps.js
152
libs/maps.js
@ -155,7 +155,8 @@ maps.prototype._addEvent = function (block, x, y, event) {
|
||||
}
|
||||
|
||||
////// 初始化所有地图 //////
|
||||
maps.prototype.initMaps = function (floorIds) {
|
||||
maps.prototype._initMaps = function () {
|
||||
var floorIds = core.floorIds;
|
||||
var maps = {};
|
||||
for (var i = 0; i < floorIds.length; i++) {
|
||||
var floorId = floorIds[i];
|
||||
@ -242,7 +243,7 @@ maps.prototype.saveMap = function (floorId) {
|
||||
return map;
|
||||
}
|
||||
var map = maps[floorId], floor = core.floors[floorId];
|
||||
var blocks = this.getMapArray(map.blocks, floor.width, floor.height, true);
|
||||
var blocks = this._getMapArrayFromBlocks(map.blocks, floor.width, floor.height, true);
|
||||
if (main.mode == 'editor') return blocks;
|
||||
|
||||
var thisFloor = this._compressFloorData(map, floor);
|
||||
@ -297,7 +298,13 @@ maps.prototype.resizeMap = function (floorId) {
|
||||
}
|
||||
|
||||
////// 将当前地图重新变成二维数组形式 //////
|
||||
maps.prototype.getMapArray = function (blockArray, width, height, checkDisable) {
|
||||
maps.prototype.getMapArray = function (floorId, showDisable) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
return this._getMapArrayFromBlocks(core.status.maps[floorId].blocks,
|
||||
core.floors[floorId].width, core.floors[floorId].height, showDisable);
|
||||
}
|
||||
|
||||
maps.prototype._getMapArrayFromBlocks = function (blockArray, width, height, showDisable) {
|
||||
if (typeof blockArray == 'string') {
|
||||
var floorId = blockArray;
|
||||
blockArray = core.status.maps[floorId].blocks;
|
||||
@ -313,11 +320,11 @@ maps.prototype.getMapArray = function (blockArray, width, height, checkDisable)
|
||||
blockArray.forEach(function (block) {
|
||||
var x = block.x, y = block.y;
|
||||
if (block.disable) {
|
||||
if (checkDisable) blocks[y][x] = block.id + ":f";
|
||||
if (showDisable) blocks[y][x] = block.id + ":f";
|
||||
}
|
||||
else {
|
||||
blocks[y][x] = block.id;
|
||||
if (checkDisable && block.disable === false)
|
||||
if (showDisable && block.disable === false)
|
||||
blocks[y][x] = block.id + ":t";
|
||||
}
|
||||
});
|
||||
@ -336,7 +343,7 @@ maps.prototype.getMapBlocksObj = function (floorId, showDisable) {
|
||||
}
|
||||
|
||||
////// 将背景前景层变成二维数组的形式 //////
|
||||
maps.prototype.getBgFgMapArray = function (name, floorId, noCache) {
|
||||
maps.prototype._getBgFgMapArray = function (name, floorId, noCache) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (!floorId) return [];
|
||||
var width = core.floors[floorId].width;
|
||||
@ -362,10 +369,26 @@ maps.prototype.getBgFgMapArray = function (name, floorId, noCache) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
maps.prototype.getBgFgNumber = function (name, x, y, floorId, noCache) {
|
||||
maps.prototype.getBgMapArray = function (floorId, noCache) {
|
||||
return this._getBgFgMapArray('bg', floorId, noCache);
|
||||
}
|
||||
|
||||
maps.prototype.getFgMapArray = function (floorId, noCache) {
|
||||
return this._getBgFgMapArray('fg', floorId, noCache);
|
||||
}
|
||||
|
||||
maps.prototype._getBgFgNumber = function (name, x, y, floorId, noCache) {
|
||||
if (x == null) x = core.getHeroLoc('x');
|
||||
if (y == null) y = core.getHeroLoc('y');
|
||||
return this.getBgFgMapArray(name, floorId, noCache)[y][x];
|
||||
return this._getBgFgMapArray(name, floorId, noCache)[y][x];
|
||||
}
|
||||
|
||||
maps.prototype.getBgNumber = function (x, y, floorId, noCache) {
|
||||
return this._getBgFgNumber('bg', x, y, floorId, noCache);
|
||||
}
|
||||
|
||||
maps.prototype.getFgNumber = function (x, y, floorId, noCache) {
|
||||
return this._getBgFgNumber('fg', x, y, floorId, noCache);
|
||||
}
|
||||
|
||||
// ------ 当前能否朝某方向移动,能否瞬间移动 ------ //
|
||||
@ -375,8 +398,8 @@ maps.prototype.generateMovableArray = function (floorId, x, y, direction) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (!floorId) return null;
|
||||
var width = core.floors[floorId].width, height = core.floors[floorId].height;
|
||||
var bgArray = this.getBgFgMapArray('bg', floorId),
|
||||
fgArray = this.getBgFgMapArray('fg', floorId),
|
||||
var bgArray = this.getBgMapArray(floorId),
|
||||
fgArray = this.getFgMapArray(floorId),
|
||||
eventArray = this.getMapArray(floorId);
|
||||
|
||||
var generate = function (x, y, direction) {
|
||||
@ -489,7 +512,7 @@ maps.prototype._canMoveDirectly_bfs = function (sx, sy, ex, ey) {
|
||||
var canMoveArray = this.generateMovableArray();
|
||||
var blocksObj = this.getMapBlocksObj(core.status.floorId);
|
||||
// 滑冰
|
||||
var bgMap = this.getBgFgMapArray('bg');
|
||||
var bgMap = this.getBgMapArray();
|
||||
|
||||
var visited = [], queue = [];
|
||||
visited[sx + "," + sy] = 0;
|
||||
@ -685,7 +708,7 @@ maps.prototype._drawMap_drawAll = function (floorId) {
|
||||
maps.prototype._drawMap_drawBlockInfo = function (ctx, block, blockInfo, arr, onMap) {
|
||||
if (blockInfo == null) return;
|
||||
if (blockInfo.cls == 'autotile') { // Autotile单独处理
|
||||
this.drawAutotile(ctx, arr, block, 32, 0, 0);
|
||||
this._drawAutotile(ctx, arr, block, 32, 0, 0);
|
||||
if (onMap) this.addGlobalAnimate(block);
|
||||
return;
|
||||
}
|
||||
@ -700,15 +723,16 @@ maps.prototype._drawMap_drawBlockInfo = function (ctx, block, blockInfo, arr, on
|
||||
|
||||
////// 绘制背景层 //////
|
||||
maps.prototype.drawBg = function (floorId, ctx) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
var onMap = ctx == null;
|
||||
if (onMap) {
|
||||
ctx = core.canvas.bg;
|
||||
core.clearMap(ctx);
|
||||
}
|
||||
this._drawBg_drawBackground(floorId, ctx);
|
||||
core.maps._drawBg_drawBackground(floorId, ctx);
|
||||
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。
|
||||
this._drawFloorImages(floorId, ctx, 'bg');
|
||||
this._drawBgFgMap(floorId, ctx, 'bg', onMap);
|
||||
core.maps._drawFloorImages(floorId, ctx, 'bg');
|
||||
core.maps._drawBgFgMap(floorId, ctx, 'bg', onMap);
|
||||
}
|
||||
|
||||
maps.prototype._drawBg_drawBackground = function (floorId, ctx) {
|
||||
@ -728,7 +752,7 @@ maps.prototype._drawBg_drawBackground = function (floorId, ctx) {
|
||||
maps.prototype.drawEvents = function (floorId, blocks, ctx) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (!blocks) blocks = core.status.maps[floorId].blocks;
|
||||
var arr = this.getMapArray(blocks, core.floors[floorId].width, core.floors[floorId].height);
|
||||
var arr = this._getMapArrayFromBlocks(blocks, core.floors[floorId].width, core.floors[floorId].height);
|
||||
var onMap = ctx == null;
|
||||
if (onMap) ctx = core.canvas.event;
|
||||
blocks.filter(function (block) {
|
||||
@ -741,6 +765,7 @@ maps.prototype.drawEvents = function (floorId, blocks, ctx) {
|
||||
|
||||
////// 绘制前景层 //////
|
||||
maps.prototype.drawFg = function (floorId, ctx) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
var onMap = ctx == null;
|
||||
if (onMap) ctx = core.canvas.fg;
|
||||
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。
|
||||
@ -758,7 +783,7 @@ maps.prototype._drawBgFgMap = function (floorId, ctx, name, onMap) {
|
||||
if (!core.status[name + "maps"])
|
||||
core.status[name + "maps"] = {};
|
||||
|
||||
var arr = this.getBgFgMapArray(name, floorId, true);
|
||||
var arr = this._getBgFgMapArray(name, floorId, true);
|
||||
for (var x = 0; x < width; x++) {
|
||||
for (var y = 0; y < height; y++) {
|
||||
var block = this.initBlock(x, y, arr[y][x], true);
|
||||
@ -850,7 +875,7 @@ maps.prototype._drawFloorImage = function (ctx, name, type, image, offsetX, widt
|
||||
}
|
||||
|
||||
////// 绘制Autotile //////
|
||||
maps.prototype.drawAutotile = function (ctx, mapArr, block, size, left, top, status) {
|
||||
maps.prototype._drawAutotile = function (ctx, mapArr, block, size, left, top, status) {
|
||||
var indexArrs = [ //16种组合的图块索引数组; // 将autotile分割成48块16*16的小块; 数组索引即对应各个小块
|
||||
// +----+----+----+----+----+----+
|
||||
[10, 9, 4, 3], //0 bin:0000 | 1 | 2 | 3 | 4 | 5 | 6 |
|
||||
@ -1215,7 +1240,7 @@ maps.prototype.searchBlock = function (id, floorId, showDisable) {
|
||||
for (var i = 0; i < core.status.maps[floorId].blocks.length; ++i) {
|
||||
var block = core.status.maps[floorId].blocks[i];
|
||||
if (block.event.id == id && (showDisable || !block.disable))
|
||||
result.push({floorId: floorId, index: i, block: block});
|
||||
result.push({floorId: floorId, index: i, block: block, x: block.x, y: block.y});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -1301,19 +1326,6 @@ maps.prototype.removeBlockById = function (index, floorId) {
|
||||
}
|
||||
}
|
||||
|
||||
////// 能否彻底从地图中删除一个图块 //////
|
||||
maps.prototype.canRemoveBlock = function (block, floorId) {
|
||||
var x = block.x, y = block.y;
|
||||
// 检查该点是否存在事件
|
||||
if (core.floors[floorId].events[x + "," + y] || core.floors[floorId].changeFloor[x + "," + y])
|
||||
return false;
|
||||
// 检查是否存在重生
|
||||
if (block.event && block.event.cls.indexOf('enemy') == 0 && core.hasSpecial(block.event.id, 23))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////// 一次性删除多个block //////
|
||||
maps.prototype.removeBlockByIds = function (floorId, ids) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
@ -1325,24 +1337,17 @@ maps.prototype.removeBlockByIds = function (floorId, ids) {
|
||||
});
|
||||
}
|
||||
|
||||
////// 将地图中所有某个图块替换成另一个图块 //////
|
||||
maps.prototype.replaceBlock = function (fromNumber, toNumber, floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (floorId instanceof Array) {
|
||||
floorId.forEach(function (floorId) {
|
||||
core.replaceBlock(fromNumber, toNumber, floorId);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var toBlock = this.initBlock(0, 0, toNumber, true);
|
||||
core.status.maps[floorId].blocks.forEach(function (block) {
|
||||
if (block.id == fromNumber) {
|
||||
block.id = toNumber;
|
||||
for (var one in toBlock.event) {
|
||||
block.event[one] = core.clone(toBlock.event[one]);
|
||||
}
|
||||
}
|
||||
});
|
||||
////// 能否彻底从地图中删除一个图块 //////
|
||||
maps.prototype.canRemoveBlock = function (block, floorId) {
|
||||
var x = block.x, y = block.y;
|
||||
// 检查该点是否存在事件
|
||||
if (core.floors[floorId].events[x + "," + y] || core.floors[floorId].changeFloor[x + "," + y])
|
||||
return false;
|
||||
// 检查是否存在重生
|
||||
if (block.event && block.event.cls.indexOf('enemy') == 0 && core.hasSpecial(block.event.id, 23))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////// 显示前景/背景地图 //////
|
||||
@ -1420,6 +1425,7 @@ maps.prototype.setBlock = function (number, x, y, floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (!floorId || number == null || x == null || y == null) return;
|
||||
if (x < 0 || x >= core.floors[floorId].width || y < 0 || y >= core.floors[floorId].height) return;
|
||||
if (typeof number == 'string') number = core.getNumberById(number);
|
||||
|
||||
var originBlock = core.getBlock(x, y, floorId, true);
|
||||
var block = this.initBlock(x, y, number, true, core.floors[floorId]);
|
||||
@ -1447,6 +1453,26 @@ maps.prototype.setBlock = function (number, x, y, floorId) {
|
||||
}
|
||||
}
|
||||
|
||||
////// 将地图中所有某个图块替换成另一个图块 //////
|
||||
maps.prototype.replaceBlock = function (fromNumber, toNumber, floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (floorId instanceof Array) {
|
||||
floorId.forEach(function (floorId) {
|
||||
core.replaceBlock(fromNumber, toNumber, floorId);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var toBlock = this.initBlock(0, 0, toNumber, true);
|
||||
core.status.maps[floorId].blocks.forEach(function (block) {
|
||||
if (block.id == fromNumber) {
|
||||
block.id = toNumber;
|
||||
for (var one in toBlock.event) {
|
||||
block.event[one] = core.clone(toBlock.event[one]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
////// 改变前景背景的图块 //////
|
||||
maps.prototype.setBgFgBlock = function (name, number, x, y, floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
@ -1629,10 +1655,8 @@ maps.prototype.jumpBlock = function (sx, sy, ex, ey, time, keep, callback) {
|
||||
var block = blockArr[0], blockInfo = blockArr[1];
|
||||
var canvases = this._initDetachedBlock(blockInfo, sx, sy, block.event.animate !== false);
|
||||
this._moveDetachedBlock(blockInfo, 32 * sx, 32 * sy, 1, canvases);
|
||||
|
||||
this.__playJumpSound();
|
||||
|
||||
var jumpInfo = ths.__generateJumpInfo(sx, sy, ex, ey, time);
|
||||
core.playSound('jump.mp3');
|
||||
var jumpInfo = this.__generateJumpInfo(sx, sy, ex, ey, time);
|
||||
jumpInfo.keep = keep;
|
||||
|
||||
this._jumpBlock_doJump(blockInfo, canvases, jumpInfo, callback);
|
||||
@ -1644,14 +1668,10 @@ maps.prototype.__generateJumpInfo = function (sx, sy, ex, ey, time) {
|
||||
return {
|
||||
x: sx, y: sy, ex: ex, ey: ey, px: 32 * sx, py: 32 * sy, opacity: 1,
|
||||
jump_peak: jump_peak, jump_count: jump_count,
|
||||
step: 0, per_time: time / 16 / core.status.replay.speed
|
||||
step: 0, per_time: time / jump_count
|
||||
};
|
||||
}
|
||||
|
||||
maps.prototype.__playJumpSound = function () {
|
||||
core.playSound('jump.mp3');
|
||||
}
|
||||
|
||||
maps.prototype._jumpBlock_doJump = function (blockInfo, canvases, jumpInfo, callback) {
|
||||
var animate = window.setInterval(function () {
|
||||
if (jumpInfo.jump_count > 0)
|
||||
@ -1766,16 +1786,16 @@ maps.prototype._animateBlock_drawList = function (list, opacity) {
|
||||
// ------ 全局动画控制,动画绘制 ------ //
|
||||
|
||||
////// 添加一个全局动画 //////
|
||||
maps.prototype.addGlobalAnimate = function (b) {
|
||||
if (!b.event || b.event.animate == null) return;
|
||||
if (b.event.cls == 'autotile') {
|
||||
var id = b.event.id, img = core.material.images.autotile[id];
|
||||
maps.prototype.addGlobalAnimate = function (block) {
|
||||
if (!block.event || block.event.animate == null) return;
|
||||
if (block.event.cls == 'autotile') {
|
||||
var id = block.event.id, img = core.material.images.autotile[id];
|
||||
if (!img || img.width == 96) return;
|
||||
core.status.autotileAnimateObjs.blocks.push(b);
|
||||
core.status.autotileAnimateObjs.blocks.push(block);
|
||||
}
|
||||
else {
|
||||
if (!b.event.animate || b.event.animate == 1) return;
|
||||
core.status.globalAnimateObjs.push(b);
|
||||
if (!block.event.animate || block.event.animate == 1) return;
|
||||
core.status.globalAnimateObjs.push(block);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
132
libs/ui.js
132
libs/ui.js
@ -23,12 +23,13 @@ ui.prototype._init = function () {
|
||||
|
||||
////////////////// 地图设置
|
||||
|
||||
ui.prototype.getContextByName = function (canvas) {
|
||||
if (typeof canvas == 'string') {
|
||||
if (core.canvas[canvas])
|
||||
canvas = core.canvas[canvas];
|
||||
else if (core.dymCanvas[canvas])
|
||||
canvas = core.dymCanvas[canvas];
|
||||
ui.prototype.getContextByName = function (name) {
|
||||
var canvas = name;
|
||||
if (typeof name == 'string') {
|
||||
if (core.canvas[name])
|
||||
canvas = core.canvas[name];
|
||||
else if (core.dymCanvas[name])
|
||||
canvas = core.dymCanvas[name];
|
||||
}
|
||||
if (canvas && canvas.canvas) {
|
||||
return canvas;
|
||||
@ -190,6 +191,36 @@ ui.prototype.calWidth = function (name, text, font) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
////// 字符串自动换行的分割 //////
|
||||
ui.prototype.splitLines = function (name, text, maxWidth, font) {
|
||||
var ctx = this.getContextByName(name);
|
||||
if (!ctx) return;
|
||||
if (font) core.setFont(name, font);
|
||||
|
||||
var contents = [];
|
||||
var last = 0;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
if (text.charAt(i) == '\n') {
|
||||
contents.push(text.substring(last, i));
|
||||
last = i + 1;
|
||||
}
|
||||
else if (text.charAt(i) == '\\' && text.charAt(i + 1) == 'n') {
|
||||
contents.push(text.substring(last, i));
|
||||
last = i + 2;
|
||||
}
|
||||
else {
|
||||
var toAdd = text.substring(last, i + 1);
|
||||
var width = core.calWidth(name, toAdd);
|
||||
if (maxWidth && width > maxWidth) {
|
||||
contents.push(text.substring(last, i));
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
contents.push(text.substring(last));
|
||||
return contents;
|
||||
}
|
||||
|
||||
////// 绘制一张图片 //////
|
||||
ui.prototype.drawImage = function (name, image, x, y, w, h, x1, y1, w1, h1) {
|
||||
var ctx = this.getContextByName(name);
|
||||
@ -233,25 +264,23 @@ ui.prototype.clearUI = function () {
|
||||
clearInterval(core.status.event.interval);
|
||||
core.status.event.interval = null;
|
||||
core.status.boxAnimateObjs = [];
|
||||
core.clearSelector();
|
||||
core.clearMap('ui');
|
||||
core.setAlpha('ui', 1);
|
||||
}
|
||||
|
||||
////// 清除光标 //////
|
||||
ui.prototype.clearSelector = function () {
|
||||
if (core.dymCanvas._selector) core.deleteCanvas("_selector");
|
||||
core.clearMap('ui');
|
||||
core.setAlpha('ui', 1);
|
||||
}
|
||||
|
||||
////// 左上角绘制一段提示 //////
|
||||
ui.prototype.drawTip = function (text, itemIcon) {
|
||||
ui.prototype.drawTip = function (text, id) {
|
||||
var textX, textY, width, height;
|
||||
clearInterval(core.interval.tipAnimate);
|
||||
core.setFont('data', "16px Arial");
|
||||
core.setTextAlign('data', 'left');
|
||||
if (!itemIcon) {
|
||||
if (id != null) {
|
||||
var info = core.getBlockInfo(id);
|
||||
if (info == null || !info.image || info.height != 32) id = null;
|
||||
else id = info;
|
||||
}
|
||||
if (!id) {
|
||||
textX = 16;
|
||||
textY = 18;
|
||||
width = textX + core.calWidth('data', text) + 16;
|
||||
@ -263,10 +292,10 @@ ui.prototype.drawTip = function (text, itemIcon) {
|
||||
width = textX + core.calWidth('data', text) + 8;
|
||||
height = 42;
|
||||
}
|
||||
this._drawTip_animate(text, itemIcon, textX, textY, width, height);
|
||||
this._drawTip_animate(text, id, textX, textY, width, height);
|
||||
}
|
||||
|
||||
ui.prototype._drawTip_animate = function (text, itemIcon, textX, textY, width, height) {
|
||||
ui.prototype._drawTip_animate = function (text, info, textX, textY, width, height) {
|
||||
var alpha = 0, hide = false;
|
||||
core.interval.tipAnimate = window.setInterval(function () {
|
||||
if (hide) alpha -= 0.1;
|
||||
@ -274,8 +303,8 @@ ui.prototype._drawTip_animate = function (text, itemIcon, textX, textY, width, h
|
||||
core.clearMap('data', 5, 5, core.ui.PIXEL, height);
|
||||
core.setAlpha('data', alpha);
|
||||
core.fillRect('data', 5, 5, width, height, '#000');
|
||||
if (itemIcon)
|
||||
core.drawImage('data', core.material.images.items, 0, itemIcon * 32, 32, 32, 10, 8, 32, 32);
|
||||
if (info)
|
||||
core.drawImage('data', info.image, info.posX * 32, info.posY * 32, 32, 32, 10, 8, 32, 32);
|
||||
core.fillText('data', text, textX + 5, textY + 15, '#fff');
|
||||
core.setAlpha('data', 1);
|
||||
if (alpha > 0.6 || alpha < 0) {
|
||||
@ -507,13 +536,13 @@ ui.prototype.drawBackground = function (left, top, right, bottom, posInfo) {
|
||||
}
|
||||
|
||||
////// 计算有效文本框的宽度
|
||||
ui.prototype.calTextBoxWidth = function (ctx, content, min_width, max_width, font) {
|
||||
ui.prototype._calTextBoxWidth = function (ctx, content, min_width, max_width, font) {
|
||||
// 无限长度自动换行
|
||||
var allLines = core.splitLines(ctx, content, null, font);
|
||||
|
||||
// 如果不存在手动换行,尽量调成半行形式
|
||||
if (allLines.length == 1) {
|
||||
var w = core.calWidth(ctx, allLines[0]);
|
||||
var w = core.calWidth(ctx, allLines[0]) + 10;
|
||||
if (w<min_width*2.3) return core.clamp(w / 1.4, min_width, max_width);
|
||||
if (w<max_width*2.2) return core.clamp(w / 2.4, min_width, max_width);
|
||||
return core.clamp(w / 3.4, min_width, max_width);
|
||||
@ -521,7 +550,7 @@ ui.prototype.calTextBoxWidth = function (ctx, content, min_width, max_width, fon
|
||||
// 存在手动换行:以最长的为准
|
||||
else {
|
||||
return core.clamp(allLines.reduce(function (pre, curr) {
|
||||
return Math.max(pre, core.calWidth(ctx, curr))
|
||||
return Math.max(pre, core.calWidth(ctx, curr) + 10);
|
||||
}, 0), min_width, max_width);
|
||||
}
|
||||
}
|
||||
@ -794,7 +823,7 @@ ui.prototype._drawTextBox_getHorizontalPosition = function (content, titleInfo,
|
||||
var min_width = 220 - paddingLeft, max_width = validWidth;
|
||||
// 无行走图或头像,则可以适当缩小min_width
|
||||
if (titleInfo.image == null) min_width = 160;
|
||||
validWidth = this.calTextBoxWidth('ui', realContent, min_width, max_width, this._buildFont());
|
||||
validWidth = this._calTextBoxWidth('ui', realContent, min_width, max_width, this._buildFont());
|
||||
width = validWidth + paddingLeft + paddingRight;
|
||||
left = core.clamp(32 * posInfo.px + 16 - width / 2 - core.bigmap.offsetX, left, right - width);
|
||||
right = left + width;
|
||||
@ -1052,9 +1081,13 @@ ui.prototype.drawConfirmBox = function (text, yesCallback, noCallback) {
|
||||
core.lockControl();
|
||||
text = core.replaceText(text || "");
|
||||
|
||||
core.status.event.id = 'confirmBox';
|
||||
core.status.event.data = {'yes': yesCallback, 'no': noCallback};
|
||||
core.status.event.ui = text;
|
||||
// 处理自定义事件
|
||||
if (core.status.event.id != 'action') {
|
||||
core.status.event.id = 'confirmBox';
|
||||
core.status.event.ui = text;
|
||||
core.status.event.data = {'yes': yesCallback, 'no': noCallback};
|
||||
}
|
||||
|
||||
if (core.status.event.selection != 0) core.status.event.selection = 1;
|
||||
this.clearUI();
|
||||
|
||||
@ -1090,6 +1123,20 @@ ui.prototype._drawConfirmBox_getRect = function (contents) {
|
||||
return { top: top, left: left, bottom: bottom, right: right, width: right - left, height: bottom - top };
|
||||
}
|
||||
|
||||
////// 绘制等待界面 //////
|
||||
ui.prototype.drawWaiting = function(text) {
|
||||
core.lockControl();
|
||||
core.status.event.id = 'waiting';
|
||||
core.clearUI();
|
||||
text = core.replaceText(text || "");
|
||||
var text_length = core.calWidth('ui', text, this._buildFont(19, true));
|
||||
var width = Math.max(text_length + 80, 220), left = this.HPIXEL - parseInt(width / 2), right = left + width;
|
||||
var top = this.HPIXEL - 48, height = 96, bottom = top + height;
|
||||
this.drawBackground(left, top, right, bottom);
|
||||
core.setTextAlign('ui', 'center');
|
||||
core.fillText('ui', text, this.HPIXEL, top + 56, core.arrayToRGBA(core.status.textAttribute.text));
|
||||
}
|
||||
|
||||
////// 绘制系统设置界面 //////
|
||||
ui.prototype.drawSwitchs = function() {
|
||||
core.status.event.id = 'switchs';
|
||||
@ -1128,20 +1175,6 @@ ui.prototype.drawQuickShop = function () {
|
||||
this.drawChoices(null, choices);
|
||||
}
|
||||
|
||||
////// 绘制等待界面 //////
|
||||
ui.prototype.drawWaiting = function(text) {
|
||||
core.lockControl();
|
||||
core.status.event.id = 'waiting';
|
||||
core.clearSelector();
|
||||
text = core.replaceText(text || "");
|
||||
var text_length = core.calWidth('ui', text, this._buildFont(19, true));
|
||||
var width = Math.max(text_length + 80, 220), left = this.HPIXEL - parseInt(width / 2), right = left + width;
|
||||
var top = this.HPIXEL - 48, height = 96, bottom = top + height;
|
||||
this.drawBackground(left, top, right, bottom);
|
||||
core.setTextAlign('ui', 'center');
|
||||
core.fillText('ui', text, this.HPIXEL, top + 56, core.arrayToRGBA(core.status.textAttribute.text));
|
||||
}
|
||||
|
||||
////// 绘制存档同步界面 //////
|
||||
ui.prototype.drawSyncSave = function () {
|
||||
core.status.event.id = 'syncSave';
|
||||
@ -1190,22 +1223,22 @@ ui.prototype.drawGameInfo = function () {
|
||||
}
|
||||
|
||||
////// 绘制分页 //////
|
||||
ui.prototype.drawPagination = function (page, totalPage, top) {
|
||||
ui.prototype.drawPagination = function (page, totalPage, y) {
|
||||
// if (totalPage<page) totalPage=page;
|
||||
if (totalPage <= 1) return;
|
||||
if (top == null) top = this.LAST;
|
||||
if (y == null) y = this.LAST;
|
||||
|
||||
core.setFillStyle('ui', '#DDDDDD');
|
||||
var length = core.calWidth('ui', page + " / " + page, this._buildFont(15, true));
|
||||
|
||||
core.setTextAlign('ui', 'left');
|
||||
core.fillText('ui', page + " / " + totalPage, parseInt((this.PIXEL - length) / 2), top*32+19);
|
||||
core.fillText('ui', page + " / " + totalPage, parseInt((this.PIXEL - length) / 2), y*32+19);
|
||||
|
||||
core.setTextAlign('ui', 'center');
|
||||
if (page > 1)
|
||||
core.fillText('ui', '上一页', this.HPIXEL - 80, top*32+19);
|
||||
core.fillText('ui', '上一页', this.HPIXEL - 80, y*32+19);
|
||||
if (page < totalPage)
|
||||
core.fillText('ui', '下一页', this.HPIXEL + 80, top*32+19);
|
||||
core.fillText('ui', '下一页', this.HPIXEL + 80, y*32+19);
|
||||
}
|
||||
|
||||
////// 绘制键盘光标 //////
|
||||
@ -1254,6 +1287,7 @@ ui.prototype.drawBook = function (index) {
|
||||
|
||||
core.drawBoxAnimate();
|
||||
this.drawPagination(page, totalPage);
|
||||
core.setTextAlign('ui', 'center');
|
||||
core.fillText('ui', '返回游戏', this.PIXEL - 46, this.PIXEL - 13,'#DDDDDD', this._buildFont(15, true));
|
||||
}
|
||||
|
||||
@ -1632,7 +1666,7 @@ ui.prototype.drawMaps = function (index, x, y) {
|
||||
var offsetX = 32 * (data.x - this.HSIZE), offsetY = 32 * (data.y - this.HSIZE);
|
||||
var value = core.paint[data.floorId];
|
||||
if (value) value = lzw_decode(value).split(",");
|
||||
core.utils.decodeCanvas(value, 32 * data.mw, 32 * data.mh);
|
||||
core.utils._decodeCanvas(value, 32 * data.mw, 32 * data.mh);
|
||||
core.drawImage('ui', core.bigmap.tempCanvas.canvas, offsetX * 32, offsetY * 32,
|
||||
this.PIXEL, this.PIXEL, 0, 0, this.PIXEL, this.PIXEL);
|
||||
}
|
||||
@ -2358,13 +2392,13 @@ ui.prototype._drawPaint_draw = function () {
|
||||
core.status.event.id = 'paint';
|
||||
core.status.event.data = {"x": null, "y": null, "erase": false};
|
||||
|
||||
core.clearSelector();
|
||||
core.clearUI();
|
||||
core.createCanvas('paint', -core.bigmap.offsetX, -core.bigmap.offsetY, 32*core.bigmap.width, 32*core.bigmap.height, 95);
|
||||
|
||||
// 将已有的内容绘制到route上
|
||||
var value = core.paint[core.status.floorId];
|
||||
if (core.isset(value)) value = lzw_decode(value).split(",");
|
||||
core.utils.decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height);
|
||||
core.utils._decodeCanvas(value, 32*core.bigmap.width, 32*core.bigmap.height);
|
||||
core.drawImage('paint', core.bigmap.tempCanvas.canvas, 0, 0);
|
||||
|
||||
core.setLineWidth('paint', 3);
|
||||
@ -2383,7 +2417,7 @@ ui.prototype._drawPaint_draw = function () {
|
||||
|
||||
////// 绘制帮助页面 //////
|
||||
ui.prototype.drawHelp = function () {
|
||||
core.clearSelector();
|
||||
core.clearUI();
|
||||
if (core.material.images.keyboard) {
|
||||
core.status.event.id = 'help';
|
||||
core.lockControl();
|
||||
|
||||
100
libs/utils.js
100
libs/utils.js
@ -75,35 +75,6 @@ utils.prototype.calValue = function (value, prefix, need, times) {
|
||||
return value;
|
||||
}
|
||||
|
||||
////// 字符串自动换行的分割 //////
|
||||
utils.prototype.splitLines = function (canvas, text, maxLength, font) {
|
||||
if (font) core.setFont(canvas, font);
|
||||
|
||||
var contents = [];
|
||||
var last = 0;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
|
||||
if (text.charAt(i) == '\n') {
|
||||
contents.push(text.substring(last, i));
|
||||
last = i + 1;
|
||||
}
|
||||
else if (text.charAt(i) == '\\' && text.charAt(i + 1) == 'n') {
|
||||
contents.push(text.substring(last, i));
|
||||
last = i + 2;
|
||||
}
|
||||
else {
|
||||
var toAdd = text.substring(last, i + 1);
|
||||
var width = core.calWidth(canvas, toAdd);
|
||||
if (maxLength && width > maxLength) {
|
||||
contents.push(text.substring(last, i));
|
||||
last = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
contents.push(text.substring(last));
|
||||
return contents;
|
||||
}
|
||||
|
||||
////// 向某个数组前插入另一个数组或元素 //////
|
||||
utils.prototype.unshift = function (a, b) {
|
||||
if (!(a instanceof Array) || b == null) return;
|
||||
@ -128,6 +99,28 @@ utils.prototype.push = function (a, b) {
|
||||
return a;
|
||||
}
|
||||
|
||||
utils.prototype.decompress = function (value) {
|
||||
try {
|
||||
var output = lzw_decode(value);
|
||||
if (output) return JSON.parse(output);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
try {
|
||||
var output = LZString.decompress(value);
|
||||
if (output) return JSON.parse(output);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
}
|
||||
catch (e) {
|
||||
main.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
////// 设置本地存储 //////
|
||||
utils.prototype.setLocalStorage = function (key, value) {
|
||||
try {
|
||||
@ -163,28 +156,6 @@ utils.prototype.setLocalStorage = function (key, value) {
|
||||
}
|
||||
}
|
||||
|
||||
utils.prototype.decompress = function (value) {
|
||||
try {
|
||||
var output = lzw_decode(value);
|
||||
if (output) return JSON.parse(output);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
try {
|
||||
var output = LZString.decompress(value);
|
||||
if (output) return JSON.parse(output);
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
}
|
||||
catch (e) {
|
||||
main.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
////// 获得本地存储 //////
|
||||
utils.prototype.getLocalStorage = function (key, defaultValue) {
|
||||
var res = this.decompress(localStorage.getItem(core.firstData.name + "_" + key));
|
||||
@ -475,7 +446,7 @@ utils.prototype._encodeRoute_encodeOne = function (t) {
|
||||
return 'K' + t.substring(4);
|
||||
else if (t.indexOf('random:') == 0)
|
||||
return 'X' + t.substring(7);
|
||||
return '';
|
||||
return '('+t+')';
|
||||
}
|
||||
|
||||
////// 解密路线 //////
|
||||
@ -485,8 +456,9 @@ utils.prototype.decodeRoute = function (route) {
|
||||
// 解压缩
|
||||
try {
|
||||
var v = LZString.decompressFromBase64(route);
|
||||
if (/^[a-zA-Z0-9+\/=:]*$/.test(v)) {
|
||||
route = v;
|
||||
if (v != null && /^[-_a-zA-Z0-9+\/=:()]*$/.test(v)) {
|
||||
if (v != "" || route.length < 8)
|
||||
route = v;
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
@ -525,6 +497,15 @@ utils.prototype._decodeRoute_number2id = function (number) {
|
||||
}
|
||||
|
||||
utils.prototype._decodeRoute_decodeOne = function (decodeObj, c) {
|
||||
// --- 特殊处理自定义项
|
||||
if (c == '(') {
|
||||
var idx = decodeObj.route.indexOf(')', decodeObj.index);
|
||||
if (idx >= 0) {
|
||||
decodeObj.ans.push(decodeObj.route.substring(decodeObj.index, idx));
|
||||
decodeObj.index = idx + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
var nxt = (c == 'I' || c == 'e' || c == 'F' || c == 'S' || c == 'Q' || c == 't') ?
|
||||
this._decodeRoute_getString(decodeObj) : this._decodeRoute_getNumber(decodeObj);
|
||||
|
||||
@ -618,6 +599,7 @@ utils.prototype.getCookie = function (name) {
|
||||
|
||||
////// 设置statusBar的innerHTML,会自动斜体和放缩,也可以增加自定义css //////
|
||||
utils.prototype.setStatusBarInnerHTML = function (name, value, css) {
|
||||
if (!core.statusBar[name]) return;
|
||||
if (typeof value == 'number') value = this.formatBigNumber(value);
|
||||
// 判定是否斜体
|
||||
var italic = /^[-a-zA-Z0-9`~!@#$%^&*()_=+\[{\]}\\|;:'",<.>\/?]*$/.test(value);
|
||||
@ -921,7 +903,7 @@ utils.prototype.myprompt = function (hint, value, callback) {
|
||||
}
|
||||
|
||||
////// 动画显示某对象 //////
|
||||
utils.prototype.show = function (obj, speed, callback) {
|
||||
utils.prototype.showWithAnimate = function (obj, speed, callback) {
|
||||
obj.style.display = 'block';
|
||||
if (!speed && main.mode != 'play') {
|
||||
obj.style.opacity = 1;
|
||||
@ -941,7 +923,7 @@ utils.prototype.show = function (obj, speed, callback) {
|
||||
}
|
||||
|
||||
////// 动画使某对象消失 //////
|
||||
utils.prototype.hide = function (obj, speed, callback) {
|
||||
utils.prototype.hideWithAnimate = function (obj, speed, callback) {
|
||||
if (!speed || main.mode != 'play') {
|
||||
obj.style.display = 'none';
|
||||
if (callback) callback();
|
||||
@ -960,7 +942,7 @@ utils.prototype.hide = function (obj, speed, callback) {
|
||||
}, speed);
|
||||
}
|
||||
|
||||
utils.prototype.encodeCanvas = function (ctx) {
|
||||
utils.prototype._encodeCanvas = function (ctx) {
|
||||
var list = [];
|
||||
var width = ctx.canvas.width, height = ctx.canvas.height;
|
||||
ctx.mozImageSmoothingEnabled = false;
|
||||
@ -987,7 +969,7 @@ utils.prototype.encodeCanvas = function (ctx) {
|
||||
}
|
||||
|
||||
////// 解析arr数组,并绘制到tempCanvas上 //////
|
||||
utils.prototype.decodeCanvas = function (arr, width, height) {
|
||||
utils.prototype._decodeCanvas = function (arr, width, height) {
|
||||
// 清空tempCanvas
|
||||
var tempCanvas = core.bigmap.tempCanvas;
|
||||
tempCanvas.canvas.width = width;
|
||||
@ -1070,7 +1052,7 @@ utils.prototype._export = function (floorIds) {
|
||||
// map
|
||||
var content = floorIds.length + "\n" + core.__SIZE__ + " " + core.__SIZE__ + "\n\n";
|
||||
floorIds.forEach(function (floorId) {
|
||||
var arr = core.maps.getMapArray(core.status.maps[floorId].blocks);
|
||||
var arr = core.maps._getMapArrayFromBlocks(core.status.maps[floorId].blocks);
|
||||
content += arr.map(function (x) {
|
||||
// check monster
|
||||
x.forEach(function (t) {
|
||||
|
||||
8
main.js
8
main.js
@ -364,7 +364,7 @@ main.dom.body.onselectstart = function () {
|
||||
main.dom.data.onmousedown = function (e) {
|
||||
try {
|
||||
e.stopPropagation();
|
||||
var loc = main.core.getClickLoc(e.clientX, e.clientY);
|
||||
var loc = main.core.actions._getClickLoc(e.clientX, e.clientY);
|
||||
if (loc == null) return;
|
||||
main.core.ondown(loc);
|
||||
} catch (ee) { main.log(ee); }
|
||||
@ -374,7 +374,7 @@ main.dom.data.onmousedown = function (e) {
|
||||
main.dom.data.onmousemove = function (e) {
|
||||
try {
|
||||
e.stopPropagation();
|
||||
var loc = main.core.getClickLoc(e.clientX, e.clientY);
|
||||
var loc = main.core.actions._getClickLoc(e.clientX, e.clientY);
|
||||
if (loc == null) return;
|
||||
main.core.onmove(loc);
|
||||
}catch (ee) { main.log(ee); }
|
||||
@ -401,7 +401,7 @@ main.dom.data.onmousewheel = function(e) {
|
||||
main.dom.data.ontouchstart = function (e) {
|
||||
try {
|
||||
e.preventDefault();
|
||||
var loc = main.core.getClickLoc(e.targetTouches[0].clientX, e.targetTouches[0].clientY);
|
||||
var loc = main.core.actions._getClickLoc(e.targetTouches[0].clientX, e.targetTouches[0].clientY);
|
||||
if (loc == null) return;
|
||||
main.core.ondown(loc);
|
||||
}catch (ee) { main.log(ee); }
|
||||
@ -411,7 +411,7 @@ main.dom.data.ontouchstart = function (e) {
|
||||
main.dom.data.ontouchmove = function (e) {
|
||||
try {
|
||||
e.preventDefault();
|
||||
var loc = main.core.getClickLoc(e.targetTouches[0].clientX, e.targetTouches[0].clientY);
|
||||
var loc = main.core.actions._getClickLoc(e.targetTouches[0].clientX, e.targetTouches[0].clientY);
|
||||
if (loc == null) return;
|
||||
main.core.onmove(loc);
|
||||
}catch (ee) { main.log(ee); }
|
||||
|
||||
@ -78,6 +78,7 @@ var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d =
|
||||
"lv": 1,
|
||||
"hpmax": 9999,
|
||||
"hp": 1000,
|
||||
"manamax": -1,
|
||||
"mana": 0,
|
||||
"atk": 100,
|
||||
"def": 100,
|
||||
|
||||
@ -223,7 +223,7 @@ var events_c12a15a8_c380_4b28_8144_256cba95f760 =
|
||||
},
|
||||
{
|
||||
"type": "if",
|
||||
"condition": "core.getBgFgNumber('bg') == 167",
|
||||
"condition": "core.getBgNumber() == 167",
|
||||
"true": [
|
||||
{
|
||||
"type": "function",
|
||||
|
||||
@ -151,7 +151,7 @@ main.floors.sample1=
|
||||
"type": "hide"
|
||||
},
|
||||
{
|
||||
"type": "setFg",
|
||||
"type": "setCurtain",
|
||||
"color": [
|
||||
0,
|
||||
0,
|
||||
@ -184,7 +184,7 @@ main.floors.sample1=
|
||||
"2,11": [
|
||||
"\t[杰克,thief]喂!醒醒!快醒醒!",
|
||||
{
|
||||
"type": "setFg",
|
||||
"type": "setCurtain",
|
||||
"time": 1500
|
||||
},
|
||||
"\t[hero]额,我这是在什么地方?",
|
||||
|
||||
@ -6,6 +6,7 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
// hero:勇士信息;hard:难度;floorId:当前楼层ID;maps:地图信息;values:全局数值信息
|
||||
|
||||
// 清除游戏数据
|
||||
// 这一步会清空状态栏和全部画布内容,并删除所有动态创建的画布
|
||||
core.clearStatus();
|
||||
// 初始化status
|
||||
core.status = core.clone(core.initStatus);
|
||||
@ -753,152 +754,156 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
// keyCode:当前按键的keyCode(每个键的keyCode自行百度)
|
||||
// altKey:Alt键是否被按下,为true代表同时按下了Alt键
|
||||
// 可以在这里任意增加或编辑每个按键的行为
|
||||
|
||||
|
||||
// 如果处于正在行走状态,则不处理
|
||||
if (!core.status.heroStop || core.status.heroMoving > 0)
|
||||
if (core.isMoving())
|
||||
return;
|
||||
|
||||
// Alt+0~9,快捷换上套装
|
||||
if (altKey && keyCode>=48 && keyCode<=57) {
|
||||
core.items.quickLoadEquip(keyCode-48);
|
||||
if (altKey && keyCode >= 48 && keyCode <= 57) {
|
||||
core.items.quickLoadEquip(keyCode - 48);
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据keyCode值来执行对应操作
|
||||
switch (keyCode) {
|
||||
case 27: // ESC:打开菜单栏
|
||||
core.openSettings(true);
|
||||
break;
|
||||
case 88: // X:使用怪物手册
|
||||
core.openBook(true);
|
||||
break;
|
||||
case 71: // G:使用楼传器
|
||||
core.useFly(true);
|
||||
break;
|
||||
case 65: // A:读取自动存档(回退)
|
||||
core.doSL("autoSave", "load");
|
||||
break;
|
||||
case 83: // S:存档
|
||||
core.save(true);
|
||||
break;
|
||||
case 68: // D:读档
|
||||
core.load(true);
|
||||
break;
|
||||
case 69: // E:打开光标
|
||||
core.ui.drawCursor();
|
||||
break;
|
||||
case 84: // T:打开道具栏
|
||||
core.openToolbox(true);
|
||||
break;
|
||||
case 81: // Q:打开装备栏
|
||||
core.openEquipbox(true);
|
||||
break;
|
||||
case 90: // Z:转向
|
||||
core.turnHero();
|
||||
break;
|
||||
case 75: case 86: // V:打开快捷商店列表
|
||||
core.openQuickShop(true);
|
||||
break;
|
||||
case 32: // SPACE:轻按
|
||||
core.getNextItem();
|
||||
break;
|
||||
case 82: // R:回放录像
|
||||
core.actions._clickSyncSave_replay();
|
||||
break;
|
||||
case 33: case 34: // PgUp/PgDn:浏览地图
|
||||
core.ui.drawMaps();
|
||||
break;
|
||||
case 77: // M:绘图模式
|
||||
core.ui.drawPaint();
|
||||
break;
|
||||
case 66: // B:打开数据统计
|
||||
core.ui.drawStatistics();
|
||||
break;
|
||||
case 72: // H:打开帮助页面
|
||||
core.ui.drawHelp();
|
||||
break;
|
||||
case 78: // N:重新开始
|
||||
core.confirmRestart();
|
||||
break;
|
||||
case 79: // O:查看工程
|
||||
core.actions._clickGameInfo_openProject();
|
||||
break;
|
||||
case 80: // P:游戏主页
|
||||
core.actions._clickGameInfo_openComments();
|
||||
break;
|
||||
case 49: // 快捷键1: 破
|
||||
if (core.hasItem('pickaxe')) {
|
||||
if (core.canUseItem('pickaxe')) {
|
||||
core.useItem('pickaxe');
|
||||
}
|
||||
else {
|
||||
core.drawTip('当前不能使用破墙镐');
|
||||
}
|
||||
case 27: // ESC:打开菜单栏
|
||||
core.openSettings(true);
|
||||
break;
|
||||
case 88: // X:使用怪物手册
|
||||
core.openBook(true);
|
||||
break;
|
||||
case 71: // G:使用楼传器
|
||||
core.useFly(true);
|
||||
break;
|
||||
case 65: // A:读取自动存档(回退)
|
||||
core.doSL("autoSave", "load");
|
||||
break;
|
||||
case 83: // S:存档
|
||||
core.save(true);
|
||||
break;
|
||||
case 68: // D:读档
|
||||
core.load(true);
|
||||
break;
|
||||
case 69: // E:打开光标
|
||||
core.ui.drawCursor();
|
||||
break;
|
||||
case 84: // T:打开道具栏
|
||||
core.openToolbox(true);
|
||||
break;
|
||||
case 81: // Q:打开装备栏
|
||||
core.openEquipbox(true);
|
||||
break;
|
||||
case 90: // Z:转向
|
||||
core.turnHero();
|
||||
break;
|
||||
case 75:
|
||||
case 86: // V:打开快捷商店列表
|
||||
core.openQuickShop(true);
|
||||
break;
|
||||
case 32: // SPACE:轻按
|
||||
core.getNextItem();
|
||||
break;
|
||||
case 82: // R:回放录像
|
||||
core.actions._clickSyncSave_replay();
|
||||
break;
|
||||
case 33:
|
||||
case 34: // PgUp/PgDn:浏览地图
|
||||
core.ui.drawMaps();
|
||||
break;
|
||||
case 77: // M:绘图模式
|
||||
core.ui.drawPaint();
|
||||
break;
|
||||
case 66: // B:打开数据统计
|
||||
core.ui.drawStatistics();
|
||||
break;
|
||||
case 72: // H:打开帮助页面
|
||||
core.ui.drawHelp();
|
||||
break;
|
||||
case 78: // N:重新开始
|
||||
core.confirmRestart();
|
||||
break;
|
||||
case 79: // O:查看工程
|
||||
core.actions._clickGameInfo_openProject();
|
||||
break;
|
||||
case 80: // P:游戏主页
|
||||
core.actions._clickGameInfo_openComments();
|
||||
break;
|
||||
case 49: // 快捷键1: 破
|
||||
if (core.hasItem('pickaxe')) {
|
||||
if (core.canUseItem('pickaxe')) {
|
||||
core.status.route.push("key:49"); // 将按键记在录像中
|
||||
core.useItem('pickaxe', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像
|
||||
} else {
|
||||
core.drawTip('当前不能使用破墙镐');
|
||||
}
|
||||
break;
|
||||
case 50: // 快捷键2: 炸
|
||||
if (core.hasItem('bomb')) {
|
||||
if (core.canUseItem('bomb')) {
|
||||
core.useItem('bomb');
|
||||
}
|
||||
else {
|
||||
core.drawTip('当前不能使用炸弹');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 50: // 快捷键2: 炸
|
||||
if (core.hasItem('bomb')) {
|
||||
if (core.canUseItem('bomb')) {
|
||||
core.status.route.push("key:50"); // 将按键记在录像中
|
||||
core.useItem('bomb', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像
|
||||
} else {
|
||||
core.drawTip('当前不能使用炸弹');
|
||||
}
|
||||
else if (core.hasItem('hammer')) {
|
||||
if (core.canUseItem('hammer')) {
|
||||
core.useItem('hammer');
|
||||
}
|
||||
else {
|
||||
core.drawTip('当前不能使用圣锤');
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 51: // 快捷键3: 飞
|
||||
if (core.hasItem('centerFly')) {
|
||||
core.ui.drawCenterFly();
|
||||
}
|
||||
break;
|
||||
case 52: // 快捷键4:破冰/冰冻/地震/上下楼器/... 其他道具依次判断
|
||||
{
|
||||
var list = ["icePickaxe", "snow", "earthquake", "upFly", "downFly", "jumpShoes", "lifeWand", "poisonWine", "weakWine", "curseWine", "superWine"];
|
||||
for (var i=0;i<list.length;i++) {
|
||||
var itemId = list[i];
|
||||
if (core.canUseItem(itemId)) {
|
||||
core.useItem(itemId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 55: // 快捷键7:绑定为轻按,方便手机版操作
|
||||
core.getNextItem();
|
||||
break;
|
||||
case 118: // F7:开启debug模式
|
||||
core.debug();
|
||||
break;
|
||||
case 87: // W:开启技能“二倍斩”
|
||||
// 检测是否拥有“二倍斩”这个技能道具
|
||||
if (core.hasItem('skill1')) {
|
||||
core.useItem('skill1');
|
||||
}
|
||||
break;
|
||||
// 在这里可以任意新增或编辑已有的快捷键内容
|
||||
/*
|
||||
case 0: // 使用该按键的keyCode
|
||||
// 还可以再判定altKey是否被按下,即 if (altKey) { ...
|
||||
|
||||
// ... 在这里写你要执行脚本
|
||||
// **强烈建议所有新增的自定义快捷键均能给个对应的道具可点击,以方便手机端的行为**
|
||||
if (core.hasItem('...')) {
|
||||
core.useItem('...');
|
||||
} else if (core.hasItem('hammer')) {
|
||||
if (core.canUseItem('hammer')) {
|
||||
core.status.route.push("key:50"); // 将按键记在录像中
|
||||
core.useItem('hammer', true); // 第二个参数true代表该次使用道具是被按键触发的,使用过程不计入录像
|
||||
} else {
|
||||
core.drawTip('当前不能使用圣锤');
|
||||
}
|
||||
|
||||
break;
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 51: // 快捷键3: 飞
|
||||
if (core.hasItem('centerFly')) {
|
||||
core.ui.drawCenterFly();
|
||||
}
|
||||
break;
|
||||
case 52: // 快捷键4:破冰/冰冻/地震/上下楼器/... 其他道具依次判断
|
||||
{
|
||||
var list = ["icePickaxe", "snow", "earthquake", "upFly", "downFly", "jumpShoes", "lifeWand", "poisonWine", "weakWine", "curseWine", "superWine"];
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var itemId = list[i];
|
||||
if (core.canUseItem(itemId)) {
|
||||
core.status.route.push("key:52");
|
||||
core.useItem(itemId, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 55: // 快捷键7:绑定为轻按,方便手机版操作
|
||||
core.getNextItem();
|
||||
break;
|
||||
case 118: // F7:开启debug模式
|
||||
core.debug();
|
||||
break;
|
||||
case 87: // W:开启技能“二倍斩”
|
||||
// 检测是否拥有“二倍斩”这个技能道具
|
||||
if (core.hasItem('skill1')) {
|
||||
core.status.route.push("key:87");
|
||||
core.useItem('skill1', true);
|
||||
}
|
||||
break;
|
||||
// 在这里可以任意新增或编辑已有的快捷键内容
|
||||
/*
|
||||
case 0: // 使用该按键的keyCode
|
||||
// 还可以再判定altKey是否被按下,即 if (altKey) { ...
|
||||
|
||||
// ... 在这里写你要执行脚本
|
||||
// **强烈建议所有新增的自定义快捷键均能给个对应的道具可点击,以方便手机端的行为**
|
||||
if (core.hasItem('...')) {
|
||||
core.status.route.push("key:0");
|
||||
core.useItem('...', true); // 增加true代表该使用道具不计入录像
|
||||
}
|
||||
|
||||
break;
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
"control": {
|
||||
@ -1006,9 +1011,14 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a =
|
||||
|
||||
// 设置魔力值
|
||||
if (core.flags.enableMana) {
|
||||
// 也可以使用flag:manaMax来表示最大魔力值;详见文档-个性化-技能塔的支持
|
||||
// core.status.hero.mana = Math.max(core.status.hero.mana, core.getFlag('manaMax', 10));
|
||||
// core.setStatusBarInnerHTML('mana', core.status.hero.mana + "/" + core.getFlag('manaMax', 10));
|
||||
// status:manamax 只有在非负时才生效。
|
||||
if (core.status.hero.manamax != null && core.status.hero.manamax >= 0) {
|
||||
core.status.hero.mana = Math.min(core.status.hero.mana, core.status.hero.manamax);
|
||||
core.setStatusBarInnerHTML('mana', core.status.hero.mana + "/" + core.status.hero.manamax);
|
||||
}
|
||||
else {
|
||||
core.setStatusBarInnerHTML("mana", core.status.hero.mana);
|
||||
}
|
||||
}
|
||||
// 设置技能栏
|
||||
if (core.flags.enableSkill) {
|
||||
|
||||
@ -1,18 +1,28 @@
|
||||
var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
||||
{
|
||||
"init": function () {
|
||||
// 在这里写的代码,在所有模块加载完毕后,游戏开始前会被执行
|
||||
|
||||
console.log("插件编写测试");
|
||||
|
||||
// 可以写一些其他的被直接执行的代码
|
||||
// 可以写一些直接执行的代码
|
||||
// 在这里写的代码将会在【资源加载前】被执行,此时图片等资源尚未被加载。
|
||||
// 请勿在这里对包括bgm,图片等资源进行操作。
|
||||
|
||||
|
||||
this.test = function () {
|
||||
console.log("插件函数执行测试");
|
||||
console.log(this);
|
||||
this._afterLoadResources = function () {
|
||||
// 本函数将在所有资源加载完毕后,游戏开启前被执行
|
||||
// 可以在这个函数里面对资源进行一些操作,比如切分图片等。
|
||||
|
||||
// 这是一个将assets.png拆分成若干个32x32像素的小图片并保存的样例。
|
||||
// var arr = core.splitImage("assets.png", 32, 32);
|
||||
// for (var i = 0; i < arr.length; i++) {
|
||||
// core.material.images.images["asset"+i+".png"] = arr[i];
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
// 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx();
|
||||
// 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx();
|
||||
// 从V2.6开始,插件中用this.XXX方式定义的函数也会被转发到core中,详见文档-脚本-函数的转发。
|
||||
},
|
||||
"drawLight": function () {
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user