diff --git a/README.md b/README.md index 17ab6be6..cf3d90bf 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! * [Docs / 使用文档说明](https://ckcz123.github.io/mota-js/) * [Video / 视频教程](https://www.bilibili.com/video/av32781473/) -![样板](./_docs/img/sample0.png) +![样板](./_docs/img/sample0.jpg) ## 目录结构 diff --git a/_docs/_api.md b/_docs/_api.md deleted file mode 100644 index 31880e51..00000000 --- a/_docs/_api.md +++ /dev/null @@ -1,685 +0,0 @@ -# 附录: 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, exp等等。 -本句等价于 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, prefix, need, times) -将一段文字中的${}进行计算并替换。 - - -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.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.removeBlockByIndexes(index, floorId) -根据索引删除或禁用某块。 - - -core.maps.removeBlockByIndexes(indexes, floorId) -根据索引删除或禁用若干块。 - - -core.maps.drawAnimate(name, x, y, alignWindow, 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为失败后的回调。 - -``` diff --git a/_docs/api.md b/_docs/api.md index 78f7c55e..e8e7d48d 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -1,6 +1,6 @@ # 附录:API列表 -?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} * +?> 样板全部的API列表都在这里了! 这里将列出所有被转发到core的API,没有被转发的函数此处不会列出,请自行在代码中查看。 @@ -14,8 +14,8 @@ core.js中只有很少的几个函数,主要是游戏开始前的初始化等 但是,core中定义了很多游戏运行时的状态,这些状态很多都会被使用到。 -``` text -core.__SIZE__, core.__PIXELS__ +```text +core.__SIZE__, core.__PIXELS__ 游戏窗口大小;对于13x13的游戏而言这两个值分别是13和416,15x15来说分别是15和480。 @@ -171,91 +171,58 @@ core.doFunc(func, _this) actions.js主要是处理一些和用户交互相关的内容。 ```text -core.registerAction(action, name, func, priority) -注册一个用户交互行为。 -action:要注册的交互类型,如 ondown, onclick, keyDown 等等。 -name:你的自定义名称,可被注销使用;同名重复注册将后者覆盖前者。 -func:执行函数;可以是一个具体的函数体,或者是一个插件中的函数名。 -priority:优先级;优先级高的被注册项将会被执行。此项可不填,默认为0。 -返回:如果func返回true,则不会再继续执行其他的交互函数;否则会继续执行其他的交互函数。 +onup: fn(loc: {x: number, y: number, size: number}) +当点击(触摸)事件放开时 +pressKey: fn(keyCode: number) +按住某个键时 -core.unregisterAction(action, name) -注销一个用户交互行为。 +keyUp: fn(keyCode: number, altKey?: bool, fromReplay?: bool) +根据放开键的code来执行一系列操作 +ondown: fn(loc: {x: number, y: number, size: number}) +点击(触摸)事件按下时 -core.doRegisteredAction(action) -执行一个用户交互行为。 -此函数将在该交互行为所注册的所有函数中,按照优先级从高到底依次执行。 -此函数剩余的参数将会作为参数传入该执行函数中。 -当某个执行函数返回true时将终止这一过程。 +registerAction: fn(action: string, name: string, func: string|fn(params: ?), priority?: number) +此函数将注册一个用户交互行为。 +action: 要注册的交互类型,如 ondown, onclick, keyDown 等等。 +name: 你的自定义名称,可被注销使用;同名重复注册将后者覆盖前者。 +func: 执行函数。 +如果func返回true,则不会再继续执行其他的交互函数;否则会继续执行其他的交互函数。 +priority: 优先级;优先级高的将会被执行。此项可不填,默认为0 +onkeyDown: fn(e: Event) +按下某个键时 -core.onkeyDown(e) -当按下某个键时的操作,e为KeyboardEvent。 -请勿直接覆盖或调用此函数,如有需要请注册一个"onkeyDown"的交互函数。 +keyDown: fn(keyCode: number) +根据按下键的code来执行一系列操作 +onStatusBarClick: fn(e?: Event) +点击自绘状态栏时 -core.onkeyUp(e) -当放开某个键时的操作,e为KeyboardEvent。 -请勿直接覆盖或调用此函数,如有需要请注册一个"onkeyUp"的交互函数。 +longClick: fn(x: number, y: number, fromEvent?: bool) +长按 +unregisterAction: fn(action: string, name: string) +注销一个用户交互行为 -core.pressKey(keyCode) -当按住某个键不动时的操作,目前只对方向键有效。 -如果需要添加对于其他键的长按,请复写_sys_onkeyDown和_sys_onkeyUp。 -请勿直接覆盖或调用此函数,如有需要请注册一个"pressKey"的交互函数。 +keyDownCtrl: fn() -> bool +长按Ctrl键时 +onclick: fn(x: number, y: number, stepPostfix?: ?) +具体点击屏幕上(x,y)点时,执行的操作 -core.keyDown(keyCode) -当按下某个键时的操作,参数为该键的keyCode值。 -请勿直接覆盖或调用此函数,如有需要请注册一个"keyDown"的交互函数。 +doRegisteredAction: fn(action: string, params: ?) +执行一个用户交互行为 +onkeyUp: fn(e: Event) +放开某个键时 -core.keyUp(keyCode, altKey, fromReplay) -当按下某个键时的操作,参数为该键的keyCode值。 -altKey标志了Alt键是否同时被按下,fromReplay表示是否是从录像回放中调用的。 -请勿直接覆盖或调用此函数,如有需要请注册一个"keyUp"的交互函数。 +onmousewheel: fn(direct: number) +滑动鼠标滚轮时的操作 - -core.ondown(loc) -当点击屏幕时的操作。loc为点击的信息。 -请勿直接覆盖或调用此函数,如有需要请注册一个"ondown"的交互函数。 -注册的ondown交互函数需要接受x, y, px, py四个参数,代表点击的位置和像素坐标。 - - -core.onmove(loc) -当在屏幕上滑动时的操作。loc为当前的坐标信息。 -请勿直接覆盖或调用此函数,如有需要请注册一个"onmove"的交互函数。 -注册的onmove交互函数需要接受x, y, px, py四个参数,代表当前的的位置和像素坐标。 - - -core.onup() -当从屏幕上离开时的操作。请注意此函数是没有参数的。 -请勿直接覆盖或调用此函数,如有需要请注册一个"onup"的交互函数。 - - -core.onclick(x, y) -当点击屏幕上的某点位置时执行的操作,请注意这里的x和y是位置坐标。 -一般而言,一个完整的ondown到onup将触发一个onclick事件。 -请勿直接覆盖或调用此函数,如有需要请注册一个"onclick"的交互函数。 - - -core.onmousewheel(direct) -当滚动鼠标滑轮时执行的操作。direct为滑轮方向,上为1,下为-1。 -请勿直接覆盖或调用此函数,如有需要请注册一个"onmousewheel"的交互函数。 - - -core.keyDownCtrl() -当长按Ctrl键不动时执行的操作。 -请勿直接覆盖或调用此函数,如有需要请注册一个"keyDownCtrl"的交互函数。 - - -core.longClick() -当长按住屏幕时执行的操作。 -请勿直接覆盖或调用此函数,如有需要请注册一个"keyDownCtrl"的交互函数。 -注册的交互函数如果某一项返回true,则之后仍然会继续触发该长按, -如果全部返回false则将停止本次长按行为,直到手指离开屏幕并重新进行长按为止。 +onmove: fn(loc: {x: number, y: number, size: number}) +当在触摸屏上滑动时 ``` ## control.js @@ -273,436 +240,452 @@ control.js将负责整个游戏的核心控制系统,分为如下几个部分 - 界面resize相关 ```text -// ------ requestAnimationFrame 相关 ------ // +showStatusBar: fn() +显示状态栏 + +startReplay: fn(list: [string]) +开始播放录像 + +triggerReplay: fn() +播放或暂停录像回放 + +screenFlash: fn(color: [number], time: number, times?: number, callback?: fn()) +画面闪烁 +例如:core.screenFlash([255, 0, 0, 1], 3); // 红屏一闪而过 +color: 一行三列(第四列视为1)或一行四列(第四列若大于1则会被视为1,第四列若填负数则会被视为0)的颜色数组,必填 +time: 单次闪烁时长,实际闪烁效果为先花其三分之一的时间渐变到目标色调,再花剩余三分之二的时间渐变回去 +times: 闪烁的总次数,不填或填0都视为1 +callback: 闪烁全部完毕后的回调函数,可选 + +setCurtain: fn(color?: [number], time?: number, callback?: fn()) +更改画面色调,不计入存档。如需长期生效请使用core.events._action_setCurtain()函数 +例如:core.setCurtain(); // 恢复画面色调,用时四分之三秒 +color: 一行三列(第四列视为1)或一行四列(第四列若大于1则会被视为1,第四列若为负数则会被视为0)的颜色数组,不填视为[0, 0, 0, 0] +time: 渐变时间,单位为毫秒。不填视为750ms,负数视为0(无渐变,立即更改) +callback: 更改完毕后的回调函数,可选。事件流中常取core.doAction + +updateDamage: fn(floorId?: string, ctx?: string|CanvasRenderingContext2D) +更新地图显伤 +例如:core.updateDamage(); // 更新当前地图的显伤,绘制在显伤层(废话) +floorId: 地图id,不填视为当前地图。预览地图时填写 +ctx: 绘制到的画布,如果填写了就会画在该画布而不是显伤层 + +nextX: fn(n?: number) -> number +获取主角面前第n格的横坐标 +例如:core.closeDoor(core.nextX(), core.nextY(), 'yellowDoor', core.turnHero); // 在主角面前关上一扇黄门,然后主角顺时针旋转90° +n: 目标格与主角的距离,面前为正数,背后为负数,脚下为0,不填视为1 + +nextY: fn(n?: number) -> number +获取主角面前第n格的纵坐标 +例如:core.jumpHero(core.nextX(2), core.nextY(2)); // 主角向前跃过一格,即跳跃靴道具的使用效果 +n: 目标格与主角的距离,面前为正数,背后为负数,脚下为0,不填视为1 + +clearContinueAutomaticRoute: fn(callback?: fn()) +清空剩下的自动寻路列表 + +updateViewport: fn() +更新大地图的可见区域 + +getMappedName: fn(name: string) -> string +获得映射文件名 + +addFlag: fn(name: string, value: number) +增减一个flag变量,等价于 core.setFlag(name, core.getFlag(name, 0) + value) +例如:core.addFlag('hatred', 1); // 增加1点仇恨值 +name: 变量名,支持中文 +value: 变量的增量 + +setFlag: fn(name: string, value: ?) +设置一个flag变量 +例如:core.setFlag('poison', true); // 令主角中毒 +name: 变量名,支持中文 +value: 变量的新值,不填或填null视为删除 + +viewMapReplay: fn() +回放录像时浏览地图 + +playSound: fn(sound: string) +播放一个音效 + +stopSound: fn() +停止所有SE + +addGameCanvasTranslate: fn(x?: number, y?: number) +加减画布偏移 + +addBuff: fn(name: string, value: number) +增减主角某个属性的百分比修正倍率,加减法叠加和抵消。等价于 core.setBuff(name, core.getBuff(name) + value) +例如:core.addBuff('atk', -0.1); // 主角获得一层“攻击力减一成”的负面效果 +name: 属性的英文名,请注意只能用于数值类属性哦,否则随后的乘法会得到NaN +value: 倍率的增量 + +drawHero: fn(status?: string, offset?: number, frame?: number) +绘制主角和跟随者并重置视野到以主角为中心 +例如:core.drawHero(); // 原地绘制主角的静止帧并重置视野野 +status: 只能为 stop, leftFoot 和 rightFoot,不填用stop。 +offset: 相对主角逻辑位置的偏移量,不填视为无偏移。 +frame: 绘制的第几帧 + +pauseBgm: fn() +暂停背景音乐的播放 + +setReplaySpeed: fn(speed: number) +设置播放速度 + +pauseReplay: fn() +暂停播放 + +doSL: fn(id?: string, type?: string) +实际进行存读档事件 + +setStatus: fn(name: string, value: number) +设置主角的某个属性 +例如:core.setStatus('atk', 100); // 设置攻击力为100 +name: 属性的英文名,其中'x'、'y'和'direction'会被特殊处理为 core.setHeroLoc(name, value),其他的会直接对 core.status.hero[name] 赋值 +value: 属性的新值 + +setAutomaticRoute: fn(destX: number, destY: number, stepPostfix: [{x: number, y: number, direction: string}]) +半自动寻路,用于鼠标或手指拖动 +例如:core.setAutomaticRoute(0, 0, [{direction: "right", x: 4, y: 9}, {direction: "right", x: 5, y: 9}]); +destX: 鼠标或手指的起拖点横坐标 +destY: 鼠标或手指的起拖点纵坐标 +stepPostfix: 拖动轨迹的数组表示,每项为一步的方向和目标点。 + +triggerHero: fn(type?: string, time?: number, callback?: fn()) +改变勇士的显隐状态 + +gatherFollowers: fn() +立刻聚集所有的跟随者 + +getStatus: fn(name: string) -> number +读取主角的某个属性,不包括百分比修正 +例如:core.getStatus('atk'); // 读取主角的攻击力 +name: 属性的英文名,其中'x'、'y'和'direction'会被特殊处理为 core.getHeroLoc(name),其他的会直接读取 core.status.hero[name] + +setHeroLoc: fn(name: string, value: string|number, noGather?: bool) +设置勇士位置 +值得注意的是,这句话虽然会使勇士改变位置,但并不会使界面重新绘制; +如需立刻重新绘制地图还需调用:core.clearMap('hero'); core.drawHero(); 来对界面进行更新。 +例如:core.setHeroLoc('x', 5) // 将勇士当前位置的横坐标设置为5。 +name: 要设置的坐标属性 +value: 新值 +noGather: 是否聚集跟随者 + +getLvName: fn(lv?: number) -> string|number +根据级别的数字获取对应的名称,后者定义在全塔属性 +例如:core.getLvName(); // 获取主角当前级别的名称,如“下级佣兵” +lv: 级别的数字,不填则视为主角当前的级别 +返回值:级别的名称,如果不存在就还是返回数字 -core.registerAnimationFrame(name, needPlaying, func) -注册一个animationFrame。它将在每次浏览器的帧刷新时(约16.6ms)被执行。 -name:你的自定义名称,可被注销使用;同名重复注册将后者覆盖前者。 -needPlaying:如果此项为true,则仅在游戏开始后才会被执行(标题界面不执行) -func:执行函数;可以是一个具体的函数体,或者是一个插件中的函数名。 -func可以接受一个timestamp作为参数,表示从整个页面加载完毕到当前时刻所经过的毫秒数。 -如果func执行报错,将在控制台打出一条信息,并自动进行注销。 +addStatus: fn(name: string, value: number) +增减主角的某个属性,等价于core.setStatus(name, core.getStatus(name) + value) +例如:core.addStatus('atk', 100'); // 给主角攻击力加100 +name: 属性的英文名 +value: 属性的增量 +speedUpReplay: fn() +加速播放 -core.unregisterAnimationFrame(name) -注销一个animationFrame,参数是你的上面的自定义名称。 +loadData: fn(data?: ?, callback?: fn()) +从本地读档 -// ------ 开始界面相关 ------ // +debug: fn() +开启调试模式, 此模式下可以按Ctrl键进行穿墙, 并忽略一切事件。 +此模式下不可回放录像和上传成绩。 -core.showStartAnimate(noAnimate, callback) -重置所有内容并显示游戏标题界面。 -noAnimate如果为true则不会有淡入动画,callback为执行完毕的回调。 +moveOneStep: fn(callback?: fn()) +每移动一格后执行的事件 +clearStatus: fn() +清除游戏状态和数据 -core.hideStartAnimate(callback) -淡出隐藏游戏标题界面,callback为执行完毕的回调。 +updateFollowers: fn() +更新跟随者坐标 +waitHeroToStop: fn(callback?: fn()) +等待主角停下 +例如:core.waitHeroToStop(core.vibrate); // 等待主角停下,然后视野左右抖动1秒 +callback: 主角停止后的回调函数 -core.isPlaying() -当前是否正在游戏中。 +hideStatusBar: fn(showToolbox?: bool) +隐藏状态栏 +showToolbox: 是否不隐藏竖屏工具栏 + +getBuff: fn(name: string) -> number +读取主角某个属性的百分比修正倍率,初始值为1 +例如:core.getBuff('atk'); // 主角当前能发挥出多大比例的攻击力 +name: 属性的英文名 + +setToolbarButton: fn(useButton?: bool) +改变工具栏为按钮1-8 +getSaves: fn(ids?: ?, callback?: fn()) +获得某些存档内容 -core.clearStatus() -清除所有的游戏状态和数据,包括状态栏的显示。 +replay: fn() +回放下一个操作 -// ------ 自动寻路、人物行走 ------ // +getStatusOrDefault: fn(status?: ?, name?: string) +从status中获得属性,如果不存在则从勇士属性中获取 -core.stopAutomaticRoute() -停止自动寻路的操作 +unregisterReplayAction: fn(name: string) +注销一个录像行为 +setBuff: fn(name: string, value: number) +设置主角某个属性的百分比修正倍率,初始值为1, +倍率存放在flag: '__'+name+'_buff__' 中 +例如:core.setBuff('atk', 0.5); // 主角能发挥出的攻击力减半 +name: 属性的英文名,请注意只能用于数值类属性哦,否则随后的乘法会得到NaN +value: 新的百分比修正倍率,不填(效果上)视为1 -core.saveAndStopAutomaticRoute() -保存剩下的寻路路线并停止自动寻路操作。主要用于打怪开门后继续寻路使用。 +continueAutomaticRoute: fn() +继续剩下的自动寻路操作 + +saveReplay: fn() +回放时存档 +setAutoHeroMove: fn(steps: [?]) +连续行走 +例如:core.setAutoHeroMove([{direction: "up", step: 1}, {direction: "left", step: 3}]); // 上左左左 +steps: 压缩的步伐数组,每项表示朝某方向走多少步 -core.continueAutomaticRoute() -继续剩下的自动寻路操作。主要用于打怪开门后继续寻路使用。 +fillPosWithPoint: fn(pos?: ?) +显示离散的寻路点 +unregisterResize: fn(name: string) +注销一个resize函数 -core.clearContinueAutomaticRoute() -清空剩下的自动寻路操作。 +saveAndStopAutomaticRoute: fn() +保存剩下的寻路,并停止 +hideStartAnimate: fn(callback?: fn()) +淡出标题画面 +例如:core.hideStartAnimate(core.startGame); // 淡出标题画面并开始新游戏,跳过难度选择 +callback: 标题画面完全淡出后的回调函数 -core.setAutomaticRoute(destX, destY, stepPostfix) -尝试开始进行一个自动寻路。stepPostfix是鼠标拖动的路径。 -此函数将检测是否在寻路中(在则停止或双击瞬移),检测是否点击自己(转身或轻按), -检测是否能单击瞬移,最后找寻自动寻路路线并开始寻路。 +getAllSaves: fn(callback?: fn()) +获得所有存档内容 +updateHeroIcon: fn(name: string) +更新状态栏的勇士图标 -core.setAutoHeroMove(steps) -设置勇士的自动行走路线,并立刻开始行走。 +setMusicBtn: fn() +设置音乐图标的显隐状态 +isPlaying: fn() -> bool +游戏是否已经开始 -core.setHeroMoveInterval(callback) -设置勇士行走动画。callback是每一步行走完毕后的回调。 +triggerBgm: fn() +开启或关闭背景音乐的播放 +moveHero: fn(direction?: string, callback?: fn()) +连续前进,不撞南墙不回头 +例如:core.moveHero(); // 连续前进 +direction: 可选,如果设置了就会先转身到该方向 +callback: 可选,如果设置了就只走一步 -core.moveOneStep(x, y) -每走完一步后执行的操作,被转发到了脚本编辑中,执行脚本编辑moveOneStep中的内容。 +getRealStatusOrDefault: fn(status?: ?, name?: string) +从status中获得实际属性(增幅后的),如果不存在则从勇士属性中获取 +removeSave: fn(index?: number, callback?: fn()) +删除某个存档 -core.moveAction(callback) -尝试执行单步行走。callback是执行完毕的回调。 -如果勇士面对的方向是noPass的,将直接触发事件并执行回调。 +registerAnimationFrame: fn(name: string, needPlaying: bool, func?: fn(timestamp: number)) +注册一个 animationFrame +name: 名称,可用来作为注销使用 +needPlaying: 是否只在游戏运行时才执行(在标题界面不执行) +func: 要执行的函数,或插件中的函数名;可接受timestamp(从页面加载完毕到当前所经过的时间)作为参数 +getHeroLoc: fn(name: string) -> string|number +读取主角的位置和/或朝向 +例如:core.getHeroLoc(); // 读取主角的位置和朝向 +name: 要读取横坐标还是纵坐标还是朝向还是都读取 +返回值:name ? core.status.hero.loc[name] : core.status.hero.loc -core.moveHero(direction, callback) -令勇士朝一个方向行走。如果设置了callback,则只会行走一步,并执行回调。 -否则,将一直朝该方向行走,直到core.status.heroStop为true为止。 -direction可为"up","down","right","left",分别对应上,下,右,左。 +stopAutomaticRoute: fn() +停止自动寻路操作 +setWeather: fn(type?: string, level?: number) +设置天气,不计入存档。如需长期生效请使用core.events._action_setWeather()函数 +例如:core.setWeather('fog', 10); // 设置十级大雾天 +type: 新天气的类型,不填视为晴天 +level: 新天气(晴天除外)的级别,必须为不大于10的正整数,不填视为5 -core.isMoving() -当前是否正在处于行走状态 +updateStatusBar: fn(doNotCheckAutoEvents?: bool) +立刻刷新状态栏和地图显伤 +doNotCheckAutoEvents: 是否不检查自动事件 +autosave: fn(removeLast?: bool) +自动存档 -core.waitHeroToStop(callback) -停止勇士的行走,等待行动结束后,再异步执行回调。 +clearStatusBar: fn() +清空状态栏 +moveAction: fn(callback?: fn()) +尝试前进一步,如果面前不可被踏入就会直接触发该点事件 +请勿直接使用此函数,如有需要请使用「勇士前进一步或撞击」事件 -core.turnHero(direction) -转向。如果设置了direction则会转到该方向,否则会右转。该函数会自动计入录像。 -direction可为"up","down","right","left",分别对应上,下,右,左。 +hasFlag: fn(name: string) -> bool +判定一个flag变量是否存在且不为false、0、''、null、undefined和NaN +例如:core.hasFlag('poison'); // 判断主角当前是否中毒 +name: 变量名,支持中文 +此函数等价于 !!core.getFlag(name) +rewindReplay: fn() +回退到上一个录像节点 -core.moveDirectly(destX, destY) -尝试瞬间移动到某点,被转发到了脚本编辑中,执行脚本编辑中的内容。 -此函数返回非负值代表成功进行瞬移,返回值是省略的步数;如果返回-1则代表没有成功瞬移。 +toolboxReplay: fn() +回放录像时打开道具栏 +playBgm: fn(bgm: string, startTime?: number) +播放背景音乐,中途开播但不计入存档且只会持续到下次场景切换。如需长期生效请将背景音乐的文件名赋值给flags.__bgm__ +例如:core.playBgm('bgm.mp3', 30); // 播放bgm.mp3,并跳过前半分钟 +bgm: 背景音乐的文件名,支持全塔属性中映射前的中文名 +startTime: 跳过前多少秒,不填则不跳过 -core.tryMoveDirectly(destX, destY) -尝试单击瞬移到某点。 -如果该点可被直接瞬间移动到,则直接瞬移到该点;否则尝试瞬移到相邻的上下左右点并行走一步。 +isReplaying: fn() -> bool +是否正在播放录像 +isMoving: fn() -> bool +当前是否正在移动 -core.drawHero(status, offset) -绘制勇士。 -status可选,为'stop','leftFoot'和'rightFoot'之一,不填或null默认是'stop'。 -offset可选,表示具体当前格子的偏移量。不填默认为0。 -此函数将重新计算地图的偏移量,调整窗口位置,绘制勇士和跟随者信息。 +getSaveIndexes: fn(callback?: fn()) +获得所有存在存档的存档位 -// ------ 画布、位置、阻激夹域、显伤 ------ // +unlockControl: fn() +解锁用户控制行为 -core.setGameCanvasTranslate(canvas, x, y) -设置某个画布的偏移量 +syncSave: fn(type?: string) +同步存档到服务器 +removeFlag: fn(name: string) +删除某个flag/变量 -core.addGameCanvasTranslate(x, y) -加减所有系统画布(ui和data除外)的偏移量。主要是被“画面震动”所使用。 +registerResize: fn(name: string, func: fn(obj: ?)) +注册一个resize函数 +name: 名称,可供注销使用 +func: 可以是一个函数,或者是插件中的函数名;可以接受obj参数,详见resize函数。 +stopReplay: fn(force?: bool) +停止播放 -core.updateViewport() -根据大地图的偏移量来更新窗口的视野范围。 +bookReplay: fn() +回放时查看怪物手册 +turnHero: fn(direction?: string) +主角转向并计入录像,不会导致跟随者聚集,会导致视野重置到以主角为中心 +例如:core.turnHero(); // 主角顺时针旋转90°,即单击主角或按下Z键的效果 +direction: 主角的新朝向,可为 up, down, left, right, :left, :right, :back 七种之一 -core.nextX(n) / core.nextY(n) -获得勇士面对的第n个位置的横纵坐标。n可不填,默认为1。 +resumeReplay: fn() +恢复播放 +resize: fn() +屏幕分辨率改变后重新自适应 -core.nearHero(x, y, n) -判定某个点是否和勇士的距离不大于n。n可不填,默认为1。 +equipboxReplay: fn() +回放录像时打开装备栏 +getSave: fn(index?: number, callback?: fn(data: ?)) +获得某个存档内容 -core.gatherFollowers() -聚集所有的跟随者到勇士的位置。 +setViewport: fn(x?: number, y?: number) +设置视野范围 +x,y: 左上角相对大地图的像素坐标,不需要为32倍数 +chooseReplayFile: fn() +选择录像文件 -core.updateFollowers() -更新跟随者们的坐标。 +lockControl: fn() +锁定用户控制,常常用于事件处理 +updateCheckBlock: fn(floorId?: string) +更新领域、夹击、阻击的伤害地图 -core.updateCheckBlock(floorId) -更新阻激夹域的信息,被转发到了脚本编辑中。 +checkBlock: fn() +检查并执行领域、夹击、阻击事件 +clearAutomaticRouteNode: fn(x?: number, y?: number) +清除自动寻路路线 -core.checkBlock() -检查勇士坐标点的阻激夹域信息。 +getFlag: fn(name: string, defaultValue?: ?) +读取一个flag变量 +name: 变量名,支持中文 +defaultValue: 当变量不存在时的返回值,可选(事件流中默认填0)。 +getNakedStatus: fn(name: string) +获得勇士原始属性(无装备和衰弱影响) -core.updateDamage(floorId, ctx) -更新全地图的显伤。floorId可选,默认为当前楼层。 -ctx可选,为画布;如果不为空,则将会绘制到该画布上而不是damage层上。 +nearHero: fn(x: number, y: number, n?: number) -> bool +判定主角是否身处某个点的锯齿领域(取曼哈顿距离) +例如:core.nearHero(6, 6, 6); // 判定主角是否身处点(6,6)的半径为6的锯齿领域 +x: 领域的中心横坐标 +y: 领域的中心纵坐标 +n: 领域的半径,不填视为1 -// ------ 录像相关 ------ // +stepReplay: fn() +单步播放 -core.chooseReplayFile() -弹出选择文件窗口,让用户选择录像文件。 +hasSave: fn(index?: number) -> bool +判断某个存档位是否存在存档 +showStartAnimate: fn(noAnimate?: bool, callback?: fn()) +进入标题画面 +例如:core.showStartAnimate(); // 重启游戏但不重置bgm +noAnimate: 可选,true表示不由黑屏淡入而是立即亮屏 +callback: 可选,完全亮屏后的回调函数 -core.startReplay(list) -开始播放一段录像。list为录像的操作数组。 +moveViewport: fn(steps?: ?, time?: number, callback?: fn()) +移动视野范围 +syncLoad: fn() +从服务器加载存档 -core.triggerReplay() -播放或暂停录像,实际上是pauseReplay或resumeReplay之一。 +setHeroMoveInterval: fn(callback?: fn()) +设置行走的效果动画 +registerReplayAction: fn(name: string, func: fn(action?: string) -> bool) +注册一个录像行为 +name: 自定义名称,可用于注销使用 +func: 具体执行录像的函数,可为一个函数或插件中的函数名; +需要接受一个action参数,代表录像回放时的下一个操作 +func返回true代表成功处理了此录像行为,false代表没有处理此录像行为。 -core.pauseReplay() / core.resumeReplay() -暂停和继续录像播放。 +checkAutosave: fn() +实际将自动存档写入存储 +resumeBgm: fn(resumeTime?: number) +恢复背景音乐的播放 +resumeTime: 从哪一秒开始恢复播放 -core.speedUpReplay() / core.speedDownReplay() -加速和减速录像播放。 +setGameCanvasTranslate: fn(ctx: string|CanvasRenderingContext2D, x: number, y: number) +设置大地图的偏移量 +checkBgm: fn() +检查bgm状态 -core.setReplaySpeed(speed) -直接设置录像回放速度。 +speedDownReplay: fn() +减速播放 +getRealStatus: fn(name: string) +计算主角的某个属性,包括百分比修正 +例如:core.getRealStatus('atk'); // 计算主角的攻击力,包括百分比修正。战斗使用的就是这个值 +name: 属性的英文名,请注意只能用于数值类属性哦,否则乘法会得到NaN -core.stopReplay(force) -停止录像回放。如果force为true则强制停止。 +saveData: fn() +存档到本地 +unregisterAnimationFrame: fn(name: string) +注销一个animationFrame -core.rewindReplay() -回退一个录像节点。 +tryMoveDirectly: fn(destX: number, destY: number) +尝试瞬移,如果该点有图块/事件/阻激夹域捕则会瞬移到它旁边再走一步(不可踏入的话当然还是触发该点事件),这一步的方向优先和瞬移前主角的朝向一致 +例如:core.tryMoveDirectly(6, 0); // 尝试瞬移到地图顶部的正中央,以样板0层为例,实际效果是瞬移到了上楼梯下面一格然后向上走一步并触发上楼事件 +destX: 目标点的横坐标 +destY: 目标点的纵坐标 - -core.saveReplay() / core.bookReplay() / core.viewMapReplay() -回放录像时的存档、查看怪物手册、浏览地图操作。 - - -core.isReplaying() -当前是否正在录像播放中。 - - -core.registerReplayAction(name, func) -注册一个自定义的录像行为。 -name:自定义名称,可用户注销使用。 -func:具体执行录像的函数,是一个函数体或者插件中的函数名。 -func需要接受action参数,代表录像回放时的当前操作行为。 -如果func返回true,则代表成功处理了此次操作,返回false代表没有进行处理。 -自己添加的录像项只能由数字、大小写、下划线线、冒号等符号组成,否则无法正常压缩和解压缩。 -对于自定义内容(比如中文文本或数组)请使用JSON.stringify再core.encodeBase64处理。 -请注意回放录像时的二次记录问题(即回放时录像会重新记录路线)。 - - -core.unregisterReplayAction(name) -注销一个录像行为。此函数一般不应当被使用。 - -// ------ 存读档相关 ------ // - -core.autosave(remoreLast) -进行一个自动存档,实际上是加入到缓存之中。 -removeLast如果为true则会从路线中删除最后一项再存(打怪开门前的状态)。 -在事件处理中不允许调用本函数,如有需要请呼出存档页面。 - - -core.checkAutosave() -将缓存的自动存档写入存储中。平均每五秒钟,或在窗口失去焦点时被执行。 - - -core.doSL(id, type) -实际执行一个存读档事件。id为存档编号,自动存档为'autoSave'。 -type只能为'save', 'load', 'replayLoad'之一,代表存档、读档和从存档回放录像。 - - -core.syncSave(type) / core.syncLoad() -向服务器同步存档,从服务器加载存档。type如果为'all'则会向服务器同步所有存档。 - - -core.saveData() -获得要存档的内容,实际转发到了脚本编辑中,执行脚本编辑中的内容。 - - -core.loadData(data, callback) -实际执行一次读档行为,data为读取到的数据,callback为执行完毕的回调。 -实际转发到了脚本编辑中,执行脚本编辑中的内容。 - - -core.getSave(index, callback) -获得某个存档位的存档。index为存档编号,0代表自动存档。 - - -core.getSaves(ids, callback) -获得若干个存档位的存档。ids为一个存档编号数组,0代表自动存档。 - - -core.getAllSaves(callback) -获得全部的存档内容。目前仅被同步全部存档和下载全部存档所调用。 - - -core.getSaveIndexes(callback) -刷新全部的存档信息,将哪些档位有存档的记录到core.saves.ids中。 - - -core.hasSave(index) -判定某个存档位是否存在存档。index为存档编号,0代表自动存档。 - - -core.removeSave(index) -删除某个存档。index为存档编号,0代表自动存档。 - - -// ------ 属性、状态、位置、变量等 ------ // - -core.setStatus(name, value) -设置勇士当前的某个属性,name可为"atk","def","hp"等。 -如core.setStatus("atk", 100)则为设置勇士攻击为100。 - - -core.addStatus(name, value) -加减勇士当前的某个属性,name可为"atk","def","hp"等。 -如core.addStatus("atk", 100)则为增加勇士攻击100点。 -等价于 core.setStatus(name, core.getStatus(name) + value)。 - - -core.getStatus(name) -获得勇士的某个原始属性值,该值不受百分比增幅影响。 -譬如你有一件道具加10%的攻击,你可以使用该函数获得你的攻击被增幅前的数值 - - -core.getStatusOrDefault(status, name) -尝试从status中获得某个原始属性值,该值不受百分比增幅影响;如果status为null或不存在对应属性值则从勇士属性中获取。 -此项在伤害计算函数中使用较多,例如传递新的攻击和防御来计算临界和1防减伤。 - - -core.getRealStatus(name) -获得勇士的某个计算属性值。该属性值是在加成buff之后得到的。 -该函数等价于 core.getStatus(name) * core.getBuff(name) - - -core.getRealStatusOrDefault(status, name) -尝试从status中获得某个原始属性值再进行增幅,如果不存在则获取勇士本身的计算属性值。 - - -core.setBuff(name, value) -设置勇士的某个属性的增幅值。value为1代表无增幅。 - - -core.addBuff(name, value) -增减勇士的某个属性的增幅值。等价于 core.setBuff(name, core.getBuff(name) + value) - - -core.getBuff(name) -获得勇士的某个属性的增幅值。默认值是1。 - - -core.setHeroLoc(name, value, noGather) -设置勇士位置属性。name只能为'x'(勇士x坐标), 'y'(勇士y坐标)和'direction'(勇士朝向)之一。 -如果noGather为true,则不会聚集所有的跟随者。 -譬如core.setHeroLoc("x", 1, true)则为设置勇士x坐标为1,不聚集所有跟随者。 - - -core.getHeroLoc(name) -获得勇士的某个位置属性。如果name为null则直接返回core.status.hero.loc。 -譬如core.getHeroLoc("x")则返回勇士当前x坐标 - - -core.getLvName(lv) -获得某个等级对应的名称,其在全塔属性的levelUp中定义。如果不存在则返回原始数值。 - - -core.setFlag(name, value) -设置某个自定义变量或flag。如果value为null则会调用core.removeFlag进行删除。 -这里的变量与事件中使用的变量等价 -譬如core.setFlag("xxx",1)则为设置变量xxx为1。 - - -core.addFlag(name, value) -加减某个自定义的变量或flag。等价于 core.setFlag(name, core.getFlag(name, 0) + value) -这里的变量与事件中使用的变量等价 -譬如core.addFlag("xxx",1)则为增加变量xxx1 - - -core.getFlag(name, defaultValue) -获得某个自定义的变量或flag。如果该flag不存在(从未赋值过),则返回defaultValue的值。 -这里的变量与事件中使用的变量等价 -譬如core.getFlag("xxx",1)则为获得变量xxx的值,如变量xxx不存在则返回1 - - -core.hasFlag(name) -判定是否拥有某个自定义变量或flag。等价于 !!core.getFlag(name, 0) -这里的变量与事件中使用的变量等价 -譬如core.hasFlag("xxx",1)则为判断变量xxx是否存在 - -core.removeFlag(name) -删除一个自定义变量或flag。 - - -core.lockControl() / core.unlockControl() -锁定和解锁控制。常常应用于事件处理。 - - -core.debug() -开启调试模式。此模式下可以按住Ctrl进行穿墙。 - -// ------ 天气,色调,音乐和音效 ------ // - -core.setWeather(type, level) -设置当前的天气。type只能为'rain', 'snow'或'fog',level为1-10之间代表强度信息。 - - -core.setCurtain(color, time, callback) -更改画面色调。color为更改到的色调,是个三元或四元组;time为渐变时间,0代表立刻切换。 -譬如core.setCurtain([255,255,255,1], 0)即为无回调无等待更改画面色调为白色 - - - -core.screenFlash(color, time, times, callback) -画面闪烁。color为色调,三元或四元组;time为单次闪烁时间,times为总闪烁次数。 - - -core.playBgm(bgm, startTime) -播放一个bgm。startTime可以控制开始时间,不填默认为0。 -如果bgm不存在、不被支持,或当前不允许播放背景音乐,则会跳过。 - - -core.pauseBgm() / core.resumeBgm() -暂停和恢复当前bgm的播放。 - - -core.triggerBgm() -更改当前bgm的播放状态。 - - -core.playSound(sound) / core.stopSound() -播放一个音效,停止全部音效。 -如果sound不存在、不被支持,或当前不允许播放音效,则会忽略。 - - -core.checkBgm() -检查bgm的状态。 -有的时候,刚打开页面时,浏览器是不允许自动播放标题界面bgm的,一定要经过一次用户操作行为。 -这时候我们可以给开始按钮增加core.checkBgm(),如果之前没有成功播放则重新播放。 - -// ------ 状态栏和工具栏相关 ------ // - -core.clearStatusBar() -清空状态栏的数据。 - - -core.updateStatusBar(doNotCheckAutoEvents) -更新状态栏,被转发到了脚本编辑中。此函数还会根据是否在回放来设置工具栏的图标。 -如果doNotCheckAutoEvents为true则此时不检查自动事件。 - -core.showStatusBar() / core.hideStatusBar(showToolbox) -显示和隐藏状态栏。 -如果showToolbox为true,则在竖屏模式下不隐藏工具栏,方便手机存读档操作。 - - -core.updateHeroIcon() -更新状态栏上的勇士图标。 - - -core.setToolbarButton(useButtom) -设置工具栏是否是拓展键盘。 - -// ------ resize 相关 ------ // - -core.registerResize(name, func) -注册一个resize函数。 -name为自定义名称,可供注销使用。 -func可以是一个函数,或插件中的函数名,可以接受一个obj作为参数。 -具体详见resize函数。 - - -core.unregisterResize(name) -注销一个resize函数。 - - -core.resize() -屏幕分辨率改变后的重新自适应。 -此函数将根据当前的屏幕分辨率信息,生成一个obj,并传入各个注册好的resize函数中执行。 +moveDirectly: fn(destX?: number, destY?: number, ignoreSteps?: number) +瞬间移动 ``` ## enemys.js @@ -710,78 +693,114 @@ core.resize() enemys.js中定义了一系列和怪物相关的API函数。 ```text -core.hasSpecial(special, test) -判断是否含有某个特殊属性。test为要检查的特殊属性编号。 -special为要测试的内容,允许接收如下类型参数: - - 一个数字:将直接和test进行判等。 - - 一个数组:将检查test是否在该数组之中存在。 - - 一个怪物信息:将检查test是否在该怪物的特殊属性中存在 - - 一个字符串:视为怪物ID,将检查该怪物的特殊属性 +getEnemys: fn() +获得所有怪物原始数据的一个副本。 +请使用core.material.enemys获得当前各项怪物属性。 + +getSpecials: fn() -> [[?]] +获得所有特殊属性的定义 + +getSpecialColor: fn(enemy: string|enemy) -> [string] +获得某个怪物所有特殊属性的颜色 + +getSpecialFlag: fn(enemy: string|enemy) -> number +获得某个怪物所有特殊属性的额外标记。 + +例如,1为全图性技能,需要进行遍历全图(光环/支援等) + +getSpecialHint: fn(enemy: string|enemy, special: number) -> string +获得某种敌人的某种特殊属性的介绍 +例如:core.getSpecialHint('bat', 1) // '先攻:怪物首先攻击' +enemy: 敌人id或敌人对象,用于确定属性的具体数值,否则可选 +special: 属性编号,可以是该敌人没有的属性 +返回值:属性的介绍,以属性名加中文冒号开头 + +getSpecialText: fn(enemy: string|enemy) -> [string] +获得某种敌人的全部特殊属性名称 +例如:core.getSpecialText('greenSlime') // ['先攻', '3连击', '破甲', '反击'] +enemy: 敌人id或敌人对象,如core.material.enemys.greenSlime +返回值:字符串数组 + +hasSpecial: fn(special: number|[number]|string|number, test: number) -> bool +判定某种特殊属性的有无 +例如:core.hasSpecial('greenSlime', 1) // 判定绿头怪有无先攻属性 +special: 敌人id或敌人对象或正整数数组或自然数 +test: 待检查的属性编号 -core.getSpecials() -获得所有特殊属性的列表。实际上被转发到了脚本编辑中,执行脚本编辑中的内容。 +nextCriticals: fn(enemy: string|enemy, number?: number, x?: number, y?: number, floorId?: string) -> [[number]] +获得某只敌人接下来的若干个临界及其减伤,算法基于useLoop开关选择回合法或二分法 +例如:core.nextCriticals('greenSlime', 9, 0, 0, 'MT0') // 绿头怪接下来的9个临界 +enemy: 敌人id或敌人对象 +number: 要计算的临界数量,可选,默认为1 +x: 敌人的横坐标,可选 +y: 敌人的纵坐标,可选 +floorId: 敌人所在的地图,可选 +返回:两列的二维数组,每行表示一个临界及其减伤 +getDefDamage: fn(enemy: string|enemy, k?: number, x?: number, y?: number, floorId?: string) -> number +计算再加若干点防御能使某只敌人对主角的总伤害降低多少 +例如:core.getDefDamage('greenSlime', 10, 0, 0, 'MT0') // 再加10点防御能使绿头怪的伤害降低多少 +enemy: 敌人id或敌人对象 +k: 假设主角增加的防御力,可选,默认为1 +x: 敌人的横坐标,可选 +y: 敌人的纵坐标,可选 +floorId: 敌人所在的地图,可选 -core.getSpecialText(enemy) -获得某个怪物的全部特殊属性名称。enemy可以是怪物信息或怪物ID。 -将返回一个数组,每一项是该怪物所拥有的一个特殊属性的名称。 +canBattle: fn(enemy: string|enemy, x?: number, y?: number, floorId?: string) -> bool +判定主角当前能否打败某只敌人 +例如:core.canBattle('greenSlime',0,0,'MT0') // 能否打败主塔0层左上角的绿头怪(假设有) +enemy: 敌人id或敌人对象 +x: 敌人的横坐标,可选 +y: 敌人的纵坐标,可选 +floorId: 敌人所在的地图,可选 +返回值:true表示可以打败,false表示无法打败 +getEnemyInfo: fn(enemy: string|enemy, hero?: ?, x?: number, y?: number, floorId?: string) -> {hp: number, atk: number, def: number, money: number, exp: number, special: [number], point: number, guards: [?]} +获得怪物真实属性 +hero: 可选,此时的勇士属性 +此函数将会计算包括坚固、模仿、光环等若干效果,将同时被怪物手册和伤害计算调用 -core.getSpecialHint(enemy, special) -获得怪物的某个特殊属性的描述。enemy可以是怪物信息或怪物ID,special为该特殊属性编号。 +getDamageInfo: fn(enemy: string|enemy, hero?: ?, x?: number, y?: number, floorId?: string) -> {damage: number, per_damage: number, hero_per_damage: number, init_damage: number, mon_hp: number, mon_atk: number, mon_def: number, turn: number} +获得战斗伤害信息 +例如:core.getDamage('greenSlime',0,0,'MT0') // 绿头怪的总伤害 +enemy: 敌人id或敌人对象 +hero: 可选,此时的勇士属性 +x: 敌人的横坐标,可选 +y: 敌人的纵坐标,可选 +floorId: 敌人所在的地图,可选 +返回值:伤害计算信息,如果因为没有破防或无敌怪等其他原因无法战斗,则返回null +getDamage: fn(enemy: string|enemy, x?: number, y?: number, floorId?: string) -> number +获得某只敌人对主角的总伤害 +例如:core.getDamage('greenSlime',0,0,'MT0') // 绿头怪的总伤害 +enemy: 敌人id或敌人对象 +x: 敌人的横坐标,可选 +y: 敌人的纵坐标,可选 +floorId: 敌人所在的地图,可选 +返回值:总伤害,如果因为没有破防或无敌怪等其他原因无法战斗,则返回null -core.canBattle(enemy, x, y, floorId) -判定当前能否战胜某个怪物。 -enemy可以是怪物信息或怪物ID,x,y,floorId为当前坐标和楼层。(下同) -能战胜返回true,不能战胜返回false。 +getDamageString: fn(enemy: string|enemy, x?: number, y?: number, floorId?: string) -> {color: string, damage: string} +获得某只敌人的地图显伤,包括颜色 +例如:core.getDamageString('greenSlime', 0, 0, 'MT0') // 绿头怪的地图显伤 +enemy: 敌人id或敌人对象 +x: 敌人的横坐标,可选 +y: 敌人的纵坐标,可选 +floorId: 敌人所在的地图,可选 +返回值:damage: 表示伤害值或为'???',color: 形如'#RrGgBb' +getCurrentEnemys: fn(floorId?: string) -> [enemy] +获得某张地图的敌人集合,用于手册绘制 +例如:core.getCurrentEnemys('MT0') // 主塔0层的敌人集合 +floorId: 地图id,可选 +返回值:敌人集合,按伤害升序排列,支持多朝向怪合并 -core.getDamage(enemy, x, y, floorId) -获得某个怪物的全部伤害值。 -如果没有破防或无法战斗则返回null,否则返回具体的伤害值。 - - -core.getDamageString(enemy, x, y, floorId) -获得某个怪物伤害字符串和颜色信息,以便于在地图上绘制显伤。 - - -core.nextCriticals(enemy, number, x, y, floorId) -获得接下来的N个临界值和临界减伤。enemy可以是怪物信息或怪物ID,x,y,floorId为当前坐标和楼层。 -number为要计算的临界值数量,不填默认为1。 -如果全塔属性中的useLoop开关被开启,则将使用循环法或二分法计算临界,否则使用回合法计算临界。 -返回一个二维数组 [[x1,y1],[x2,y2],...] 表示接下来的每个临界值和减伤值。 - - -core.getDefDamage(enemy, k, x, y, floorId) -获得某个怪物的k防减伤值。k可不填默认为1,x,y,floorId为当前xy坐标和楼层。 - - -core.getEnemyInfo(enemy, hero, x, y, floorId) -获得某个怪物的实际计算时的属性。该函数实际被转发到了脚本编辑中。 -hero可为null或一个对象,具体将使用core.getRealStatusOrDefault(hero, "atk")来获得攻击力数值。 -该函数应当返回一个对象,记录了怪物的实际计算时的属性。 - - -core.getDamageInfo(enemy, hero, x, y, floorId) -获得某个怪物的战斗信息。该函数实际被转发到了脚本编辑中。 -hero可为null或一个对象,具体将使用core.getRealStatusOrDefault(hero, "atk")来获得攻击力数值。 -如果该函数返回null,则代表不可战斗(如没有破防,或无敌等)。 -否则,该函数应该返回一个对象,记录了战斗伤害信息,如战斗回合数等。 -从V2.5.5开始,该函数也允许直接返回一个数字,代表战斗伤害值,此时回合数将视为0。 - - -core.getCurrentEnemys(floorId) -获得某个楼层不重复的怪物信息,floorId不填默认为当前楼层。该函数会被怪物手册所调用。 -该函数将返回一个列表,每一项都是一个不同的怪物,按照伤害值从小到大排序。 -另外值得注意的是,如果设置了某个怪物的displayIdInBook,则会返回对应的怪物。 - - -core.hasEnemyLeft(enemyId, floorId) -检查某个楼层是否还有剩余的(指定)怪物。 -floorId为楼层ID,可忽略表示当前楼层。也可以填数组如["MT0","MT1"]同时检测多个楼层。 -enemyId如果不填或null则检查是否剩余任何怪物,否则只检查是否剩余指定的某类怪物。 +hasEnemyLeft: fn(enemyId?: string, floorId?: string|[string]) -> bool +检查某些楼层是否还有漏打的(某种)敌人 +例如:core.hasEnemyLeft('greenSlime', ['sample0', 'sample1']) // 样板0层和1层是否有漏打的绿头怪 +enemyId: 敌人id,可选,null表示任意敌人 +floorId: 地图id或其数组,可选,不填为当前地图 +返回值:地图中是否还存在该种敌人 ``` ## events.js @@ -795,832 +814,341 @@ events.js将处理所有和事件相关的操作,主要分为五个部分: ```text -// ------ 游戏的开始和结束 ------ // +afterChangeFloor: fn(floorId?: string) +转换楼层结束的事件 -core.resetGame(hero, hard, floorId, maps, values) -重置整个游戏。该函数实际被转发到了脚本编辑中。 +popEventLoc: fn() +将当前点坐标入栈 +afterOpenDoor: fn(doorId?: string, x?: number, y?: number) +开一个门后触发的事件 -core.startGame(hard, seed, route, callback) -开始新游戏。 -hard为难度字符串,会被设置为core.status.hard。 -seed为开始时要设置的的种子,route为要开始播放的录像,callback为回调函数。 -该函数将重置整个游戏,执行startText事件,上传游戏人数统计信息等。 +checkLvUp: fn() +检查升级事件 +insertAction: fn(action: string|?|[?], x?: number, y?: number, callback?: fn(), addToLast?: bool) +插入一段事件;此项不可插入公共事件,请用 core.insertCommonEvent +例如:core.insertAction('一段文字'); // 插入一个显示文章 +action: 单个事件指令,或事件指令数组 +x: 新的当前点横坐标,可选 +y: 新的当前点纵坐标,可选 +callback: 新的回调函数,可选 +addToLast: 插入的位置,true表示插入到末尾,否则插入到开头 -core.win(reason, norank) -游戏胜利,reason为结局名,norank如果为真则该结局不计入榜单。 -该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容。 +unfollow: fn(name?: string) +取消跟随 +name: 取消跟随的行走图,不填则取消全部跟随者 + +hasVisitedFloor: fn(floorId?: string) -> bool +是否到达过某个楼层 + +startEvents: fn(list?: [?], x?: number, y?: number, callback?: fn()) +开始执行一系列自定义事件 +setHeroIcon: fn(name: string, noDraw?: bool) +更改主角行走图 +例如:core.setHeroIcon('npc48.png', true); // 把主角从阳光变成样板0层左下角的小姐姐,但不立即刷新 +name: 新的行走图文件名,可以是全塔属性中映射前的中文名。映射后会被存入core.status.hero.image +noDraw: true表示不立即刷新(刷新会导致大地图下视野重置到以主角为中心) -core.lose(reason) -游戏失败,reason为结局名。该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容。 +changingFloor: fn(floorId?: string, heroLoc?: {x: number, y: number, direction: string}) +楼层转换中 + +setEvents: fn(list?: [?], x?: number, y?: number, callback?: fn()) +直接设置事件列表 +setValue: fn(name: string, operator: string, value: ?, prefix?: string) +数值操作 -core.gameOver(ending, fromReplay, norank) -游戏结束。ending为获胜结局名,null代表失败;fromReplay标识是否是录像触发的。 -此函数将询问是否上传成绩(如果ending不是null),是否下载录像等,并重新开始。 +precompile: fn(data?: ?) +预编辑事件 +vibrate: fn(time?: number, callback?: fn()) +视野左右抖动 +例如:core.vibrate(); // 视野左右抖动1秒 +time: 抖动时长,单位为毫秒。必须为半秒的倍数,不填或小于1秒都视为1秒 +callback: 抖动平息后的回调函数,可选 -core.restart() -重新开始游戏。本质上就是播放标题界面的BGM并调用showStartAnimate。 +confirmRestart: fn() +询问是否需要重新开始 +battle: fn(id: string, x?: number, y?: number, force?: bool, callback?: fn()) +战斗,如果填写了坐标就会删除该点的敌人并触发战后事件 +例如:core.battle('greenSlime'); // 和从天而降的绿头怪战斗(如果打得过) +id: 敌人id,必填 +x: 敌人的横坐标,可选 +y: 敌人的纵坐标,可选 +force: true表示强制战斗,可选 +callback: 回调函数,可选 -core.confirmRestart() -确认用户是否需要重新开始。 +follow: fn(name: string) +跟随 +name: 要跟随的一个合法的4x4的行走图名称,需要在全塔属性注册 -// ------ 系统事件处理 ------ // +beforeBattle: fn(enemyId?: string, x?: number, y?: number) -> bool +战斗前触发的事件;返回false代表不进行战斗 -core.registerSystemEvent(type, func) -注册一个系统事件,即通过图块的默认触发器所触发的事件。 -type为一个要注册的事件类型,func为要执行的函数体或插件中的函数名。 -func需要接受(data, callback)作为参数,分别是触发点的图块信息,和执行完毕时的回调。 -如果注册一个已经存在的系统事件,比如openDoor,则会覆盖系统的默认函数。 +registerEvent: fn(type: string, func: fn(data: ?, x?: number, y?: number, prefix?: string)) +注册一个自定义事件 +type: 事件类型 +func: 事件的处理函数,可接受(data, x, y, prefix)参数 +data为事件内容,x和y为当前点坐标(可为null),prefix为当前点前缀 + +flyTo: fn(toId?: string, callback?: fn()) -> bool +飞往某一层 + +afterGetItem: fn(id?: string, x?: number, y?: number, isGentleClick?: bool) +获得一个道具后的事件 + +doAction: fn(keepUI?: true) +执行下一个事件指令,常作为回调 +例如:core.setCurtain([0,0,0,1], undefined, core.doAction); // 事件中的原生脚本,配合勾选“不自动执行下一个事件”来达到此改变色调只持续到下次场景切换的效果 +keepUI: true表示不清除UI画布和选择光标 + +openBook: fn(fromUserAction?: bool) +点击怪物手册时的打开操作 + +save: fn(fromUserAction?: bool) +点击存档按钮时的打开操作 + +load: fn(fromUserAction?: bool) +点击读档按钮时的打开操作 + +getNextItem: fn(noRoute?: bool) +轻按获得面前的物品或周围唯一物品 +noRoute: 若为true则不计入录像 - -core.unregisterSystemEvent(type) -注销一个系统事件。type是上面你注册的事件类型。 - - -core.doSystemEvent(type, data, callback) -执行一个系统事件。type为事件类型,data为该事件点的图块信息,callback为执行完毕的回调。 - - -core.battle(id, x, y, force, callback) -和怪物进行战斗。 -id为怪物的ID,x和y为怪物坐标,force如果为真将强制战斗,callback为执行完毕的回调。 -如果填写了怪物坐标,则会删除对应点的图块并执行该点战后事件。 -如果是在事件流的执行过程中调用此函数,则不会进行自动存档,且会强制战斗。 - - -core.beforeBattle(enemyId, x, y) -战前事件。实际被转发到了脚本编辑中,执行脚本编辑中的内容,可以用于加上一些战前特效。 -此函数在“检测能否战斗和自动存档”【之后】执行。 -如果需要更早的战前事件,请在插件中覆重写 core.events.doSystemEvent 函数。 -此函数返回true则将继续本次战斗,返回false将不再战斗。 - - -core.afterBattle(enemyId, x, y, callback) -战后事件,将执行扣血、加金币经验、特殊属性处理、战后事件处理等操作。 -实际被转发到了脚本编辑中,执行脚本编辑中的内容。 - - -core.openDoor(x, y, needKey, callback) -尝试开一个门。x和y为门的坐标,needKey表示是否需要钥匙,callback为执行完毕的回调。 -如果不是一个有效的门,需要钥匙且未持有等,均会忽略此事件并直接执行callback。 - - -core.afterOpenDoor(doorId, x, y, callback) -开完一个门后执行的事件,实际被转发到了脚本编辑中,执行脚本编辑中的内容。 - - -core.getItem(id, num, x, y, callback) -获得若干个道具。itemId为道具ID,itemNum为获得的道具个数,不填默认为1。 -x和y为道具点的坐标,如果设置则会擦除地图上的该点,也可不填。 -譬如core.getItem("yellowKey",2)会直接获得两把黄钥匙。 - - -core.afterGetItem(id, x, y, callback) -获得一个道具后执行的事件,实际被转发到了脚本编辑中,执行脚本编辑中的内容。 - - -core.getNextItem(noRoute) -轻按,即获得面对的道具。如果noRoute为真则这个轻按行为不会计入录像。 - - -core.changeFloor(floorId, stair, heroLoc, time, callback, fromLoad) -楼层切换。floorId为目标楼层ID,stair为是什么楼梯,heroLoc为目标点坐标。 -time为切换时间,callback为切换完毕的回调,fromLoad标志是否是从读档造成的切换。 -floorId也可以填":before"和":next"表示前一层和后一层。 -heroLoc为{"x": 0, "y": 0, "direction": "up"}的形式。不存在则从勇士位置取。 -如果stair不为null,则会在该楼层中找对应的图块作为目标点的坐标并覆盖heroLoc。 -一般设置的是"upFloor"和"downFloor",但也可以用任何其他的图块ID。 - - -core.changingFloor(floorId, heroLoc, fromLoad) -正在执行楼层切换中执行的操作,实际被转发到了脚本编辑中。 - - -core.hasVisitedFloor(floorId) -是否曾经到达过某一层。 - - -core.visitFloor(floorId) -标记曾经到达了某一层。 - - -core.passNet(data) -执行一个路障处理。这里只有毒衰咒网的处理,血网被移动到了updateCheckBlock中。 - - -core.pushBox(data) -执行一个推箱子事件。 - - -core.afterPushBox() -推箱子之后触发的事件,实际被转发到了脚本编辑中,执行脚本编辑中的内容。 - - -core.changeLight(id, x, y) -踩灯后的事件。 - -// ------ 自定义事件的处理 ------ // - -core.registerEvent(type, func) -注册一个自定义事件。type为事件名,func为执行事件的函数体或插件中的函数名。 -func可以接受(data, x, y, prefix)参数,其中data为事件内容,x和y为该点坐标,prefix为该点前缀。 -同名注册的事件将进行覆盖。 -请记得在自定义处理事件完毕后调用core.doAction()再继续执行下一个事件! - - -core.unregisterEvent(type) -注销一个自定义事件。 - - -core.doEvent(data, x, y, prefix) -执行一个自定义事件。data为事件内容,将根据data.type去注册的事件列表中查找对应的执行函数。 -x和y为该点坐标,prefix为该点前缀。执行事件时也会把(data, x, y, prefix)传入执行函数。 - - -core.setEvents(list, x, y, callback) -设置自定义事件的执行列表,坐标和回调函数。 - - -core.startEvents(list, x, y, callback) -开始执行一系列的自定义事件。list为事件列表,x和y为事件坐标,callback为执行完毕的回调。 -此函数将调用core.setEvents,然后停止勇士,再执行core.doAction()。 - - -core.doAction(keepUI) -执行下一个自定义事件。 -此函数将检测事件列表是否全部执行完毕,如果是则执行回调函数。 -否则,将从事件列表中弹出下一个事件,并调用core.doEvent进行执行。 -如果keepUI为true,则不会清掉UI层和selector,适合于自己用脚本的绘制。 - - -core.insertAction(action, x, y, callback, addToLast) -向当前的事件列表中插入一个或多个事件并执行。 -如果当前并不是在事件执行流中,则会调用core.startEvents()开始执行事件,否则仅仅执行插入操作。 -action为要插入的事件,可以是一个单独的事件,或者是一个事件列表。 -x,y,callback如果设置了且不为null,则会覆盖当前的坐标和回调函数。 -addToLast如果为真,则会插入到事件执行列表的尾部,否则是插入到执行列表的头部。 - - -core.getCommonEvent(name) -根据名称获得某个公共事件内容。 - - -core.recoverEvents(data) -恢复事件现场。一般用于呼出怪物手册、呼出存读档页面等时,恢复事件执行流。 - - -core.checkAutoEvents() -检测自动事件并执行。 - - -core.precompile(events) -尝试预编译一段事件。 - - -// ------ 点击状态栏图标时执行的一些操作 ------ // - -core.openBook(fromUserAction) -尝试打开怪物手册。fromUserAction标志是否是从用户的行为触发,如按键或点击状态栏。(下同) -不建议复写此函数,否则【呼出怪物手册】事件会出问题。 - - -core.useFly(fromUserAction) -尝试使用楼传器。可以安全的复写此函数,参见文档-个性化-覆盖楼传事件。 - - -core.flyTo(toId, callback) -尝试飞行到某个楼层,被转发到了脚本编辑中。 -如果此函数返回true代表成功进行了飞行,false代表不能进行飞行。 - - -core.openEquipbox(fromUserAction) / core.openToolbox(fromUserAction) -尝试打开道具栏和装备栏。可以安全复写这两个函数。 - - -core.openQuickShop(fromUserAction) / core.openKeyBoard(fromUserAction) -尝试打开快捷商店和虚拟键盘。可以安全复写这两个函数。 - - -core.save(fromUserAction) / core.load(fromUserAction) -尝试打开存读档页面。 -不建议复写这两个函数,否则【呼出存读档页面】事件会出问题。 - - -core.openSettings(fromUserAction) -尝试打开系统菜单。不建议复写此函数。 - - -// ------ 一些具体事件的执行内容 ------ // - -core.hasAsync() -当前是否存在未执行完毕的异步事件。请注意正在播放的动画也算异步事件。 - - -core.follow(name) / core.unfollow(name) -跟随勇士/取消跟随。name为行走图名称。 -在取消跟随时如果指定了name,则会从跟随列表中选取一个该行走图取消,否则取消所有跟随。 -跟随和取消跟随都会调用core.gatherFollowers()来聚集所有的跟随者。 - - -core.setValue(name, operator, value, prefix) / core.addValue(name, value, prefix) -设置/增减某个数值。name可以是status:xxx,item:xxx或flag:xxx。 -value可以是一个表达式,将调用core.calValue()计算。prefix为前缀,独立开关使用,脚本中一般忽略。 - - -core.doEffect(effect, need, times) -执行一个effect操作。该函数目前仅被全局商店的status:xxx+=yyy所调用。 - - -core.setEnemy(id, name, value, prefix) -设置一个怪物属性。id为怪物的ID,name为要设置的项,比如hp,atk,def等等。 -value可以是一个表达式,将调用core.calValue()计算。prefix为前缀,独立开关使用,脚本中一般忽略。 - - -core.setFloorInfo(name, values, floorId, prefix) -设置某层楼的楼层属性,其中name为该楼层属性对应的条目,values为要设置的值,floorId为楼层id,prefix一般直接忽略。 -譬如core.setFloorInfo("name","4", "MT1")则为设置MT1显示在状态栏中的层数为4 - - -core.setGlobalAttribute(name, value) -设置一个全局属性,如边框颜色等。 - - -core.setGlobalFlag(name, value) -设置一个全局开关,如enableXXX等。 -如果需要设置一个全局数值如红宝石数值,可以直接简单的修改core.values,因此没有单独列出函数。 - - -core.closeDoor(x, y, id, callback) -执行一个关门事件。如果不是一个合法的门,或者该点不为空地,则会忽略本事件。 - - -core.showImage(code, image, sloc, loc, opacityVal, time, callback) -显示一张图片。code为图片编号,image为图片内容或图片名。 -sloc为[x,y,w,h]形式,表示在原始图片上裁剪的区域,也可直接设为null表示整张图片。 -loc为[x,y,w,h]形式,表示在界面上绘制的位置和大小,w和h可忽略表示使用绘制大小。 -opacityVal为绘制的不透明度,time为淡入时间。 -此函数将创建一个画布,其z-index是100+code,即图片编号为1则是101,编号50则是150。 -请注意,curtain层的z-index是125,UI层的z-index是140;因此可以通过图片编号来调整覆盖关系。 - - -core.hideImage(code, time, callback) -隐藏一张图片。code为图片编号,time为淡出时间。 - - -core.moveImage(code, to, opacityVal, time, callback) -移动一张图片。code为图片编号,to为[x,y]表示目标位置,opacityVal目标不透明度,time为移动时间。 - - -core.showGif(name, x, y) -绘制一张gif图片或取消所有绘制内容。如果name不设置则视为取消。x和y为左上角像素坐标。 - - -core.setVolume(value, time, callback) -设置音量。value为目标音量大小,在0到1之间。time为音量渐变的时间。 - - -core.vibrate(time, callback) -画面震动。time为震动时间。 -请注意,画面震动时间必须是500的倍数,系统也会自动把time调整为上整的500倍数值。 - - -core.eventMoveHero(steps, time, callback) -使用事件移动勇士。time为每步的移动时间。 -steps为移动数组,可以接受'up','down','left','right','forward'和'backward'项。 -使用事件移动勇士将不会触发任何地图上的事件。 - - -core.jumpHero(ex, ey, time, callback) -跳跃勇士。ex和ey为目标点的坐标,可以为null表示原地跳跃。time为总跳跃时间。 - - -core.openShop(shopId, needVisited) -打开一个全局商店。needVisited表示是否需要该商店原本就是启用状态。 -如果该商店对应的实际上是一个全局事件,则会直接插入并执行。 - - -core.disableQuickShop(shopId) -禁用一个全局商店,即把一个商店从启用变成禁用状态。 - - -core.canUseQuickShop(shopId) -当前能否使用某个全局商店,实际被转发到了脚本编辑中。 -如果此函数返回null则表示可以使用,返回一个字符串表示不可以,该字符串表示不可以的原因。 - - -core.setHeroIcon(name, noDraw) -设置勇士的行走图。 -name为行走图名称,noDraw如果为真则不会调用core.drawHero()函数进行刷新。 - - -core.checkLvUp() -检查升级事件。该函数将判定当前是否升级(或连续升级),然后执行升级事件。 - - -core.tryUseItem(itemId) -尝试使用一个道具。 -对于怪物手册和楼传器,将分别调用core.openBook()和core.useFly()函数。 -对于中心对称飞行器,则会调用core.drawCenterFly()函数。 -对于其他的道具,将检查是否拥有,能否使用,并且进行使用。 -``` - -## icons.js - -icons.js主要是负责素材相关信息,比如某个素材在对应的图片上的位置。 - -```text -core.getClsFromId(id) -根据某个素材的ID获得该素材的cls - - -core.getTilesetOffset(id) -根据某个素材来获得对应的tileset和坐标信息。 -如果该素材不是tileset,则返回null。 -``` - -## items.js - -items.js主要负责一切和道具相关的内容。 - -```text -core.getItemEffect(itemId, itemNum) -即捡即用类的道具获得时的效果。实际对应道具图块属性中的itemEffect框。 - - -core.getItemEffectTip(itemId) -即捡即用类的道具获得时的额外提示,比如“,攻击+100”。 -实际对应道具图块属性中的itemEffectTip框。 - - -core.useItem(itemId, noRoute, callback) -尝试使用一个道具。实际对应道具图块属性中的useItemEffect框。 -此函数也会调用一遍core.canUseItem(),如果无法使用将直接返回。 -noRoute如果为真,则这次使用道具的过程不会被计入录像。 -使用道具完毕后,对于消耗道具将自动扣除,永久道具不会扣除。 - - -core.canUseItem(itemId) -当前能否使用某个道具。 -有些系统道具如破炸和上下楼器等,会在计算出目标点的坐标后存入core.status.event.ui。 -使用道具时将直接从core.status.event.ui调用,不会重新计算。 - - -core.itemCount(itemId) -获得某个道具的个数。 - - -core.hasItem(itemId) -当前是否拥有某个道具。等价于 core.itemCount(itemId) > 0 -请注意,装备上的装备不视为拥有该道具,即core.hasEquip()和core.hasItem()是完全不同的。 - - -core.hasEquip(itemId) -当前是否装备上某个装备。 -请注意,装备上的装备不视为拥有该道具,即core.hasEquip()和core.hasItem()是完全不同的。 - - -core.getEquip(equipType) -获得某个装备位的当前装备。equipType为装备类型,从0开始。 -如果该装备位没有装备则返回null,否则返回当前装备的ID。 - - -core.setItem(itemId, itemNum) -设置某个道具的个数。 - - -core.addItem(itemId, itemNum) -增减某个道具的个数,itemNum可不填默认为1。 - - -core.getEquipTypeByName(name) -根据装备位名称来找到一个空的装备孔,适用于多重装备,装备位名称可在全塔属性中设置。 -如果没有一个装备孔是该装备名称,则返回-1。 -譬如:core.getEquipTypeByName("武器")默认返回全塔属性中武器对应的装备孔号0。 - - -core.getEquipTypeById(equipId) -获得某个装备的装备类型。 -如果其type写的是装备名(多重装备),则调用core.getEquipTypeByName()函数。 - - -core.canEquip(equipId, hint) -当前能否穿上某个装备。如果hint为真,则不可装备时会气泡提示原因。 - - -core.loadEquip(equipId, callback) -穿上某个装备,equipId为装备id。 - - -core.unloadEquip(equipType, callback) -脱下某个装备孔的装备。 -譬如core.unloadEquip(0)则为脱下0号装备孔中的装备,默认0号装备孔对应“武器”,1号装备孔对应“盾牌” - - -core.compareEquipment(compareEquipId, beComparedEquipId) -比较两个套装的差异。 -此函数将对所有的勇士属性包括生命魔力攻防护盾金币等进行比较。 -如果存在差异的,将作为一个对象返回其差异内容。 - - -core.quickSaveEquip(index) -保存当前套装。index为保存的套装编号。 - - -core.quickLoadEquip() -读取当前套装。index为读取的套装编号。 - - -core.getEquippedStatus(name) -获得装备直接增加的属性数据。 -``` - -## loader.js - -loader.js主要负责资源加载相关的内容。 - -```text -core.loadImage(imgName, callback) -从 project/images/ 中加载一张图片。imgName为图片名。 -callback为执行完毕的回调函数,接收(imgName, image)即图片名和图片内容作为参数。 -如果图片不存在或加载失败则会在控制台打出一条错误日志,不会执行回调。 - - -core.loadImages(names, toSave, callback) -从 project/images/ 中加载若干张图片。 -names为一个图片名的列表,toSave为加载并存到的对象。 -callback为全部加载完毕执行的回调。 - - -core.loadOneMusic(name) -从 project/sounds/ 或第三方中加载一个音乐,并存入core.material.bgms中。name为音乐名。 - - -core.loadOneSound(name) -从 project/sounds/ 中加载一个音效,并存入core.material.sounds中。name为音效名。 - - -core.loadBgm(name) -预加载一个bgm并加入缓存列表core.musicStatus.cachedBgms。 -此函数将会检查bgm的缓存,预加载和静音播放。 -如果缓存列表溢出(core.musicStatus.cacheBgmCount)则通过LRU算法选择一个bgm并调用core.freeBgm()。 - - -core.freeBgm(name) -释放一个bgm的内存并移出缓存列表。如果该bgm正在播放则也会立刻停止。 -``` - -## map.js - -maps.js负责一切和地图相关的处理内容,包括如下几个方面: -- 地图的初始化,保存和读取,地图数组的生成 -- 是否可移动或瞬间移动的判定 -- 地图的绘制 -- 获得某个点的图块信息 -- 启用和禁用图块,改变图块 -- 移动/跳跃图块,淡入淡出图块 -- 全局动画控制,动画的绘制 - -```text -// ------ 地图的初始化,保存和读取,地图数组的生成 ------ // - -core.loadFloor(floorId, map) -从楼层或者存档中生成core.status.maps的内容。 -map为存档信息,如果某项在map中不存在则会从core.floors中读取。 - - -core.getNumberById(id) -给定一个图块ID,找到图块对应的图块编号。 - - -core.initBlock(x, y, id, addInfo, eventFloor) -给定一个数字,初始化一个图块信息。 -x和y为坐标,id为数字或者可以:t或:f结尾表示初始是启用还是禁用状态。 -addInfo如果为true则会填充上图块的默认信息,比如给怪物添加battle触发器。 -eventFloor如果设置为某个楼层信息,则会填充上该点的自定义或楼层切换事件。 - - -core.compressMap(mapArr, floorId) -压缩地图。mapArr为要压缩的二维数组,floorId为对应的楼层。 -此函数将把mapArr和对应的楼层中的数组进行比较,并只取差异值进行存储。 -通过这种压缩地图的方式,不仅节省了存档空间,还支持了任意修改地图的接档。 - - -core.decompressMap(mapArr, floorId) -解压缩地图。mapArr为压缩后的地图,floorId为对应的楼层。 -此函数返回解压后的二维数组。 - - -core.saveMap(floorId) -将某层楼的数据生成存档所保存的内容。在core.saveData()中被调用。 - - -core.loadMap(data, floorId) -从data中读取楼层数据,并调用core.loadFloor()进行初始化。 - - -core.removeMaps(fromId, toId) -删除某个区域的地图。调用此函数后,这些楼层将不可飞,不可被浏览地图,也不计入存档。 -fromId和toId为要删除的起终点楼层ID;toId也可以不填代表只删除某一层。 -此函数适用于高层塔的砍层,例如每100层一个区域且互相独立,不可再返回的情况。 - - -core.resizeMap(floorId) -根据某层楼的地图大小来调整大地图的画布大小。floorId可为null表示当前层。 - - -core.getMapArray(floorId, showDisable) -生成某层楼的二维数组。floorId可不填代表当前楼层。 -showDisable若为真,则对于禁用的点会加上:f表示,否则视为0。 - - -core.getMapBlocksObj(floorId, showDisable) -以x,y的形式返回每个点的图块信息。floorId可不填表示当前楼层。 -此函数将返回 {"0,0": {...}, "0,1": {...}} 这样的结构,其中内部为对应点的block信息。 - - -core.getBgMapArray(floorId, noCache) -获得某层楼的背景层的二维数组。floorId可不填表示当前楼层。 -如果noCache为真则重新从剧本中读取而不使用缓存数据。 - - -core.getFgMapArray(floorId, noCache) -获得某层楼的前景层的二维数组。floorId可不填表示当前楼层。 -如果noCache为真则重新从剧本中读取而不使用缓存数据。 - - -core.getBgNumber(x, y, floorId, noCache) -获得某层楼的背景层中某个点的数字。floorId可不填表示当前楼层。 -如果noCache为真则重新从剧本中读取而不使用缓存数据。 -本函数实际等价于 core.getBgMapArray(floorId, noCache)[y][x] - - -core.getBgNumber(x, y, floorId, noCache) -获得某层楼的前景层中某个点的数字。参数和方法同上。 - -// ------ 是否可移动或瞬间移动的判定 ------ // - -core.generateMovableArray(floorId, x, y, direction) -生成全图或某个点的可通行方向数组。floorId为楼层Id,可不填默认为当前点。 -这里的可通行方向数组,指的是["up","down","left","right"]中的一个或多个组成的数组。 - - 如果不设置x和y,则会返回一个三维数组,其中每个点都是一个该点可通行方向的数组。 - - 如果设置了x和y但没有设置direction,则只会返回该点的可通行方向数组, - - 如果设置了x和y以及direction,则会判定direction是否在该点可通行方向数组中,并返回true或false。 -可以使用core.inArray()来判定某个方向是否在可通行方向数组中。 - - -core.canMoveHero(x, y, direction, floorId) -某个点是否可朝某个方向移动。x和y可选,不填或为null则默认为勇士当前点。 -direction可选,不填或为null则默认勇士当前朝向。floorId不填则默认为当前楼层。 -此函数将直接调用 core.generateMovableArray() 进行判定。 - - -core.canMoveDirectly(destX, destY) -当前能否瞬间移动到某个点。 -如果可以瞬移则返回非负数,其值为该次瞬移所少走的步数;如果不能瞬移则返回-1。 - - -core.automaticRoute(destX, destY) -找寻到目标点的一条自动寻路路径。 - -// ------ 绘制地图相关 ------ // - -core.drawBlock(block, animate) -重新绘制一个图块,block为图块信息。 -如果animate不为null则代表是通过全局动画的绘制,其值为当前的帧数。 - - -core.generateGroundPattern(floorId) -生成某个楼层的地板信息。floorId不填默认为当前楼层。 -该函数可被怪物手册、对话框帧动画等地方使用。 - - -core.drawMap(floorId, callback) -绘制某层楼的地图。floorId为目标楼层ID,可不填表示当前楼层。 -此函数会将core.status.floorId设置为floorId,并设置core.status.thisMap。 -将依次调用core.drawBg(), core.drawEvents()和core.drawFg()函数,最后绘制勇士和更新地图显伤。 - - -core.drawBg(floorId, ctx) -绘制背景层。floorId为目标楼层ID,可不填表示当前楼层。 -如果ctx不为null,则背景层将绘制在该画布上而不是bg层上(drawThumbnail使用)。 -可以通过复写该函数,调整_drawFloorImages和_drawBgFgMap的顺序来调整背景图块和贴图的遮挡顺序。 - - -core.drawEvents(floorId, blocks, ctx) -绘制事件层。floorId为目标楼层ID,可不填表示当前楼层。 -block表示要绘制的图块列表,可不填使用当前楼层的图块列表。 -如果ctx不为null,则背景层将绘制在该画布上而不是event层上(drawThumbnail使用)。 - - -core.drawFg(floorId, ctx) -绘制前景层。floorId为目标楼层ID,可不填表示当前楼层。 -如果ctx不为null,则背景层将绘制在该画布上而不是fg层上(drawThumbnail使用)。 -可以通过复写该函数,调整_drawFloorImages和_drawBgFgMap的顺序来调整前景图块和贴图的遮挡顺序。 - - -core.drawThumbnail(floorId, blocks, options, toDraw) -绘制一个楼层的缩略图。floorId为目标楼层ID,可不填表示当前楼层。 -block表示要绘制的图块列表,可不填使用当前楼层的图块列表。 -options为绘制选项(可为null),包括: - heroLoc: 勇士位置;heroIcon:勇士图标(默认当前勇士);damage:是否绘制显伤; - flags:当前的flags(在存读档时使用) -toDraw为要绘制到的信息(可为null,或为一个画布名),包括: - ctx:要绘制到的画布(名);x,y:起点横纵坐标(默认0);size:绘制大小(默认416/480); - all:是否绘制全图(默认false);centerX,centerY:截取中心(默认为地图正中心) - -// ------ 获得某个点的图块信息 ------ // - -core.noPass(x, y, floorId) -判定某个点是否有noPass(不可通行)的图块。 - - -core.npcExists(x, y, floorId) -判定某个点是否有NPC的存在。 - - -core.terrainExists(x, y, id, floorId) -判定某个点是否有(id对应的)地形存在。 -如果id为null,则只要存在terrains即为真,否则还会判定对应点的ID。 - - -core.stairExists(x, y, floorId) -判定某个点是否存在楼梯。 - - -core.nearStair() -判定当前勇士是否在楼梯上或旁边(距离不超过1)。 - - -core.enemyExists(x, y, id, floorId) -判定某个点是否有(id对应的)怪物存在。 -如果id为null,则只要存在怪物即为真,否则还会判定对应点的怪物ID。 -请注意,如果需要判定某个楼层是否存在怪物请使用core.hasEnemyLeft()函数。 - - -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。如果该点不存在图块则返回null。 - - -core.getBlockCls(x, y, floorId, showDisable) -获得某个点的图块类型。如果该点不存在图块则返回null。 - - -core.getBlockInfo(block) -根据某个的图块信息获得其详细的素材信息。 -如果参数block为字符串,则视为图块ID;如果参数为数字,则视为图块的数字。 -此函数将返回一个非常详尽的素材信息,目前包括如下几项: -number:素材数字;id:素材id;cls:素材类型;image:素材所在的素材图片;animate:素材的帧数。 -posX, posY:素材在该素材图片上的位置;height:素材的高度;faceIds:NPC朝向记录。 - - -core.searchBlock(id, floorId, showDisable) -搜索一个图块出现过的所有位置。id为图块ID,也可以传入图块的数字。 -id支持通配符搜索,比如"*Door"可以搜索所有的门,"unknownEvent*"可以所有所有的unknownEvent。 -floorId为要搜索的楼层,可以是一个楼层ID,或者一个楼层数组。如果floorId不填则只搜索当前楼层。 -showDisable如果为真,则对于禁用的图块也会返回。 -此函数将返回一个数组,每一项为一个搜索到的结果: -{"floorId": ..., "index": ..., "block": {...}, "x": ..., "y": ...} -即包含该图块所在的楼层ID,在该楼层的blocks数组的索引,图块内容,和横纵坐标。 - - -// ------ 启用和禁用图块,改变图块 ------ // - -core.showBlock(x, y, floorId) -将某个点从禁用变成启用状态。floorId可不填或null表示当前楼层。 - - -core.hideBlock(x, y, floorId) -将某个点从启用变成禁用状态,但不会对其进行删除。floorId可不填或null表示当前楼层。 -此函数不会实际将该块从地图中进行删除,而是将该点设置为禁用,以供以后可能的启用事件。 - - -core.removeBlock(x, y, floorId) -将从启用变成禁用状态,并尽可能将其从地图上删除。 -和hideBlock相比,如果该点不存在自定义事件(比如门或普通的怪物),则将直接从地图中删除。 -如果存在自定义事件,则简单的禁用它,以供以后可能的启用事件。 - - -core.removeBlockByIndex(index, floorId) -每个楼层的图块存成一个数组,index即为该数组中的索引,每个索引对应该地图中的一个图块 -根据索引从地图的block数组中尽可能删除一个图块。floorId可不填或null表示当前楼层。 - - -core.removeBlockByIndexes(indexes, floorId) -indexes为由索引组成的数组,如[0,1]等 -根据索引数组从地图的block数组中尽可能删除一系列图块。floorId可不填或null表示当前楼层。 - - -core.canRemoveBlock(block, floorId) -block为图块信息,可由core.getBlock获取 -判定当前能否完全删除某个图块。floorId可不填或null表示当前楼层。 -如果该点存在自定义事件,或者是重生怪,则不可进行删除。 - - -core.showBgFgMap(name, loc, floorId, callback) -显示某层楼中某个背景/前景层的图块。name只能为'bg'或'fg'表示背景或前景层。 -loc为该点坐标,floorId可不填默认为当前楼层。callback为执行完毕的回调。 - - -core.hideBgFgMap(name, loc, floorId, callback) -隐藏某层楼中某个背景/前景层的图块。name只能为'bg'或'fg'表示背景或前景层。 -loc为该点坐标,floorId可不填默认为当前楼层。callback为执行完毕的回调。 - - -core.showFloorImage(loc, floorId, callback) -显示某层楼中的某个楼层贴图。loc为该贴图的左上角坐标。floorId可省略表示当前楼层。 - - -core.hideFloorImage(loc, floorId, callback) -隐藏某层楼中的某个楼层贴图。loc为该贴图的左上角坐标。floorId可省略表示当前楼层。 - - -core.setBlock(number, x, y, floorId) -改变某个楼层的某个图块。 -number为要改变到的数字,也可以传入图块id(将调用core.getNumberById()来获得数字)。 -x,y和floorId为目标点坐标和楼层,可忽略为当前点和当前楼层。 - - -core.replaceBlock(fromNumber, toNumber, floorId) -将某个或某些楼层中的所有某个图块替换成另一个图块 -fromNumber和toNumber为要被替换和替换到的数字。 -floorId可为某个楼层ID,或者一个楼层数组;如果不填只视为当前楼层。 -值得注意的是,使用此函数转了的点上的自定义事件可能无法被执行。 -如有需要,再对那些存在事件的点执行core.setBlock()即可 - - -core.setBgFgBlock(name, number, x, y, floorId) -设置前景/背景层的某个图块。name只能为'bg'或'fg'表示前景或背景层。 -number为要设置到的图块数字,x,y和floorId为目标点坐标和楼层,可忽略为当前点和当前楼层。 - - -core.resetMap(floorId) -重置某层或若干层的地图和楼层属性。 -floorId可为某个楼层ID,或者一个楼层数组如["MT1","MT2"](同时重置若干层);如果不填则只重置当前楼层。 - -// ------ 移动/跳跃图块,淡入淡出图块 ------ // - -core.moveBlock(x, y, steps, time, keep, callback) -移动一个图块,x和y为图块的坐标。 -steps为移动的数组,每一项只能是"up","down","left","right"之一。 -time为每一步的移动时间,不填默认为500ms。 -如果keep为真,则在移动完毕后将自动调用一个setBlock事件,改变目标点的图块(即不消失), -否则会按照time时间来淡出消失。callback会执行完毕后的回调。 - - -core.jumpBlock(sx, sy, ex, ey, time, keep, callback) -跳跃一个图块,sx和sy为图块的坐标,ex和ey为目标坐标。time为整个跳跃过程中的全程用时,不填默认500。 -如果keep为真,则在移动完毕后将自动调用一个setBlock事件,改变目标点的图块(即不消失), -否则会按照time时间来淡出消失。callback会执行完毕后的回调。 - - -core.animateBlock(loc, type, time, callback) -淡入/淡出一个或多个图块。 -loc为一个图块坐标,或者一个二维数组表示一系列图块坐标(将同时显示和隐藏)。 -type只能为'show'或'hide'表示是淡入但是淡出。time为动画时间,callback为执行完毕的回调。 - -// ------ 全局动画控制,动画的绘制 ------ // - -core.addGlobalAnimate(block) -添加一个全局帧动画。 - - -core.removeGlobalAnimate(x, y, name) -删除一个或全部的全局帧动画。name可为'bg',null或'fg'表示某个图层。 -x和y如果为null,则会删除全部的全局帧动画,否则只会删除该点的该层的帧动画。 - - -core.drawBoxAnimate() -绘制UI层的box动画,如怪物手册和对话框中的帧动画等。 - - -core.drawAnimate(name, x, y, alignWindow, callback) -绘制一个动画。name为动画名,x和y为绘制的基准坐标,callback为绘制完毕的回调函数。 -此函数将播放动画音效,并异步开始绘制该动画。 -此函数会返回一个动画id,可以通过core.stopAnimate()立刻停止该动画的播放。 - - -core.drawHeroAnimate(name, callback) -绘制一个跟随勇士行动的动画。name为动画名,callback为绘制完毕的回调函数。 -此函数将播放动画音效,并异步开始绘制该动画。 -此函数会返回一个动画id,可以通过core.stopAnimate()立刻停止该动画的播放。 - - -core.stopAnimate(id, doCallback) -立刻停止某个动画的播放。id为上面core.drawAnimate的返回值。 -如果doCallback为真,则会执行该动画所对应的回调函数。 +hasAsync: fn() -> bool +当前是否有未处理完毕的异步事件 + +openEquipbox: fn(fromUserAction?: bool) +点击装备栏时的打开操作 + +recoverEvents: fn(data?: ?) +恢复一个事件 + +setGlobalFlag: fn(name: string, value: bool) +设置一个系统开关 +例如:core.setGlobalFlag('steelDoorWithoutKey', true); // 使全塔的所有铁门都不再需要钥匙就能打开 +name: 系统开关的英文名 +value: 开关的新值,您可以用!core.flags[name]简单地表示将此开关反转 + +moveImage: fn(code: number, to?: [number], opacityVal?: number, time?: number, callback?: fn()) +移动一张图片并/或改变其透明度 +例如:core.moveImage(1, null, 0.5); // 1秒内把1号图片变为50%透明 +code: 图片编号 +to: 新的左上角坐标,省略表示原地改变透明度 +opacityVal: 新的透明度,省略表示不变 +time: 移动用时,单位为毫秒。不填视为1秒 +callback: 图片移动完毕后的回调函数,可选 + +openSettings: fn(fromUserAction?: bool) +点击设置按钮时的操作 + +afterPushBox: fn() +推箱子后的事件 + +unregisterSystemEvent: fn(type: string) +注销一个系统事件 + +trigger: fn(x?: number, y?: number, callback?: fn()) +触发(x,y)点的系统事件;会执行该点图块的script属性,同时支持战斗(会触发战后)、道具(会触发道具后)、楼层切换等等 +callback: 执行完毕的回调函数 + +restart: fn() +重新开始游戏;此函数将回到标题页面 + +doEvent: fn(data?: ?, x?: number, y?: number, prefix?: string) +执行一个自定义事件 + +win: fn(reason?: string, norank?: bool, noexit?: bool) +游戏获胜事件 + +setGlobalAttribute: fn(name: string, value: string) +设置全塔属性 + +openToolbox: fn(fromUserAction?: bool) +点击工具栏时的打开操作 + +setVolume: fn(value: number, time?: number, callback?: fn()) +调节bgm的音量 +例如:core.setVolume(0, 100, core.jumpHero); // 0.1秒内淡出bgm,然后主角原地跳跃半秒 +value: 新的音量,为0或不大于1的正数。注意系统设置中是这个值的平方根的十倍 +time: 渐变用时,单位为毫秒。不填或小于100毫秒都视为0 +callback: 渐变完成后的回调函数,可选 + +pushEventLoc: fn(x?: number, y?: number, floorId?: string) -> bool +将当前点坐标入栈 + +openKeyBoard: fn(fromUserAction?: bool) +点击虚拟键盘时的打开操作 + +insertCommonEvent: fn(name?: string, args?: [?], x?: number, y?: number, callback?: fn(), addToLast?: bool) +插入一个公共事件 +例如:core.insertCommonEvent('毒衰咒处理', [0]); +name: 公共事件名;如果公共事件不存在则直接忽略 +args: 参数列表,为一个数组,将依次赋值给 flag:arg1, flag:arg2, ... +x: 新的当前点横坐标,可选 +y: 新的当前点纵坐标,可选 +callback: 新的回调函数,可选 +addToLast: 插入的位置,true表示插入到末尾,否则插入到开头 + +hideImage: fn(code: number, time?: number, callback?: fn()) +隐藏一张图片 +例如:core.hideImage(1, 1000, core.jumpHero); // 1秒内淡出1号图片,然后主角原地跳跃半秒 +code: 图片编号 +time: 淡出时间,单位为毫秒 +callback: 图片完全消失后的回调函数,可选 + +visitFloor: fn(floorId?: string) +到达某楼层 + +openQuickShop: fn(fromUserAction?: bool) +点击快捷商店按钮时的打开操作 + +afterBattle: fn(enemyId?: string, x?: number, y?: number) +战斗结束后触发的事件 + +pushBox: fn(data?: ?) +推箱子 + +autoEventExecuted: fn(symbol?: string, value?: ?) -> bool +当前是否执行过某个自动事件 + +onSki: fn(number?: number) -> bool +当前是否在冰上 + +showImage: fn(code: number, image: string|image, sloc?: [number], loc?: [number], opacityVal?: number, time?: number, callback?: fn()) +显示一张图片 +例如:core.showImage(1, core.material.images.images['winskin.png'], [0,0,128,128], [0,0,416,416], 0.5, 1000); // 裁剪winskin.png的最左边128×128px,放大到铺满整个视野,1秒内淡入到50%透明,编号为1 +code: 图片编号,为不大于50的正整数,加上100后就是对应画布层的z值,较大的会遮罩较小的,注意色调层的z值为125,UI层为140 +image: 图片文件名(可以是全塔属性中映射前的中文名)或图片对象(见上面的例子) +sloc: 一行且至多四列的数组,表示从原图裁剪的左上角坐标和宽高,可选 +loc: 一行且至多四列的数组,表示图片在视野中的左上角坐标和宽高,可选 +opacityVal: 不透明度,为小于1的正数。不填视为1 +time: 淡入时间,单位为毫秒。不填视为0 +callback: 图片完全显示出来后的回调函数,可选 + +getItem: fn(id: string, num?: number, x?: number, y?: number, callback?: fn()) +获得道具并提示,如果填写了坐标就会删除该点的该道具 +例如:core.getItem('book'); // 获得敌人手册并提示 +id: 道具id,必填 +num: 获得的数量,不填视为1,填了就别填坐标了 +x: 道具的横坐标,可选 +y: 道具的纵坐标,可选 +callback: 回调函数,可选 + +registerSystemEvent: fn(type: string, func: fn(data?: ?, callback?: fn())) +注册一个系统事件 +type: 事件名 +func: 为事件的处理函数,可接受(data,callback)参数 + +startGame: fn(hard: string, seed: number, route: string, callback?: fn()) +开始新游戏 +例如:core.startGame('咸鱼乱撞', 0, ''); // 开始一局咸鱼乱撞难度的新游戏,随机种子为0 +hard: 难度名,会显示在左下角(横屏)或右下角(竖屏) +seed: 随机种子,相同的种子保证了录像的可重复性 +route: 经由base64压缩后的录像,用于从头开始的录像回放 +callback: 回调函数,可选 + +doSystemEvent: fn(type: string, data?: ?, callback?: fn()) +执行一个系统事件 + +resetGame: fn(hero?: ?, hard?: ?, floorId?: string, maps?: ?, values?: ?) +初始化游戏 + +setFloorInfo: fn(name: string, values: ?, floorId?: string, prefix?: string) +设置一项楼层属性并刷新状态栏 +例如:core.setFloorInfo('ratio', 2, 'MT0'); // 把主塔0层的血瓶和宝石变为双倍效果 +name: 要修改的属性名 +values: 属性的新值。 +floorId: 楼层id,不填视为当前层 +prefix: 独立开关前缀,一般不需要 + +openDoor: fn(x: number, y: number, needKey?: bool, callback?: fn()) +开门(包括三种基础墙) +例如:core.openDoor(0, 0, true, core.jumpHero); // 打开左上角的门,需要钥匙,然后主角原地跳跃半秒 +x: 门的横坐标 +y: 门的纵坐标 +needKey: true表示需要钥匙,会导致机关门打不开 +callback: 门完全打开后或打不开时的回调函数,可选 + +setEnemy: fn(id: string, name: string, value: ?, prefix?: string) +设置一项敌人属性并计入存档 +例如:core.setEnemy('greenSlime', 'def', 0); // 把绿头怪的防御设为0 +id: 敌人id +name: 属性的英文缩写 +value: 属性的新值,可选 +prefix: 独立开关前缀,一般不需要,下同 + +autoEventExecuting: fn(symbol?: string, value?: ?) -> bool +当前是否在执行某个自动事件 + +checkAutoEvents: fn() +检测自动事件 + +showGif: fn(name?: string, x?: number, y?: number) +绘制一张动图或擦除所有动图 +例如:core.showGif(); // 擦除所有动图 +name: 动图文件名,可以是全塔属性中映射前的中文名 +x: 动图在视野中的左上角横坐标 +y: 动图在视野中的左上角纵坐标 + +unregisterEvent: fn(type: string) +注销一个自定义事件 + +jumpHero: fn(ex?: number, ey?: number, time?: number, callback?: fn()) +主角跳跃,跳跃勇士。ex和ey为目标点的坐标,可以为null表示原地跳跃。time为总跳跃时间。 +例如:core.jumpHero(); // 主角原地跳跃半秒 +ex: 跳跃后的横坐标 +ey: 跳跃后的纵坐标 +time: 跳跃时长,单位为毫秒。不填视为半秒 +callback: 跳跃完毕后的回调函数,可选 + +closeDoor: fn(x: number, y: number, id: string, callback?: fn()) +关门,目标点必须为空地 +例如:core.closeDoor(0, 0, 'yellowWall', core.jumpHero); // 在左上角关掉一堵黄墙,然后主角原地跳跃半秒 +x: 横坐标 +y: 纵坐标 +id: 门的id,也可以用三种基础墙 +callback: 门完全关上后的回调函数,可选 + +eventMoveHero: fn(steps: [step], time?: number, callback?: fn()) +强制移动主角(包括后退),这个函数的作者已经看不懂这个函数了 +例如:core.eventMoveHero(['forward'], 125, core.jumpHero); // 主角强制前进一步,用时1/8秒,然后主角原地跳跃半秒 +steps: 步伐数组,注意后退时跟随者的行为会很难看 +time: 每步的用时,单位为毫秒。0或不填则取主角的移速,如果后者也不存在就取0.1秒 +callback: 移动完毕后的回调函数,可选 + +changeFloor: fn(floorId: string, stair?: string, heroLoc?: {x?: number, y?: number, direction?: string}, time?: number, callback?: fn()) +场景切换 +例如:core.changeFloor('MT0'); // 传送到主塔0层,主角坐标和朝向不变,黑屏时间取用户定义的值 +floorId: 传送的目标地图id,可以填':before'和':after'分别表示楼下或楼上 +stair: 传送的位置 +heroLoc: 传送的坐标;会覆盖stair +time: 传送的黑屏时间,单位为毫秒;不填为用户设置值 +callback: 传送的回调函数 + +getCommonEvent: fn(name: string) -> [?] +获得一个公共事件 + +lose: fn(reason?: string) +游戏失败事件 + +gameOver: fn(ending?: string, fromReplay?: bool, norank?: bool) +游戏结束 +例如:core.gameOver(); // 游戏失败 +ending: 结局名,省略表示失败 +fromReplay: true表示在播放录像,可选 +norank: true表示不计入榜单,可选 + +useFly: fn(fromUserAction?: bool) +点击楼层传送器时的打开操作 + +tryUseItem: fn(itemId: string) +尝试使用一个道具 +例如:core.tryUseItem('pickaxe'); // 尝试使用破墙镐 +itemId: 道具id,其中敌人手册、传送器和飞行器会被特殊处理 ``` ## ui.js @@ -1631,281 +1159,297 @@ ui.js负责一切UI界面的绘制。主要包括三个部分: - 动态创建画布相关的API ```text -// ------ 设置某个画布的属性的相关API ------// -这系列函数的name一般都是画布名,可以是系统画布或动态创建的画布。 -但也同时也允许直接传画布的context本身,将返回自身。 +resizeCanvas: fn(name: string, x: number, y: number) +重新设置一个自定义画布的大小 +deleteCanvas: fn(name: string) +删除一个自定义画布 -core.getContextByName(name) -根据画布名找到一个画布的context;支持系统画布和自定义画布。 -如果不存在画布此函数返回null。 -该参数也可以直接传画布的context自身,则返回自己。 +drawSLPanel: fn(index?: ?, refresh?: bool) +绘制存档/读档界面 +drawKeyBoard: fn() +绘制虚拟键盘 -core.clearMap(name) -清空某个画布图层。 -该函数的name也可以是'all',若为'all'则为清空所有系统画布。 +drawStorageRemove: fn() +绘制存档删除页面 +deleteAllCanvas: fn() +清空所有的自定义画布 -core.fillText(name, text, x, y, style, font, maxWidth) -在某个画布上绘制一段文字。 -text为要绘制的文本,x,y为要绘制的坐标,style可选为绘制的样式,font可选为绘制的字体。(下同) -style可直接使用"red","white"等或用"rgba(255,255,255,1)"或用"#FFFFFF"等方式来获得字体对应的颜色 -font的格式为"20px Verdana"前者为字体大小,后者为字体 -如果maxWidth不为null,则视为文字最大宽度,如果超过此宽度则会自动放缩文字直到自适应为止。 -请注意textAlign和textBaseline将决定绘制的左右对齐和上下对齐方式。 -具体可详见core.setTextAlign()和core.setTextBaseline()函数。 -譬如:core.fillText("ui", "这是要描绘的文字", 10, 10, "red", "20px Verdana", 100) -即是在ui图层上,以10,10为起始点,描绘20像素大小,Verdana字体的红色字,长度不超过100像素 +drawIcon: fn(name: string|CanvasRenderingContext2D, id: string, x: number, y: number, w?: number, h?: number, frame?: number) +在某个canvas上绘制一个图标 +drawFly: fn(page?: ?) +绘制楼层传送器 -core.fillBoldText(name, text, x, y, style, font) -在某个画布上绘制一个描黑边的文字。 +setOpacity: fn(name: string|CanvasRenderingContext2D, opacity: number) +设置某个canvas整体的透明度;此函数直接改变画布本身,对已经绘制的内容也生效 +如果仅想对接下来的绘制生效请使用setAlpha +drawAbout: fn() +绘制“关于”界面 -core.fillRect(name, x, y, width, height, style) -绘制一个矩形。width, height为矩形宽高,style可选为绘制样式。如果设置将调用core.setFillStyle()。(下同) +getTextContentHeight: fn(content: string, config?: ?) +获得某段文字的预计绘制高度;参数说明详见 drawTextContent +drawSwitchs: fn() +绘制系统设置界面 -core.strokeRect(name, x, y, width, height, style, lineWidth) -绘制一个矩形的边框。style可选为绘制样式,如果设置将调用core.setStrokeStyle()。 -lineWidth如果设置将调用core.setLineWidth()。(下同) +drawSyncSelect: fn() +绘制存档同步选择页面 +drawArrow: fn(name: string|CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number, style?: string, lineWidth?: number) +在某个canvas上绘制一个箭头 -core.drawLine(name, x1, y1, x2, y2, style, lineWidth) -绘制一条线,x1y1为起始点像素,x2y2为终止点像素。 +drawReplay: fn() +绘制回放界面 +strokeEllipse: fn(name: string|CanvasRenderingContext2D, x: number, y: number, a: number, b: number, angle?: number, style?: string, lineWidth?: number) +在某个canvas上绘制一个椭圆的边框 -core.drawArrow(name, x1, y1, x2, y2, style, lineWidth) -绘制一个箭头,x1y1为起始点像素,x2y2为终止点像素。 +fillCircle: fn(name: string|CanvasRenderingContext2D, x: number, y: number, r: number, style?: string) +在某个canvas上绘制一个圆 +参考资料:https://www.w3school.com.cn/tags/canvas_arc.asp +clearTip: fn() +清除左上角提示内容 -core.setFont(name, font) / core.setLineWidth(name, lineWidth) -设置一个画布的字体/线宽。 +strokeRoundRect: fn(name: string|CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number, style?: string, lineWidth?: number, angle?: number) +在某个canvas上绘制一个圆角矩形的边框 +getContextByName: fn(canvas: string|CanvasRenderingContext2D) -> CanvasRenderingContext2D +根据画布名找到一个画布的context;支持系统画布和自定义画布。如果不存在画布返回null。 +也可以传画布的context自身,则返回自己。 -core.setAlpha(name, font) / core.setOpacity(name, font) -设置一个画布的绘制不透明度和画布本身的不透明度。 -两者区别如下: - - setAlpha是设置"接下来绘制的内容的不透明度",不会对已经绘制的内容产生影响。 - > 比如setAlpha('ui', 0.5)则会在接下来的绘制中使用0.5的不透明度。 - - setOpacity是设置"画布本身的不透明度",已经绘制的内容也会产生影响。 - > 比如我已经在UI层绘制了一段文字,再setOpacity则也会让已经绘制的文字变得透明。 -尽量不要对系统画布使用setOpacity(因为会对已经绘制的内容产生影响),自定义创建的画布则不受此限制。 +drawImage: fn(name: string|CanvasRenderingContext2D, image: string|image, x: number, y: number, w?: number, h?: number, x1?: number, y1?: number, w1?: number, h1?: number, angle?: number) +在一个画布上绘制图片 +后面的8个坐标参数与canvas的drawImage的八个参数完全相同。 +name: 可以是系统画布之一,也可以是任意自定义动态创建的画布名 画布名称或者画布的context +image: 要绘制的图片,可以是一个全塔属性中定义的图片名(会从images中去获取;支持加':x',':y',':o'翻转),图片本身,或者一个画布。 +angle:旋转角度 +参考资料:http://www.w3school.com.cn/html5/canvas_drawimage.asp +drawTip: fn(text: string, id?: string, frame?: number) +左上角绘制一段提示 +text: 要提示的字符串,支持${}语法 +id: 要绘制的图标ID +frame: 要绘制该图标的第几帧 -core.setFillStyle(name, style) / core.setStrokeStyle(name, style) -设置一个画布的填充样式/描边样式。 +drawBackground: fn(left: string, top: string, right: string, bottom: string, posInfo?: {px: number, py: number, direction: string}) +绘制一个背景图,可绘制winskin或纯色背景;支持小箭头绘制 +fillEllipse: fn(name: string|CanvasRenderingContext2D, x: number, y: number, a: number, b: number, angle?: number, style?: string) +在某个canvas上绘制一个椭圆 -core.setTextAlign(name, align) -设置一个画布的文字横向对齐模式,这里的align只能为'left', 'right'和'center',分别对应左对齐,右对齐,居中。 -默认为'left'。 +setFillStyle: fn(name: string|CanvasRenderingContext2D, style: string) +设置某个canvas的绘制属性(如颜色等) +参考资料:https://www.w3school.com.cn/tags/canvas_fillstyle.asp +drawText: fn(contents: string, callback?: fn()) +地图中间绘制一段文字 -core.setTextBaseline(name, baseline) -设置一个画布的纵向对齐模式。有关textBaseline的说明可参见如下资料: -http://www.runoob.com/tags/canvas-textbaseline.html -默认值是'alphabetic'。 -请注意,系统画布在绘制前都是没有设置过textBaseline的,都是按照alphabetic进行坐标绘制。 -因此,如果你修改了系统画布的textBaseline来绘图,记得再绘制完毕后修改回来。 +drawConfirmBox: fn(text: string, yesCallback?: fn(), noCallback?: fn()) +绘制一个确认框 +此项会打断事件流,如需不打断版本的请使用core.myconfirm() +text: 要绘制的内容,支持 ${} 语法 +yesCallback: 点击确认后的回调 +noCallback: 点击取消后的回调 +fillPolygon: fn(name: string|CanvasRenderingContext2D, nodes?: [[number]], style?: string) +在某个canvas上绘制一个多边形 -core.calWidth(name, text, font) -计算一段文字在某个画布上的绘制宽度,此函数其实是ctx.measureText()的包装。 -font可选,如果存在则会先设置该画布上的字体。 -此函数不会对文字进行换行,如需换行版本请使用core.splitLines()函数。 +drawStatistics: fn(floorIds?: string) +绘制“数据统计”界面 +fillText: fn(name: string|CanvasRenderingContext2D, text: string, x: number, y: number, style?: string, font?: string, maxWidth?: number) +在某个画布上绘制一段文字 +text: 要绘制的文本 +style: 绘制的样式 +font: 绘制的字体 +最大宽度,超过此宽度会自动放缩 +参考资料:https://www.w3school.com.cn/tags/canvas_filltext.asp -core.splitLines(name, text, maxWidth, font) -计算一段文字在某画布上换行分割的结果。 -text为文字内容,maxWidth为最大宽度,可为null表示不自动换行。 -font可选,如果存在则会先设置该画布上的字体。 -此函数将返回一个换行完毕的文本列表。 +setTextBaseline: fn(name: string|CanvasRenderingContext2D, baseline: string) +设置某个canvas的基准线 +baseline: 可为alphabetic, top, hanging, middle, ideographic, bottom +参考资料:https://www.w3school.com.cn/tags/canvas_textbaseline.asp +drawSettings: fn() +绘制系统菜单栏 -core.drawImage(name, image, x, y, w, h, x1, y1, w1, h1) -在一张画布上绘制一张图片,此函数其实是ctx.drawImage()的包装。 -可以查看下面的文档以了解各项参数的信息: -http://www.w3school.com.cn/html5/canvas_drawimage.asp -这里的image允许传一个图片,画布。也允许传递图片名,将从你导入的图片中获取图片内容。 +loadCanvas: fn(name: string|CanvasRenderingContext2D) +加载某个canvas状态 +splitLines: fn(name: string|CanvasRenderingContext2D, text: string, maxWidth?: number, font?: string) +字符串自动换行的分割;具有标点禁则功能 -core.drawIcon(name, id, x, y, w, h) -在一张画布上绘制一个图标。 -id为注册过的图标ID,也可以使用状态栏的图标ID,例如lv, hp, up, save, settings等。 -x和y为绘制的左上角坐标;w和h可选为绘制的宽高,如果不填或null则使用该图标的默认宽高。 +setAlpha: fn(name: string|CanvasRenderingContext2D, alpha: number) +设置某个canvas接下来绘制的不透明度;不会影响已经绘制的内容 +如果需要修改画布本身的不透明度请使用setOpacity +参考资料:https://www.w3school.com.cn/tags/canvas_globalalpha.asp +setLineWidth: fn(name: string|CanvasRenderingContext2D, lineWidth: number) +设置某个canvas的线宽度 +参考资料:https://www.w3school.com.cn/tags/canvas_linewidth.asp -// ------ 具体的某个UI界面的绘制 ------ // -core.closePanel() -结束一切事件和UI绘制,关闭UI窗口,返回游戏。 -此函数将以此调用core.clearUI(),core.unlockControl(),并清空core.status.event里面的内容。 +drawEquipbox: fn(index?: ?) +绘制装备界面 +drawTextBox: fn(content: string, showAll?: bool) +绘制一个对话框 -core.clearUI() -重置UI窗口。此函数将清掉所有的UI帧动画和光标,清空UI画布,并将alpha设为1。 +relocateCanvas: fn(name: string, x: number, y: number) +重新定位一个自定义画布 +closePanel: fn() +结束一切事件和绘制,关闭UI窗口,返回游戏进程 -core.drawTip(text, id, clear) -在左上角以气泡的形式绘制一段提示。 -text为文字内容,仅支持${}的表达式计算,不支持换行和变色。 -id可选,为同时绘制的图标ID,如果不为null则会同时绘制该图标(仅对32x32的素材有效)。 -也可以使用状态栏的图标ID,例如lv, hp, up, save, settings等。 -如果clear为true,则会清空当前所有正在显示的提示。 +textImage: fn(content: string, lineHeight?: number) -> image +文本图片化 +drawStatusBar: fn() +绘制状态栏 -core.clearTip() -清空当前所有正在显示的提示。 +setStrokeStyle: fn(name: string|CanvasRenderingContext2D, style: string) +设置某个canvas边框属性 +参考资料:https://www.w3school.com.cn/tags/canvas_strokestyle.asp +clearUI: fn() +清空UI层内容 -core.drawText(content, callback) -绘制一段文字。contents为一个字符串或一个字符串数组,callback为全部绘制完毕的回调。 -支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t和\b的语法。 -如果当前在事件处理中或录像回放中,则会自动转成core.insertAction处理。 -不建议使用该函数,如有绘制文字的需求请尽量使用core.insertAction()插入剧情文本事件。 +drawWindowSkin: fn(background: string, ctx: string|CanvasRenderingContext2D, x: number, y: number, w: string, h: string, direction?: string, px?: number, py?: number) +绘制WindowSkin +drawGameInfo: fn() +绘制游戏信息界面 -core.drawWindowSelector(background, x, y, w, h) -绘制一个WindowSkin的闪烁光标。background可为winskin的图片名或图片本身。 -x,y,w,h为绘制的左上角位置和宽高,都是像素为单位。 +fillRect: fn(name: string|CanvasRenderingContext2D, text: string, x: number, y: number, style?: string, font?: string) +绘制一个矩形。style可选为绘制样式 +text: 要绘制的文本 +style: 绘制的样式 +font: 绘制的字体 +参考资料:https://www.w3school.com.cn/tags/canvas_fillrect.asp +drawScrollText: fn(content: string, time: number, lineHeight?: number, callback?: fn()) +绘制滚动字幕 -core.drawWindowSkin(background, ctx, x, y, w, h, direction, px, py) -绘制一个WindowSkin。background可为winskin的图片名或图片本身。 -ctx为画布名或画布本身,x,y,w,h为左上角位置和宽高,都是像素为单位。 -direction, px, py可选,如果设置则会绘制一个对话框箭头。 +strokePolygon: fn(name: string|CanvasRenderingContext2D, nodes?: [[number]], style?: string, lineWidth?: number) +在某个canvas上绘制一个多边形的边框 +strokeCircle: fn(name: string|CanvasRenderingContext2D, x: number, y: number, r: ?, style?: string, lineWidth?: number) +在某个canvas上绘制一个圆的边框 +参考资料:https://www.w3school.com.cn/tags/canvas_arc.asp -core.drawBackground(left, top, right, bottom, posInfo) -绘制一个背景图。此函数将使用你在【剧情文本设置】中设置的背景,即用纯色或WindowSkin来绘制。 -left, top, right, bottom为你要绘制的左上角和右下角的坐标。 -posInfo如果不为null则是一个含position, px和py的对象,表示一个对话框箭头的绘制。 +drawLocalSaveSelect: fn() +绘制单存档界面 +drawWaiting: fn(text: string) +绘制等待界面 -core.drawTextContent(ctx, content, config) -根据配置在某个画布上绘制一段文字。此函数会被core.drawTextBox()所调用。 -ctx为画布名或画布本身,如果不设置则会忽略该函数。 -content为要绘制的文字内容,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等) - ,但不支持支持\t和\b的语法。 -config为绘制的配置项,目前可以包括如下几项: - - left, top:在该画布上绘制的左上角像素位置,不设置默认为(0,0)。 - > 该函数绘制时会将textBaseline设置为'top',因此只需要考虑第一个字的左上角位置。 - - maxWidth:单行最大宽度,超过此宽度将自动换行,不设置不会自动换行。 - - color:默认颜色,为#XXXXXX形式。如果不设置则使用剧情文本设置中的正文颜色。 - - bold:是否粗体。如果不设置默认为false。 - - align:文字对齐方式,仅在maxWidth设置时有效,默认为'left'。 - - fontSize:字体大小,如果不设置则使用剧情文本设置中的正文字体大小。 - - lineHeight:绘制的行距值,如果不设置则使用fontSize*1.3(即1.3倍行距)。 - - time:打字机效果。若不为0,则会逐个字进行绘制,并设置core.status.event.interval定时器。 - - interval:字符间的间距。值表示绘制每个字符之间间隔的距离,默认为0。 +setFont: fn(name: string|CanvasRenderingContext2D, font: string) +设置某个canvas的文字字体 +参考资料:https://www.w3school.com.cn/tags/canvas_font.asp +drawChoices: fn(content?: string, choices?: [?]) +绘制一个选项界面 -core.drawTextBox(content, showAll) -绘制一个对话框。content为一个字符串或一个字符串数组。 -支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t和\b的语法。 -该函数将使用用户在剧情文本设置中的配置项进行绘制。 -实际执行时,会计算文本框宽度并绘制背景,绘制标题和头像,再调用core.drawTextContent()绘制正文内容。 -showAll可选,如果为true则不会使用打字机效果而全部显示,主要用于打字机效果的点击显示全部。 +setFontForMaxWidth: fn(name: string|CanvasRenderingContext2D, text: string, maxWidth: number, font?: ?) -> string +根据最大宽度自动缩小字体 +clearMap: fn(name: string|CanvasRenderingContext2D, x?: number, y?: number, width?: number, height?: number) +清空某个画布图层 +name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名;还可以直接传画布的context本身。 +如果name也可以是'all',若为all则为清空所有系统画布。 +参考资料:https://www.w3school.com.cn/tags/canvas_clearrect.asp -core.drawScrollText(content, time, lineHeight, callback) -绘制一个滚动字幕。content为绘制内容,time为总时间(默认为5000),lineHeight为行距比例(默认为1.4)。 -滚动字幕将绘制在UI上,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),但不支持\t和\b效果。 -可以通过剧情文本设置中的align控制是否居中绘制,offset控制其距离左边的偏移量。 +drawTextContent: fn(ctx: string|CanvasRenderingContext2D, content: string, config: ?) +绘制一段文字到某个画布上面 +ctx: 要绘制到的画布 +content: 要绘制的内容;转义字符不允许保留 \t, \b 和 \f +config: 绘制配置项,目前暂时包含如下内容(均为可选) +left, top:起始点位置;maxWidth:单行最大宽度;color:默认颜色;align:左中右 +fontSize:字体大小;lineHeight:行高;time:打字机间隔 +返回值:绘制信息 +calWidth: fn(name: string|CanvasRenderingContext2D, text: string, font?: string) -> number +计算某段文字的宽度 +参考资料:https://www.w3school.com.cn/tags/canvas_measuretext.asp -core.textImage(content, lineHeight) -将文本图片化。content为绘制内容,lineHeight为行距比例(默认为1.4)。 -可以通过剧情文本设置中的align控制是否居中绘制。 -此函数将返回一个临时画布的canvas,供转绘到其他画布上使用。 +fillArc: fn(name: string|CanvasRenderingContext2D, x: number, y: number, r: number, start: number, end: number, style?: string) +在某个canvas上绘制一个扇形 +参考资料:https://www.w3school.com.cn/tags/canvas_arc.asp +drawWindowSelector: fn(background: ?, x: number, y: number, w: number, h: number) +绘制选择光标 -core.drawChoices(content, choices) -绘制一个选项框。 -content可选,为选项上方的提示文字,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),也支持\t。 -choices必选,为要绘制的选项内容,是一个列表。其中的每一项: - - 可以是一个字符串,表示选项文字,将使用剧情文本设置中的正文颜色来绘制,仅支持${}表达式计算。 - - 或者是一个包含text, color和icon的对象。 - > text必选,为要绘制的文字内容,仅支持${}的表达式计算, - > color为要绘制的选项颜色,可以是#XXXXXX的格式或RGBA数组。不设置则使用正文颜色。 - > icon为要绘制的图标ID,支持使用素材的ID,或者系统图标。 +strokeArc: fn(name: string|CanvasRenderingContext2D, x: number, y: number, r: number, start: number, end: number, style?: string, lineWidth?: number) +在某个canvas上绘制一段弧 +参考资料:https://www.w3school.com.cn/tags/canvas_arc.asp +drawLine: fn(name: string|CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number, style?: string, lineWidth?: number) +在某个canvas上绘制一条线 +参考资料:https://www.w3school.com.cn/tags/canvas_lineto.asp -core.drawConfirmBox(text, yesCallback, noCallback) -绘制一个确认框。text为确认文字,支持\n换行(但不支持自动换行)和${}表达式计算。 -yesCallback和noCallback分别为确定和取消的回调函数。 -可以在调用此函数前设置core.status.event.selection来控制默认的选中项(0确定1取消)。 -此函数和core.myconfirm的区别主要在于: - - 此函数会清掉UI层原有的绘制信息,core.myconfirm不会清除。 - - 此函数可以用键盘进行操作,core.myconfirm必须用鼠标点击。 -另外请注意:本函数和事件流的执行不兼容,选择也不会进录像。 -如果需要在事件流中调用请使用提供选择项。 +drawPagination: fn(page?: ?, totalPage?: ?, y?: number) +绘制分页 +drawBookDetail: fn(index?: ?) +绘制怪物属性的详细信息 -core.drawWaiting(text) -绘制一个等待界面,一般用于同步存档之类的操作。 -调用此函数后,需要再调用core.closePanel()才会恢复游戏。 +drawToolbox: fn(index?: ?) +绘制道具栏 +drawHelp: fn() +绘制帮助页面 -core.drawPagination(page, totalPage, y) -绘制一个分页。y如果不设置则绘制在最后一行。 +drawQuickShop: fn() +绘制快捷商店选择栏 +drawCenterFly: fn() +绘制中心对称飞行器 -core.drawBook(index) / core.drawBookDetail(index) -绘制怪物手册,绘制怪物的详细信息。 +strokeRect: fn(name: string|CanvasRenderingContext2D, x: number, y: number, width: number, height: number, style: string) +绘制一个矩形的边框 +style: 绘制的样式 +参考资料:https://www.w3school.com.cn/tags/canvas_strokerect.asp +drawBook: fn(index?: ?) +绘制怪物手册 -core.drawFly(page) / core.drawCenterFly() / core.drawShop(shopId) -绘制楼传页面,中心对称飞行器,绘制商店 - - -core.drawToolbox(index) / core.drawEquipbox(index) / core.drawKeyBoard() -绘制道具栏,绘制装备栏,绘制虚拟键盘。 - - -core.drawMaps(index, x, y) / core.drawSLPanel(index, refresh) -绘制浏览地图,绘制存读档界面。 +fillRoundRect: fn(name: string|CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radius: number, style?: string, angle?: number) +在某个canvas上绘制一个圆角矩形 +fillBoldText: fn(name: string|CanvasRenderingContext2D, text: string, x: number, y: number, style?: string, strokeStyle?: string, font?: string) +在某个画布上绘制一个描边文字 +text: 要绘制的文本 +style: 绘制的样式 +strokeStyle: 要绘制的描边颜色 +font: 绘制的字体 -core.drawStatusBar() -自定义绘制状态栏,仅在状态栏canvas化开启时有效,实际被转发到了脚本编辑中。 +drawSyncSave: fn() +绘制存档同步界面 +saveCanvas: fn(name: string|CanvasRenderingContext2D) +保存某个canvas状态 -core.drawStatistics() -绘制数据统计。将从脚本编辑中获得要统计的数据列表,再遍历所有地图进行统计。 +drawCursor: fn() +绘制键盘光标 +createCanvas: fn(name: string, x: number, y: number, width: number, height: number, zIndex: number) -> CanvasRenderingContext2D +动态创建一个画布。 +name: 要创建的画布名,如果已存在则会直接取用当前存在的。 +x,y: 创建的画布相对窗口左上角的像素坐标 +width,height: 创建的长宽。 +zIndex: 创建的纵向高度(关系到画布之间的覆盖),z值高的将覆盖z值低的;系统画布的z值可在个性化中查看。 +返回创建的画布的context,也可以通过core.dymCanvas[name]调用。 -core.drawAbout() / core.drawHelp() -绘制关于界面,帮助界面。 +setTextAlign: fn(name: string|CanvasRenderingContext2D, align: string) +设置某个canvas的对齐 +参考资料:https://www.w3school.com.cn/tags/canvas_textalign.asp -// ------ 动态创建画布相关的API ------ // - - -core.ui.createCanvas(name, x, y, width, height, z) -动态创建一个自定义画布。name为要创建的画布名,如果已存在则会直接取用当前存在的。 -x,y为创建的画布相对窗口左上角的像素坐标,width,height为创建的长宽。 -z值为创建的纵向高度(关系到画布之间的覆盖),z值高的将覆盖z值低的;系统画布的z值可在个性化中查看。 -返回创建的画布的context,也可以通过core.dymCanvas[name]或core.getContextByName获得。 - - -core.ui.relocateCanvas(name, x, y) -重新定位一个自定义画布。x和y为画布的左上角坐标,name为画布名。 - - -core.ui.resizeCanvas(name, width, height, styleOnly) -重新设置一个自定义画布的大小。width和height为新设置的宽高。 -styleOnly控制是否只修改画布的显示大小(而不修改画布的内部大小)。 -如果styleOnly为true,则只修改其显示大小(即canvas.style.width); -否则,则会同时修改画布的显示大小和内部大小并清空画布内容。 - - -core.ui.deleteCanvas(name) -删除一个自定义画布。 - - -core.ui.deleteAllCanvas() -删除所有的自定义画布。 +drawMaps: fn(index?: ?, x?: number, y?: number) +绘制浏览地图界面 ``` ## utils.js @@ -1913,256 +1457,321 @@ core.ui.deleteAllCanvas() utils.js是一个工具函数库,里面有各个样板中使用到的工具函数。 ```text -core.replayText(text, need, times) -将一段文字中的${}(表达式)进行替换。need和time一般可以直接忽略。 +clamp: fn(x: number, a: number, b: number) -> number +将x限定在[a,b]区间内,注意a和b可交换 +例如:core.clamp(1200, 1, 1000); // 1000 +x: 原始值,!x为true时x一律视为0 +a: 下限值,大于b将导致与b交换 +b: 上限值,小于a将导致与a交换 +rand: fn(num?: number) -> number +不支持SL的随机数 +例如:1 + core.rand(6); // 随机生成一个小于7的正整数,模拟骰子的效果 +num: 填正数表示生成小于num的随机自然数,否则生成小于1的随机正数 +返回值:随机数,即使读档也不会改变结果 -core.replaceValue(value) -对一个表达式中的特殊规则进行替换,如status:xxx等。 -请注意,此项不会对独立开关如switch:A进行替换。 +clone: fn(data?: ?, filter?: fn(name: string, value: ?) -> bool, recursion?: bool) +深拷贝一个对象(函数将原样返回) +例如:core.clone(core.status.hero, (name, value) => (name == 'items' || typeof value == 'number'), false); // 深拷贝主角的属性和道具 +data: 待拷贝对象 +filter: 过滤器,可选,表示data为数组或对象时拷贝哪些项或属性,true表示拷贝 +recursion: 过滤器是否递归,可选。true表示过滤器也被递归 +返回值:拷贝的结果,注意函数将原样返回 +setLocalForage: fn(key: string, value?: ?, successCallback?: fn(), errorCallback?: fn()) +往数据库写入一段数据 -core.calValue(value, prefix, need, time) +getGlobal: fn(key: string, defaultValue?: ?) +读取一个全局存储,适用于global:xxx,支持录像。 +例如:if (core.getGlobal('一周目已通关', false) === true) core.getItem('dagger'); // 二周目游戏进行到此处时会获得一把屠龙匕首 +key: 全局变量名称,支持中文 +defaultValue: 可选,当此全局变量不存在或值为null、undefined时,用此值代替 +返回值:全局变量的值 + +replaceText: fn(text: string, prefix?: string) -> string +将一段文字中的${}(表达式)进行替换。 +例如:core.replaceText('衬衫的价格是${status:hp}镑${item:yellowKey}便士。'); // 把主角的生命值和持有的黄钥匙数量代入这句话 +text: 模板字符串,可以使用${}计算js表达式,支持“状态、物品、变量、独立开关、全局存储、图块id、图块类型、敌人数据、装备id”等量参与运算 +返回值:替换完毕后的字符串 + +removeLocalStorage: fn(key: string) +移除本地存储 + +unzip: fn(blobOrUrl?: ?, success?: fn(data: ?), error?: fn(error: string), convertToText?: bool, onprogress?: fn(loaded: number, total: number)) +解压一段内容 + +formatTime: fn(time: number) -> string +格式化时间 + +readFile: fn(success?: fn(data: string), error?: fn(message: string), readType?: bool) +尝试请求读取一个本地文件内容 [异步] +success: 成功后的回调 +error: 失败后的回调 +readType: 不设置则以文本读取,否则以DataUrl形式读取 + +readFileContent: fn(content: string) +文件读取完毕后的内容处理 [异步] + +formatDate: fn(date: ?) -> string +格式化日期为字符串 + +download: fn(filename: string, content: string) +弹窗请求下载一个文本文件 +例如:core.download('route.txt', JSON.stringify(core.status.route)); // 弹窗请求下载录像 +filename: 文件名 +content: 文件内容 + +encodeBase64: fn(str: string) -> string +base64加密 +例如:core.encodeBase64('abcd'); // 'YWJjZA==' +str: 明文 +返回值:密文 + +strlen: fn(str: string) -> number +求字符串的国标码字节数,也可用于等宽字体下文本的宽度测算。请注意样板的默认字体Verdana不是等宽字体 +例如:core.strlen('无敌ad'); // 6 +str: 待测字符串 +返回值:字符串的国标码字节数,每个汉字为2,每个ASCII字符为1 + +myprompt: fn(hint: string, value: string, callback?: fn(data?: string)) +让用户输入一段文字 + +getCookie: fn(name: string) -> string +访问浏览器cookie + +decodeRoute: fn(route: string) -> [string] +录像解压的最后一步,即一压的逆过程 +例如:core.decodeRoute(core.encodeRoute(core.status.route)); // 一压当前录像再解压-_-| +route: 录像解压倒数第二步的结果,即一压的结果 +返回值:原始录像 + +formatDate2: fn(date: ?) -> string +格式化日期为最简字符串 + +unshift: fn(a: [?], b: ?) -> [?] +将b(可以是另一个数组)插入数组a的开头,此函数用于弥补a.unshift(b)中b只能是单项的不足。 +例如:core.unshift(todo, {type: 'unfollow'}); // 在事件指令数组todo的开头插入“取消所有跟随者”指令 +a: 原数组 +b: 待插入的新首项或前缀数组 +返回值:插入完毕后的新数组,它是改变原数组a本身得到的 + +same: fn(a?: ?, b?: ?) -> bool +判定深层相等, 会逐层比较每个元素 +例如:core.same(['1', 2], ['1', 2]); // true + +setTwoDigits: fn(x: number) -> string +两位数显示 + +splitImage: fn(image?: string|image, width?: number, height?: number) -> [image] +等比例切分一张图片 +例如:core.splitImage(core.material.images.images['npc48.png'], 32, 48); // 把npc48.png切分成若干32×48px的小人 +image: 图片名(支持映射前的中文名)或图片对象(参见上面的例子),获取不到时返回[] +width: 子图的宽度,单位为像素。原图总宽度必须是其倍数,不填视为32 +height: 子图的高度,单位为像素。原图总高度必须是其倍数,不填视为正方形 +返回值:子图组成的数组,在原图中呈先行后列,从左到右、从上到下排列。 + +decompress: fn(value: ?) +解压缩一个数据 + +showWithAnimate: fn(obj?: ?, speed?: number, callback?: fn()) +动画显示某对象 + +subarray: fn(a?: [?], b?: [?]) -> [?]|null +判定一个数组是否为另一个数组的前缀,用于录像接续播放。请注意函数名没有大写字母 +例如:core.subarray(['ad', '米库', '小精灵', '小破草', '小艾'], ['ad', '米库', '小精灵']); // ['小破草', '小艾'] +a: 可能的母数组,不填或比b短将返回null +b: 可能的前缀,不填或比a长将返回null +返回值:如果b不是a的前缀将返回null,否则将返回a去掉此前缀后的剩余数组 + +turnDirection: fn(turn: string, direction?: string) -> string +计算应当转向某个方向 +turn: 转向的方向,可为 up,down,left,right,:left,:right,:back 七种 +direction: 当前方向 + +myconfirm: fn(hint: string, yesCallback?: fn(), noCallback?: fn()) +显示确认框,类似core.drawConfirmBox(),但不打断事件流 +例如:core.myconfirm('重启游戏?', core.restart); // 弹窗询问玩家是否重启游戏 +hint: 弹窗的内容,支持 ${} 语法 +yesCallback: 确定后的回调函数 +noCallback: 取消后的回调函数,可选 + +calValue: fn(value: string, prefix?: string) 计算一个表达式的值,支持status:xxx等的计算。 -prefix为前缀(switch:xxx的独立开关使用),need和time一般可以直接忽略。 +例如:core.calValue('status:hp + status:def'); // 计算主角的生命值加防御力 +value: 待求值的表达式 +prefix: 独立开关前缀,一般可省略 +返回值:求出的值 +encodeRoute: fn(route: [string]) -> string +录像压缩缩 +例如:core.encodeRoute(core.status.route); // 压缩当前录像 +route: 原始录像,自定义内容(不予压缩,原样写入)必须由0-9A-Za-z和下划线、冒号组成,所以中文和数组需要用JSON.stringify预处理再base64压缩才能交由一压 +返回值:一压的结果 -core.unshift(a, b) / core.push(a, b) -将b插入到列表a之前或之后。b可以是一个元素或者一个数组。 +decodeBase64: fn(str: string) -> string +base64解密 +例如:core.decodeBase64('YWJjZA=='); // "abcd" +str: 密文 +返回值:明文 +http: fn(type: string, url: string, formData: ?, success?: fn(data: string), error?: fn(message: string), mimeType?: string, responseType?: string, onprogress?: fn(loaded: number, total: number)) +发送一个HTTP请求 [异步] +type: 请求类型,只能为GET或POST +url: 目标地址 +formData: 如果是POST请求则为表单数据 +success: 成功后的回调 +error: 失败后的回调 -core.decompress(value) -解压缩一个字符串并进行JSON解析。value可能会被LZString或LZW算法进行压缩。 -返回解压后的JSON格式内容,如果无法解压则返回null。 +getLocalStorage: fn(key: string, defaultValue?: ?) +获得本地存储 +arrayToRGB: fn(color: [number]) -> string +颜色数组转字符串 +例如:core.arrayToRGB([102, 204, 255]); // "#66ccff" +color: 一行三列的数组,必须为不大于255的自然数 +返回值:该颜色的#xxxxxx字符串表示 -core.setLocalStorage(key, value) -将一个键值对存入localStorage中,会立刻返回结果。 -此函数会自动给key加上它的name作为前缀,以便于不同塔之间的区分。 -value为要存储的内容,存储前会被JSON转成字符串形式,并LZW算法进行压缩。 -如果value为null,则实际会调用core.removeLocalStorage()函数清除该key。 -localStorage为浏览器的默认存储,和存档无关,只有5M的空间大小。 -此函数立刻返回true或false,如果为false则代表存储失败,一般指的是空间满了。 +arrayToRGBA: fn(color: [number]) -> string +颜色数组转字符串 +例如:core.arrayToRGBA([102, 204, 255, 0.3]); // "rgba(102,204,255,0.3)" +color: 一行三列或一行四列的数组,前三个元素必须为不大于255的自然数。第四个元素(如果有)必须为0或不大于1的数字,第四个元素不填视为1 +返回值:该颜色的rgba(...)字符串表示 +formatBigNumber: fn(x: number, onMap?: bool) -> string +大数字格式化,单位为10000的倍数(w,e,z,j,g),末尾四舍五入 +例如:core.formatBigNumber(123456789, false); // "12346w" +x: 原数字 +onMap: 可选,true表示用于地图显伤,结果总字符数最多为5,否则最多为6 +返回值:格式化结果 -core.getLocalStorage(key, defaultValue) -从localStorage中获得一个键的值,会立刻返回结果。 -此函数会自动给key加上它的name作为前缀,以便于不同塔之间的区分。 -如果对应的键值不存在或为null,则会返回defaultValue。 -返回的结果会被调用core.decompress进行解压缩和JSON解析。 +removeLocalForage: fn(key: string, successCallback?: fn(), errorCallback?: fn()) +移除本地数据库的数据 +matchWildcard: fn(pattern: string, string: string) -> bool +通配符匹配,用于搜索图块等批量处理。 +例如:core.playSound(core.matchWildcard('*Key', itemId) ? 'item.mp3' : 'door.mp3'); // 判断捡到的是钥匙还是别的道具,从而播放不同的音效 +pattern: 模式串,每个星号表示任意多个(0个起)字符 +string: 待测串 +返回值:true表示匹配成功,false表示匹配失败 -core.removeLocalStorage(key) -从localStorage中删除一个键的值,会立刻返回。 -此函数会自动给key加上它的name作为前缀,以便于不同塔之间的区分。 +setLocalStorage: fn(key: string, value?: ?) +设置本地存储 +hideWithAnimate: fn(obj?: ?, speed?: number, callback?: fn()) +动画使某对象消失 -core.setLocalForage(key, value, successCallback, errorCallback) -将一个键值对存入localForage中,异步返回结果。 -如果用户没有开启【新版存档】开关,则仍然会使用core.setLocalStorage()。 -localForage为一个开源库,项目地址 https://github.com/localForage/localForage -一般存入的是indexedDB,这是一个浏览器的自带数据库,没有空间限制。 -successCallback和errorCallback均可选,表示该次存储成功或失败的回调, -此函数为异步的,只能通过回调函数来获得存储的成功或失败信息。 +copy: fn(data: string) -> bool +尝试复制一段文本到剪切板。 +isset: fn(v?: ?) -> bool +判断一个值是否不为null,undefined和NaN +例如:core.isset(0/0); // false,因为0/0等于NaN +v: 待测值,可选 +返回值:false表示待测值为null、undefined、NaN或未填写,true表示为其他值。 -core.getLocalForage(key, defaultValue, successCallback, errorCallback) -从localForage中获得一个键的值,异步返回结果。 -如果对应的键值不存在,则会使用defaultValue。 -如果获得成功,则会将core.decompress后的结果传入successCallback回调函数执行。 -errorCallback可选,如果失败,则会将错误信息传入errorCallback()。 -此函数是异步的,只能通过回调函数来获得读取的结果或错误信息。 +replaceValue: fn(value: string) -> string +对一个表达式中的特殊规则进行替换,如status:xxx等。 +例如:core.replaceValue('status:atk+item:yellowKey'); // 把这两个冒号表达式替换为core.getStatus('hp')和core.itemCount('yellowKey')这样的函数调用 +value: 模板字符串,注意独立开关不会被替换 +返回值:替换完毕后的字符串 +getLocalForage: fn(key: string, defaultValue?: ?, successCallback?: fn(data: ?), errorCallback?: fn()) +从本地数据库读出一段数据 -core.setGlobal(key, value) -设置一个全局存储,适用于global:xxx。 -录像播放时将忽略此函数,否则直接调用core.setLocalStorage。 - - -core.getGlobal(key, value) -获得一个全局存储,适用于global:xxx,支持录像。 -正常游戏时将使用core.getLocalStorage获得具体的数据,并将结果存放到录像中。 -录像播放时会直接从录像中获得对应的数据。 - - -core.clone(data, filter, recursion) -深拷贝一个对象。有关浅拷贝,深拷贝,基本类型和引用类型等相关知识可参见: -https://zhuanlan.zhihu.com/p/26282765 -filter为过滤函数,如果设置且不为null则需传递一个可接受(name, value)的函数, -并返回true或false,表示该项是否应该被深拷贝。 -recursion表示该filter是否应递归向下传递,如果为true则递归函数也将传该filter。 -例如: -core.clone(core.status.hero, function(name, value) { - return name == 'items' || typeof value == 'number'; -}, false); -这个例子将会深拷贝勇士的属性和道具。 - - -core.splitImage(image, width, height) -等比例切分一张图片。width和height为每张子图片的宽高。 -请确保原始图片的宽度和高度都是是width和height的倍数。 -此函数将返回一个一维数组,每一项都是一张切分好的图片,横向再纵向排列。 -例如4x3的图片按1x1切分得到一个长度为12的数组,按如下方式进行排列: -0 1 2 3 -4 5 6 7 -8 9 10 11 -可以将很多需要的图片拼在一张大图上,然后在插件的_afterLoadResources中切分。 -切分好的图片再存入core.material.images.images中,这样可以少很多IO请求。 - - -core.formatDate(date) / core.formatDate2(date) / core.formatTime(time) -格式化日期和时间。 - - -core.setTwoDigits(x) -将x变成两位数。其实就是 parseInt(x) < 10 ? "0" + x : x - - -core.formatBigNumber(x, onMap) -大数据格式化。x为要格式化的内容,如果不合法会返回???。 -onMap标记是否在地图上调用,如果为真则尝试格式化成六位,否则五位。 - - -core.arrayToRGB(color) / core.arrayToRGBA(color) -将一个颜色数组,例如[255,0,0,1]转成#FF0000或rgba(255,0,0,1)的形式。 - - -core.encodeRoute(route) -录像压缩和解压缩。route为要压缩的路线数组。 -此函数将尽可能对录像进行压缩。对于无法识别的项目(比如自己添加的),将不压缩而原样放入。 -例如,["up","up","left","move:3:5","test:2333","getNext","item:bomb","down"] -将被压缩成"U2LM3:5(test:2333)GIbomb:D"。 -自己添加的录像项只能由数字、大小写、下划线线、冒号等符号组成,否则无法正常压缩和解压缩。 -对于自定义内容(比如中文文本或数组)请使用JSON.stringify再core.encodeBase64处理。 -压缩的结果将再次进行LZString.compressToBase64()的压缩以进一步节省空间。 - - -core.decodeRoute(route) -解压缩一个录像,返回解压完毕的路线数组。 - - -core.isset(v) -判定v是不是null, undefined或NaN。 -请尽量避免使用此函数,而是直接判定 v == null (请注意 null==undefined !) - - -core.subarray(a, b) -判定数组b是不是数组a的一个前缀子数组。 -如果是,则返回a中除去b后的剩余数组,否则返回null。 - - -core.inArray(array, element) +inArray: fn(array?: ?, element?: ?) -> bool 判定array是不是一个数组,以及element是否在该数组中。 +array: 可能的数组,不为数组或不填将导致返回值为false +element: 待查找的元素 +返回值:如果array为数组且具有element这项,就返回true,否则返回false +setGlobal: fn(key: string, value?: ?) +设置一个全局存储,适用于global:xxx,录像播放时将忽略此函数。 +例如:core.setBlobal('一周目已通关', true); // 设置全局存储“一周目已通关”为true,方便二周目游戏中的新要素。 +key: 全局变量名称,支持中文 +value: 全局变量的新值,不填或null表示清除此全局存储 -core.clamp(x, a, b) -将x限定在[a,b]区间内。 +rand2: fn(num?: number) -> number +支持SL的随机数,并计入录像 +例如:1 + core.rand2(6); // 随机生成一个小于7的正整数,模拟骰子的效果 +num: 正整数,0或不填会被视为2147483648 +返回值:属于 [0, num) 的随机数 +setStatusBarInnerHTML: fn(name: string, value: ?, css?: string) +填写非自绘状态栏 +例如:core.setStatusBarInnerHTML('hp', core.status.hero.hp, 'color: #66CCFF'); // 更新状态栏中的主角生命,使用加载画面的宣传色 +name: 状态栏项的名称,如'hp', 'atk', 'def'等。必须是core.statusBar中的一个合法项 +value: 要填写的内容,大数字会被格式化为至多6个字符,无中文的内容会被自动设为斜体 +css: 额外的css样式,可选。如更改颜色等 -core.getCookie(name) -获得一个cookie值,如果不存在该cookie则返回null。 +matchRegex: fn(pattern: string, string: string) -> string +是否满足正则表达式 +push: fn(a: [?], b: ?) -> [?] +将b(可以是另一个数组)插入数组a的末尾,此函数用于弥补a.push(b)中b只能是单项的不足。 +例如:core.push(todo, {type: 'unfollow'}); // 在事件指令数组todo的末尾插入“取消所有跟随者”指令 +a: 原数组 +b: 待插入的新末项或后缀数组 +返回值:插入完毕后的新数组,它是改变原数组a本身得到的 -core.setStatusBarInnerHTML(name, value, css) -设置一个状态栏的innerHTML。此函数会自动设置状态栏的文字放缩和斜体等效果。 -name为状态栏的名称,如atk, def等。需要是core.statusBar中的一个合法项。 -value为要设置到的数值,如果是数字则会先core.formatBigNumber()进行格式化。 -css可选,为增添的额外css内容,比如可以设定颜色等。 +formatSize: fn(size: number) -> string +格式化文件大小 - -core.strlen(str) -计算某个字符串的实际长度。每个字符的长度,ASCII码视为1,中文等视为2。 - - -core.reverseDirection(direction) -翻转方向,即"up"转成"down", "left"转成"right"等。 - - -core.matchWildcard(pattern, string) -进行通配符的匹配判定,目前仅支持*(可匹配0或任意个字符)。比如"a*b*c"可以匹配"aa012bc"。 - - -core.encodeBase64(str) / core.decodeBase64(str) -将字符串进行base64加密或解密。 -可用于解压缩录像数据 - - -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大法。 -但是,此函数会将生成的随机数值存入录像,因此如果调用次数太多则会导致录像文件过大。 -对于需要大量生成随机数,但又想使用真随机支持SL大法的(例如随机生成地图等),可以采用如下方式: - var x = core.rand2(100); for (var i = 0; i < x; i++) core.rand() -即先生成一个真随机数,根据该数来推进伪随机的种子,这样就可以放心调用core.rand()啦。 - - -core.readFile(success, error, accept) -读取一个本地文件内容。success和error分别为读取成功或失败的回调函数。 -accept如果设置则控制能选择的文件类型。 -iOS平台暂不支持读取文件操作。 - - -core.readFileContent(content) -读取到的文件内容。此函数会被APP等调用,来传递文件的具体内容。 - - -core.download(filename, content) -生成一个文件并下载。filename为文件名,content为具体的文件内容。 -iOS平台暂不支持下载文件操作。 - - -core.copy(data) -将一段内容拷贝到剪切板。 - - -core.myconfirm(hint, yesCallback, noCallback) -弹窗绘制一段提示信息并让用户确认。hint为提示信息。 -yesCallback和noCallback分别为确定和取消的回调函数。 -此函数和core.drawConfirmBox的区别主要在于: - - drawConfirmBox会清掉UI层原有的绘制信息,此函数不会清除。 - - drawConfirmBox可以用键盘进行操作,此函数必须用鼠标点击。 -另外请注意:本函数的选择也不会进录像,一般用于全局的提示。 -如果需要在事件流中调用请使用显示确认框或显示选择项。 - - -core.myprompt(hint, value, callback) -弹窗让用户输入一段内容。hint为提示信息,value为框内的默认填写内容。 -callback为用户点击确认或取消后的回调。 -如果用户点击了确认,则会把框内的内容(可能是空串)传递给callback,否则把null传递给callback。 - - -core.showWithAnimate(obj, speed, callback) / core.hideWithAnimate(obj, speed, callback) -动画淡入或淡出一个对象。 - - -core.same(a, b) -判定a和b是否相同,包括类型相同和值相同。 -如果a和b都是数组,则会递归依次比较数组中的值;如果都是对象亦然。 - - -core.unzip(blobOrUrl, success, error, convertToText) -解压一个zip文件。 -blobOrUrl为传入的二进制zip文件Blob格式,或zip文件的地址。 -success为成功后的回调,接收 文件名-文件内容 形式的对象,即 -{"filename1": ..., "filename2": ...} -error为失败的回调,接收参数message为错误信息。 -convertToText如果为true则会将每个文件内容转成纯文本而不是二进制格式。 - - -core.http(type, url, formData, success, error, mimeType, responseType) -发送一个异步HTTP请求。 -type为'GET'或者'POST';url为目标地址;formData如果是POST请求则为表单数据。 -success为成功后的回调,error为失败后的回调。 -mimeType和responseType如果设置将会覆盖默认值。 - - -lzw_encode(s) / lzw_decode(s) +lzw_encode: fn(s: string) -> string LZW压缩算法,来自https://gist.github.com/revolunet/843889 + +lzw_decode: fn(s: string) -> string +LZW解压算法,来自https://gist.github.com/revolunet/843889 +``` + +## plugins.js + +插件编写中内置了一些常用的插件。 + +```text +drawLight: fn(name: string|CanvasRenderingContext2D, color?: number, lights?: [[number]], lightDec?: number) +绘制一段灯光效果 +name:必填,要绘制到的画布名;可以是一个系统画布,或者是个自定义画布;如果不存在则创建 +color:可选,只能是一个0~1之间的数,为不透明度的值。不填则默认为0.9。 +lights:可选,一个数组,定义了每个独立的灯光。其中每一项是三元组 [x,y,r] x和y分别为该灯光的横纵坐标,r为该灯光的半径。 +lightDec:可选,0到1之间,光从多少百分比才开始衰减(在此范围内保持全亮),不设置默认为0。比如lightDec为0.5代表,每个灯光部分内圈50%的范围全亮,50%以后才开始快速衰减。 +例如:core.plugin.drawLight('test', 0.2, [[25,11,46,0.1]]); // 创建一个test图层,不透明度0.2,其中在(25,11)点存在一个半径为46的灯光效果,灯光中心不透明度0.1。 +core.plugin.drawLight('test2', 0.9, [[25,11,46],[105,121,88],[301,221,106]]); // 创建test2图层,且存在三个灯光效果,分别是中心(25,11)半径46,中心(105,121)半径88,中心(301,221)半径106。 + +openShop: fn(shopId: string, noRoute?: bool) +打开一个全局商店 +shopId: 要开启的商店ID +noRoute: 打开行为是否不计入录像 + +isShopVisited: fn(id: string) -> bool +某个全局商店是否被访问过 + +listShopIds: fn() -> [string] +列出所有应当显示的快捷商店列表 + +canOpenShop: fn(id: string) -> bool +当前能否打开某个商店 + +setShopVisited: fn(id: string, visited?: bool) +设置某个商店的访问状态 + +canUseQuickShop: fn(id: string) -> string +当前能否使用某个快捷商店 +如果返回一个字符串,则代表不能,返回的字符串作为不能的提示;返回null表示可以使用 + +removeMaps: fn(fromId: string, toId?: string) +删除某一些楼层;删除后不会存入存档,不可浏览地图也不可飞到。 +fromId: 开始删除的楼层ID +toId: 删除到的楼层编号;可选,不填则视为fromId +例如:core.removeMaps("MT1", "MT300") 删除MT1~MT300之间的全部层 +core.removeMaps("MT10") 只删除MT10层 + +resumeMaps: fn(fromId: string, toId?: string) +恢复某一些被删除楼层。 +fromId: 开始恢复的楼层ID +toId: 恢复到的楼层编号;可选,不填则视为fromId +例如:core.resumeMaps("MT1", "MT300") 恢复MT1~MT300之间的全部层 +core.resumeMaps("MT10") 只删恢复MT10层 + +openItemShop: fn(itemShopId: string) +打开一个道具商店 ``` diff --git a/_docs/editor.md b/_docs/editor.md index 22e369ac..4018861d 100644 --- a/_docs/editor.md +++ b/_docs/editor.md @@ -1,5 +1,7 @@ # 修改编辑器 +?> 在这一节中,让我们来了解如何修改编辑器(包括配置表格和事件编辑器) + 在改动core时, 有时会相应的更改project中存储数据的结构, 而表格和事件编辑器不做相应更改的话就无法顺畅的编辑改动了结构的数据了, 此文档帮助造塔者进行`配置表格`的修改, 以及修改_server/MotaAction.g4和其他相关文件来调整事件编辑器的图块. ## 修改表格 @@ -312,3 +314,7 @@ return code;
    '特效/声音':[
       MotaActionBlocks['meteorite_s'].xmlText(),
       MotaActionBlocks['sleep_s'].xmlText(),
+ +========================================================================================== + +[继续阅读下一章:API列表](api) \ No newline at end of file diff --git a/_docs/element.md b/_docs/element.md index 4438b897..d90b186b 100644 --- a/_docs/element.md +++ b/_docs/element.md @@ -1,9 +1,11 @@ # 元件说明 -?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} * -在这个部分,将详细讲解编辑器的每个部件的用法。 +?> 在这个部分,将详细讲解编辑器的每个部件的用法。 + ## 素材区 + 素材区在展开状态下,从左到右分为若干列: + 1. `project\materials\terrains.png`:位于素材区第一列(最上面两个图块不在这张图片里,它们分别是擦除和空气墙),其中从楼梯开始往下有系统含义,请勿随意修改其图块属性。 2. `project\materials\animates.png`:位于素材区第二列,共4帧。主要为星空、岩浆、三色墙、六色门、四向出入口箭头、四种路障。 3. `project\materials\enemys.png`:32×32px(像素,下同)的怪物,您可以随意修改它们的任何属性。如果嫌两帧太少,还可以作为32×48px怪物画在靠下2/3部分。 @@ -13,96 +15,103 @@ 7. `project\autotiles`:自动元件,会随着在地图上的连续摆放而自动采取适当的绘制方式。 8. `project\tilesets`:额外素材,用来突破其他素材合计不得超过1000个的限制。您可以在这个区域拖动来批量框选,再在地图区单击成片绘制或拖动平铺。 -您可以随时使用`core.getBlockCls(x, y, floorId, showDisable)`这一API来获取游戏中某个位置的图块类别,其中自动元件和额外素材会分别返回“autotile”和“tileset”,其他的则会返回所在的图片文件名(不含后缀)。 ## 地图编辑(快捷键Z) -![image](img/v2.7/editor.png)如图所示,您可以在此对地图进行清空或删除操作,也可以新建或批量新建任意宽高的空白地图。其中“导出并复制地图”是指显示出左侧的矩阵并复制(一般用来跨塔复制地图),您也可以直接改动其中的数字,再点击“从框中导入地图”就能将改动的结果同步到地图上。下面的“楼层ID、中文名、状态栏名”分别对应楼层属性(快捷键V)的floorId、title和name,其中floorId也作为文件名(不能使用中文),title会显示在楼传界面和楼层切换黑屏,name也允许使用中文。 + +![image](img/editor.jpg) + +如图所示,您可以在此对地图进行清空或删除操作,也可以新建或批量新建任意宽高的空白地图。 + +其中“导出并复制地图”是指显示出左侧的矩阵并复制(一般用来跨塔复制地图),您也可以直接改动其中的数字,再点击“从框中导入地图”就能将改动的结果同步到地图上。 + +下面的“楼层ID、中文名、状态栏名”分别对应楼层属性(快捷键V)的floorId、title和name,其中floorId也作为文件名(不能使用中文),title会显示在楼传界面和楼层切换黑屏,name也允许使用中文。 + ## 图块属性(快捷键C) -![image](img/v2.7/mapsC.png) + +![image](img/mapsC.jpg) + 如上图,除怪物和道具外,所有素材的图块属性都定义在`project\maps.js`中。道具和怪物属性也支持清空和批量复制,下面逐一讲解各条目的含义和用法: -1. 图块ID:`core.getBlockId(x, y, floorId, showDisable)`的返回结果,不允许使用中文和纯数字。请注意,额外素材(tileset)的图块ID由素材图片的顺序和图块在图片上的位置确定,无法更改,也请勿随意调换图片的顺序。样板已注册的图块中建议只修改怪物和NPC的图块ID,修改方法为上图最下方的“修改图块id为”。 -2. 图块数字:见前面的描述,额外素材的数字由ID去掉字母X得到。 -3. 图块类别:即前面所说的`core.getBlockCls(x, y, floorId, showDisable)`的返回结果。 -4. 图块名称:怪物在手册中、道具在道具栏中、其他图块在剧情对话中的默认名称,可以随意修改。但原则上不推荐不同的怪物和道具有重复的名称,否则会影响事件编辑器的中文替换功能。 -在讲解其他属性之前,这里简单介绍一下素材的注册机制。 +1. **图块ID:**图块的唯一标识符`core.getBlockId(x, y, floorId, showDisable)`,不允许使用中文和纯数字。请注意,额外素材`tileset`的图块ID由素材图片的顺序和图块在图片上的位置确定,无法更改,也请勿随意调换图片的顺序。样板已注册的图块中建议只修改怪物和NPC的图块ID,修改方法为上图最下方的**修改图块id为**。 +2. **图块数字:**见前面的描述,额外素材的数字由ID去掉字母X得到。 +3. **图块类别:**图块素材的类型。 +4. **图块名称:**怪物在手册中、道具在道具栏中、其他图块在剧情对话中的默认名称,可以随意修改。但原则上不推荐不同的怪物和道具有重复的名称,否则会影响事件编辑器的中文替换功能。 -除自动元件和额外素材外,其余图块只有在注册后才拥有上面所说的ID和数字。 +你可以随时使用 `core.getBlockId(x, y, floorId, showDisable)` 获得地图上任何一个点的图块ID;`core.getBlockCls(x, y, floorId, showDisable)` 或的地图上任何一个点的图块类别;详见[API列表](api)。 -未注册的图块则只有“索引”,索引为n表示该图块在图片的第(n+1)行, +在讲解其他属性之前,这里简单介绍一下素材的注册机制: -ID和索引的对应关系定义在project\icons.js中。 - -尝试用未注册的图块(如道具一列中的某些魔杖和飞羽,或者利用便捷PS工具新追加的图块)在地图上绘制,就会出现红色的问号方框。 - -此时请在数据区手动注册此图块,只需填写一个新ID和数字(1000以内)即可。 - -也可以点击“自动注册”按钮批量注册该图片的所有未注册素材,自动注册出的ID非常难看,建议立即手动修改为有意义的英数或拼音。 +* 除自动元件和额外素材外,其余图块只有在注册后才拥有上面所说的ID和数字。 +* 未注册的图块则只有“索引”,索引为n表示该图块在图片的第(n+1)行, +* ID和索引的对应关系定义在`project\icons.js`中。 +* 尝试用未注册的图块(如利用便捷PS工具新追加的图块)在地图上绘制,就会出现红色的问号方框。 +* 此时请在数据区手动注册此图块,只需填写一个新ID和数字(1000以内)即可。 +* 也可以点击“自动注册”按钮批量注册该图片的所有未注册素材,自动注册出的ID无任何意义,建议手动修改成有意义的内容。 自动元件的注册与此不同,除了替换样板现有的几个外,如果还需要追加新的,请在地图区下方的下拉框中切换到“追加素材”(快捷键M),然后导入文件到画板autotile,再点击“追加”按钮即可。非Windows系统追加其他素材也主要依靠这种方式,具体用法请自行探索。 + ### 非怪物非道具属性 -1. 触发器:目前素材区只有第一列最下面两个图块使用pushBox这一触发器,请勿修改之,也请勿对别的图块使用这一触发器。其余触发器中custom一般不需要,ski用于画在背景层的图块来实现滑冰效果,openDoor用于制作门。(怪物和道具的触发器分别是battle和getItem,不能修改) - 关于推箱子,存在三种图块:目标点(flower)、没推到位的黄箱子(box)、推到位的绿箱子(boxed)。 - - 推箱子的前方不能存在任何事件层图块(flower除外),否则会推不动。 - - 每推一步箱子后将触发“脚本编辑——推箱子后”,您可以在里面统计上述三种图块的数量,进行对应的处理。 -2. 可通行性:勾选后勇士才可以踏入此图块,否则只能撞击此图块。(怪物被锁定为不可通行,道具被锁定为可通行) -3. 碰触脚本:勇士踏入或撞击此图块时执行的脚本,该项会被eval,相当于一种自定义的触发器,您可以参考踩灯和四种路障去填写它。 -4. 不可出入方向:对三个图层的图块都有效。不可出方向指的是勇士站在这种图块上不能向哪个方向走(包括撞击),不可入方向指的是勇士不能从哪个方向走向这种图块(包括撞击,如勾选了“上”则不能从上方向下走向这个图块),请参考素材区第一列最下面的四个箭头。 -5. 可破震:勾选后,此图块将成为破墙镐(pickaxe)和地震卷轴(earthquake)这两个道具的目标。 -6. 动画帧数:您可以修改此帧数来让本来有4帧的图块只用前3帧循环播放,另外制作门时请务必将此帧数改为1,表示门在打开前静止在第1帧。 -7. 门信息:只对4帧的图块(自动元件除外)有效,您可以点击“编辑按钮”来填写此图块作为门的开关耗时、开关音效以及需要哪些钥匙各多少把(可以填写任何消耗类道具,也可以选择某些道具只需持有一定数量而不消耗)。修改此信息后,您需要将上面的“动画帧数”改为1,并可能需要将“触发器”改为openDoor(不改的话将无法通过撞击来开门,但可以像三色墙一样用来制作暗墙)。 -8. 行走图朝向:只对npc48有效。设置后,当勇士撞击该npc时npc会尝试转身面向勇士(对话事件结束前请使用“事件转向”指令将其转回去)。 - - 走动时也会尝试自动转向,请参考样板0层使用的小姐姐。 +1. **触发器:**当碰触到地图上此图块时触发的系统事件,详见[事件](event)。 + * **battle**: (未列出)战斗;当撞上一个怪物且没有覆盖触发器时(参见[事件](event))将自动调用此触发器产生战斗,并此战后事件。 + * **getItem**: (未列出)获得道具;当撞上一个道具且没有覆盖触发器时(参见[事件](event))将自动调用此触发器获得它,并触发道具后事件。 + * **changeFloor**: (未列出)楼层切换;对于地图上绑定的绿点将自动调用此触发器产生楼层切换事件。 + * **openDoor**: 用于制作门效果,当撞上此图块时将尝试开门(仅对`animates`和`npc48`生效);具体开门动画参见下面的门信息。 + * **pushBox**: 推箱子信息;请勿对非箱子使用此触发器。 + * **ski**: 冰信息;拥有此触发器的图块放置在背景层时,走上去将触发滑冰效果。 + * **custom**: 自定义系统触发器;你可以使用 `core.registerSystemEvent` 来自己定义一个系统触发器,参见[API列表](api)。 +2. **可通行性:**勾选后勇士才可以踏入此图块,否则只能撞击此图块。(怪物被锁定为不可通行,道具被锁定为可通行,如有需要可以修改点上的不可通行性) +3. **碰触脚本:**勇士踏入或撞击此图块时执行的脚本,该项会被eval,相当于一种自定义的触发器,您可以参考踩灯和四种路障去填写它。 +4. **不可出入方向:**对三个图层的图块都有效。不可出方向指的是勇士站在这种图块上不能向哪个方向走(包括撞击),不可入方向指的是勇士不能从哪个方向走向这种图块(包括撞击)。例如,勾选了“上”则不能从上方向下走向这个图块。请参考素材区第一列最下面的四个箭头。 +5. **可破震:**勾选后,此图块将成为破墙镐(pickaxe)和地震卷轴(earthquake)这两个道具的目标。 +6. **动画帧数:**您可以修改此帧数来让本来有4帧的图块只用前3帧循环播放,另外制作门时请务必将此帧数改为1,表示门在打开前静止在第1帧。 +7. **门信息:**只对`animates`和`npc48`有效,您可以点击“编辑按钮”来填写此图块作为门的开关耗时、开关音效以及需要哪些钥匙各多少把(可以填写任何消耗类道具,也可以选择某些道具只需持有一定数量而不消耗)。修改此信息后,您需要将上面的“动画帧数”改为1,并可能需要将“触发器”改为openDoor(不改的话将无法通过撞击来开门,但可以像三色墙一样用来制作暗墙)。 +8. **行走图朝向:**只对npc48有效。设置后,当勇士撞击该npc时npc会尝试转身面向勇士(对话事件结束前请使用“事件转向”指令将其转回去)。走动时也会尝试自动转向,请参考样板0层使用的小姐姐。 ### 道具属性 + 样板自带的道具都在样板0层摆好了,您可以直接进入游戏捡起它们,就会看到该道具的注意事项,这里不再赘述。 -1. 道具类别:虽然和图块类别的英文缩写都是cls,但有本质区别,请注意区分。道具的图块类别都是items,而道具类别分为以下几种: - 1. items:是的你没看错,又是items这个词,请注意和图块类别的items相区分。它表示即捡即用类不进背包的道具,如四种血瓶、三种宝石等。这类道具需要用到的其他属性有“即捡即用效果”、“即捡即用提示”、“碰触或使用事件”。 - 2. tools:进背包的消耗类道具,如钥匙和解药瓶、便携式血瓶蓝瓶(生命魔杖)、破震炸飞和跳鞋等。这类道具需要用到的其他属性有“道具描述”、“不显示在道具栏”、“回放不绘制道具栏”、“碰触或使用事件”、“使用效果”、“能否使用”。 - 3. constants:进背包的永久道具(每件在背包的数量要么为1要么为0),如手册、楼传、幸运金币、十字架、护符、二倍斩等,这类道具需要用到的其他属性和tools一致。 - 4. equips:装备,它需要用到的其他属性有“道具描述”、“道具的装备属性”、“能否装备”。 - 所以,如果您想把四种血瓶和三种宝石改为便携式,就只需把其道具类别改为tools(当然,楼层属性中的宝石血瓶效果一项也就失效了)。 +1. **道具类别:**虽然和图块类别的英文缩写都是cls,但有本质区别,请注意区分。道具的图块类别都是items,而道具类别分为以下几种: + * items:是的你没看错,又是`items`这个词,请注意和图块类别的`items`相区分。它表示即捡即用类不进背包的道具,如四种血瓶、三种宝石等。这类道具需要用到的其他属性有“即捡即用效果”、“即捡即用提示”、“碰触或使用事件”。 + * tools:进背包的消耗类道具,如钥匙和解药瓶、便携式血瓶蓝瓶(生命魔杖)、破震炸飞和跳鞋等。这类道具需要用到的其他属性有“道具描述”、“不显示在道具栏”、“回放不绘制道具栏”、“碰触或使用事件”、“使用效果”、“能否使用”。 + * constants:进背包的永久道具(每件在背包的数量要么为1要么为0),如手册、楼传、幸运金币、十字架、护符、二倍斩等,这类道具需要用到的其他属性和tools一致。 + * equips:装备,它需要用到的其他属性有“道具描述”、“道具的装备属性”、“能否装备”。 + * 例如:如果您想把四种血瓶和三种宝石改为便携式,就只需把其道具类别改为tools(当然,楼层属性中的宝石血瓶效果一项也就失效了)。 + * 如果想把大黄门钥匙变为钥匙盒(红黄蓝钥匙各一把),只需把其道具类别从tools改为items + * 如果想把剑盾变成装备,只需把其道具类别改为`equips`,等等 +2. **道具描述:**对除即捡即用类外的道具都有效。一个字符串,为道具在道具栏里的描述,也作为首次捡到时的提示信息的一部分(如果全塔属性中开启了这一提示功能的话)。支持使用`${表达式计算}`语法(如四种血瓶和三种宝石那样,但不支持中文替换),此语法的详细规则见“显示文章正文的转义序列”,和“值块和冒号缩写量”。 +3. **不显示在道具栏:**对tools和constants有效,勾选此项后,该道具在背包中将不显示出来。常用于不能主动使用或已有专门的使用按钮的道具来节省显示篇幅,如手册、楼传、幸运金币、十字架、护符和钥匙等。 +4. **回放不绘制道具栏:**勾选此项后,录像回放中使用此道具将不显示黑黑的道具栏。常用于频繁使用的道具,如楼传、技能和冰冻徽章等。 +5. **即捡即用效果:**如题,该项会被eval,一般为一行下述的代码: `core.status.hero.xxx += yyy * core.status.thisMap.ratio` + * 其中xxx为勇士的某种状态(如生命hp、生命上限hpmax、魔力mana、魔力上限manamax、护盾mef、攻防和金经) + * yyy为此道具的基础效果(如四种血瓶和三种宝石的基础效果定义在了全塔属性中) + * `core.status.thisMap.ratio`则是指该道具所在楼层的“楼层属性”最下面的“宝石血瓶效果”。 +6. **即捡即用提示:**实际显示时会被接在“获得xxx”后面,所以该项总是一个以逗号开头的字符串,同样支持`${表达式计算}`语法。 +7. **碰触或使用事件:**对除equips外都有效。该项用于代替“即捡即用效果”(但会使勇士停下脚步,且会晚于afterGetItem事件被执行)和“使用效果”,如样板中的黄宝石和生命魔杖。如果您的js语法基础薄弱,那么它将是您的不二之选。 +8. **使用效果:**对tools和constants有效。该项会被eval,一般为一个js函数,较为简单的使用效果(如解药瓶)也可能是一行代码,破炸冰的目标个数请直接在该项中修改。总的来说因为事件比起脚本更容易实现异步特效且录像安全性更好,所以如非必要,不建议用此项。 +9. **能否使用:**对tools和constants有效。该项也会被eval,一般为一个js函数,较为简单的使用条件(如解药瓶)也可能是一行形如`core.hasFlag('xxx')`的代码。如果该道具在任何情况下都不能主动使用,请留null(并最好勾选“不显示在道具栏”以节约显示篇幅),如果该道具在任何情况下都可以使用,请填“true”,如果使用条件较为复杂,也推荐直接填“true”先斩后奏,在使用效果中再行判定,并在使用失败的场合使用`core.addItem('xxx')`静默返还一件该道具,如样板中的破墙镐和炸弹。 +10. **能否装备:**对equips有效,请注意在装上装备后如果条件不再满足也不会自动卸下。和“能否使用”不同,此项留null表示任何情况下都可以装备。 +11. **道具的装备属性:**在介绍此项之前,请先留意一下“全塔属性”中的“装备孔”一项。该项为一个字符串数组,最多允许6项(13×13样板)或8项(15×15样板)。每一项为装备的类型名称,建议是两个汉字(如“武器”、“防具”)。类型允许重复,如可以让勇士最多同时装备两块盾牌。 + * 装备类型:一个自然数,和前面的“装备孔”对应,如0表示武器,1表示防具。如果装备孔有重复的名称则这里也直接写名称(不用加引号),穿戴时会自动尝试寻找第一个同类型的空闲装备位,没有空闲的话会提示玩家先卸下一件。 + * 普攻动画:`project\animates`文件夹中任何一个文件的名称(不带后缀,但需要在全塔属性中注册过),只对第一个装备孔有效。普攻动画会播放在和勇士战斗的怪物位置处,如果是强制战斗的天降怪物,则会播放在勇士身上并跟随,请自行注意。详见“文件注册”使用动画。 + * 数值提升项:若干个键值对,表示该装备增加属性的常数值(支持负数)。7个常用属性可以通过下拉框选取,自定义的新属性也可以手动输入。 + * 百分比提升项:若干个键值对,表示该装备增加属性的百分比(支持负数,如填-10就表示减少10%),修改方法同上。 + * 装备对属性的影响原理:在穿脱装备时,会根据数值提升项和百分比提升项,分别调用`core.status.hero.xxx += yyy和core.addBuff('xxx', yyy)`这两个API(衰弱的附加和解除同理),而状态栏的显示值和战斗中的使用值则是`core.getStatus('xxx')`和buff值相乘再向下取整所得。 + * PC端按下Ctrl+0~9可以保存当前套装,Alt+0~9快速更换套装。 - 如果想把大黄门钥匙变为钥匙盒(红黄蓝钥匙各一把),只需把其道具类别从tools改为items.如果想把剑盾变成装备,只需把其道具类别改为`equips`. -2. 道具描述:对除即捡即用类外的道具都有效。一个字符串,为道具在道具栏里的描述,也作为首次捡到时的提示信息的一部分(如果全塔属性中开启了这一提示功能的话)。支持使用`${表达式计算}`语法(如四种血瓶和三种宝石那样,但不支持中文替换),此语法的详细规则见“显示文章正文的转义序列”,和“值块和冒号缩写量”。 -3. 不显示在道具栏:对tools和constants有效,勾选此项后,该道具在背包中将不显示出来。常用于不能主动使用或已有专门的使用按钮的道具来节省显示篇幅,如手册、楼传、幸运金币、十字架、护符和钥匙等。 -4. 回放不绘制道具栏:勾选此项后,录像回放中使用此道具将不显示黑黑的道具栏。常用于频繁使用的道具,如楼传、技能和冰冻徽章等。 -5. 即捡即用效果:如题,该项会被eval,一般为一行下述的代码: - `core.status.hero.xxx += yyy * core.status.thisMap.ratio` +道具相关API请阅读[API列表](api)。 - 其中xxx为勇士的某种状态(如生命hp、生命上限hpmax、魔力mana、魔力上限manamax、护盾mef、攻防和金经),yyy为此道具的基础效果(如四种血瓶和三种宝石的基础效果定义在了全塔属性中),而最后的ratio则是指该道具所在楼层的“楼层属性”最下面的“宝石血瓶效果”。 -6. 即捡即用提示:实际显示时会被接在“获得 - xxx”后面,所以该项总是一个以逗号开头的字符串,同样支持`${表达式计算}`语法。 -7. 碰触或使用事件:对除equips外都有效。该项用于代替“即捡即用效果”(但会使勇士停下脚步,且会晚于afterGetItem事件被执行)和“使用效果”,如样板中的黄宝石和生命魔杖。如果您的js语法基础薄弱,那么它将是您的不二之选。 -8. 使用效果:对tools和constants有效。该项会被eval,一般为一个js函数,较为简单的使用效果(如解药瓶)也可能是一行代码,破炸冰的目标个数请直接在该项中修改。总的来说因为事件比起脚本更容易实现异步特效且录像安全性更好,所以如非必要,不建议用此项。 -9. 能否使用:对tools和constants有效。该项也会被eval,一般为一个js函数,较为简单的使用条件(如解药瓶)也可能是一行形如`core.hasFlag('xxx')`的代码。如果该道具在任何情况下都不能主动使用,请留null(并最好勾选“不显示在道具栏”以节约显示篇幅),如果该道具在任何情况下都可以使用,请填“true”,如果使用条件较为复杂,也推荐直接填“true”先斩后奏,在使用效果中再行判定,并在使用失败的场合使用`core.addItem('xxx')`静默返还一件该道具,如样板中的破墙镐和炸弹。 -10. 能否装备:对equips有效,请注意在装上装备后如果条件不再满足也不会自动卸下。和“能否使用”不同,此项留null表示任何情况下都可以装备。 -11. 道具的装备属性:在介绍此项之前,请先留意一下“全塔属性”中的“装备孔”一项。该项为一个字符串数组,最多允许6项(13×13样板)或8项(15×15样板)。每一项为装备的类型名称,建议是两个汉字(如“武器”、“防具”)。类型允许重复,如可以让勇士最多同时装备两块盾牌。 - - 接下来介绍道具的装备属性,点击“编辑”按钮进入其图形化编辑模式。该项分为以下几个方面: - 1. 类型:一个自然数,和前面的“装备孔”对应,如0表示武器,1表示防具。如果装备孔有重复的名称则这里也直接写名称(不用加引号),穿戴时会自动尝试寻找第一个同类型的空闲装备位,没有空闲的话会提示玩家先卸下一件。 - 2. 普攻动画:`project\animates`文件夹中任何一个文件的名称(不带后缀,但需要在全塔属性中注册过),只对第一个装备孔有效。普攻动画会播放在和勇士战斗的怪物位置处,如果是强制战斗的天降怪物,则会播放在勇士身上并跟随,请自行注意。详见“文件注册”使用动画。 - 3. 数值提升项:若干个键值对,表示该装备增加属性的常数值(支持负数)。7个常用属性可以通过下拉框选取,自定义的新属性也可以手动输入。 - 4. 百分比提升项:若干个键值对,表示该装备增加属性的百分比(支持负数,如填$-$10就表示减少10%),修改方法同上。 - 装备对属性的影响原理是:在穿脱装备时,会根据数值提升项和百分比提升项,分别调用`core.status.hero.xxx += yyy和core.addBuff('xxx', yyy)`[^10]这两个API(衰弱的附加和解除同理),而状态栏的显示值和战斗中的使用值则是`core.getStatus('xxx')`和buff值相乘再向下取整所得。 - -PC端按下Ctrl+0—9可以保存当前套装,Alt+0—9快速更换套装。 - -道具相关API请阅读libs\items.js(双击默认会运行,请用文本编辑器打开)。 ### 怪物属性 -1. 手册映射ID:如前所述,npc48提供了“行走图朝向”来实现多朝向,而怪物则没有这么好的待遇。如果您制作了四种面朝不同方向但属性完全一致的怪物,那么您可以将其中三种怪物的“手册映射ID”填写为剩下一种怪物的ID,这样手册中(确切地说,`core.getCurrentEnemys()`函数的因变量)就会统一显示为剩下那一种怪物。 -2. 生命、攻防、金经:如题,注意金经必须在“全塔属性”(快捷键B)中的“状态栏显示项”中也勾选才能真正被启用。持有幸运金币时打怪获得的金币翻倍,附加诅咒状态时打怪不获得金经。 -3. 加点:若全塔属性勾选了“加点”,则此项为正数时将作为与该怪物每场战斗胜利后传递给“公共事件——加点事件”的参数(即那里的flag:arg1,默认表示加点的倍率),您可以自行修改该事件。 -4. 不可炸:勾选后该怪物不会成为炸弹的目标,有阻击怪在场的情况下请务必给有战后事件的怪物(如机关门守卫和boss)勾选此项,否则玩家可能会偷梁换柱地炸掉该怪物并把阻击怪推过去打死来触发战后事件。 -5. 特殊属性:一个由正整数组成的一维数组,您可以点击“勾选框编辑”按钮来修改它。所有特殊属性都定义在“脚本编辑——怪物特殊属性”,您可以在那里追加新的。它们大体分为四类: + +1. **手册映射ID:**如前所述,npc48提供了“行走图朝向”来实现多朝向,而怪物则没有这么好的待遇。如果您制作了四种面朝不同方向但属性完全一致的怪物,那么您可以将其中三种怪物的“手册映射ID”填写为剩下一种怪物的ID,这样手册中(确切地说,`core.getCurrentEnemys()`函数的因变量)就会统一显示为剩下那一种怪物。 +2. **生命、攻防、金经:**如题,注意金经必须在“全塔属性”(快捷键B)中的“状态栏显示项”中也勾选才能真正被启用。持有幸运金币时打怪获得的金币翻倍,附加诅咒状态时打怪不获得金经。 +3. **加点:**若全塔属性勾选了“加点”,则此项为正数时将作为与该怪物每场战斗胜利后传递给“公共事件——加点事件”的参数(即那里的flag:arg1,默认表示加点的倍率),您可以自行修改该事件。 +4. **不可炸:**勾选后该怪物不会成为炸弹的目标,有阻击怪在场的情况下请务必给有战后事件的怪物(如机关门守卫和boss)勾选此项,否则玩家可能会偷梁换柱地炸掉该怪物并把阻击怪推过去打死来触发战后事件。 +5. **特殊属性:**一个由正整数组成的一维数组,您可以点击“勾选框编辑”按钮来修改它。所有特殊属性都定义在“脚本编辑——怪物特殊属性”,您可以在那里追加新的。它们大体分为四类: 1. 手册中属性值的修正:(按照结算顺序)模仿、坚固、光环,修正后的属性也将被用于战斗,详见“脚本编辑——怪物真实属性”。 2. 战损的修正:这类最多,先攻、魔攻、连击(次数为n)、破甲(比例为defValue)、反击(比例为atkValue,回合数为勇士的攻击回合数)、净化(倍数为n,1表示单纯无视护盾)、吸血(比例为value,是否加到自身为add)、仇恨(每场战斗的仇恨增值由全塔属性指定)、无敌、固伤(数值为damage)、支援。其中又以仇恨和固伤不能被护盾直接抵消而和无敌较为特殊,详见“脚本编辑——战斗伤害信息”。 3. 战后的影响:中毒、衰弱、诅咒、仇恨(的累加和减半)、自爆、退化(扣减值分别为atkValue和defValue)、重生,详见“脚本编辑——战后脚本”和“公共事件——毒衰咒处理”。 - 4. 阻激夹域捕:即对主角行走的妨害,详见“脚本编辑——阻激夹域伤害”,该函数也负责了血网(图块ID为lavaNet,请勿修改)的伤害。 + 4. 阻激夹域捕捉:即对主角行走的妨害,详见“脚本编辑——阻激夹域伤害”,该函数也负责了血网(图块ID为lavaNet,请勿修改)的伤害。 阻激域的伤害都为value且在夹击之前结算,领域的形状和半径与光环一致。 @@ -118,72 +127,61 @@ PC端按下Ctrl+0—9可以保存当前套装,Alt+0—9快速更换套装。 core.status.hero.flags.no_zone = true; // 禁用领域 core.status.hero.flags.no_ambush = true; // 禁用捕捉 core.getItem('amulet'); // 禁用血网等路障 - core.setEnemy('greenSlime', 'name', '绿史莱姆'); // 设置怪物属性,并计入存档 + core.setEnemy('greenSlime', 'atk', 100); // 设置怪物属性,并计入存档 core.getDamageString(enemy, x, y, floorId); // 获取某只怪的地图显伤字符串和颜色 core.getCurrentEnemys(floorId); // 获取某层楼的(映射后)怪物列表,按战损递增排列 core.hasEnemyLeft(enemyId, floorId); // 漏怪检测,两个参数都允许使用一维数组 - core.hasSpecial(src, n); // 检测src是否含有编号为n的特殊属性,src分为以下几种情况: + core.hasSpecial(special, test); // 检测special是否有test这一个特殊属性 ``` -如果src为一个数组,检查n是否在其中。为一个数字,检查是否和n全等; -为字符串,视为怪物ID去检查。为对象,将其special域作为src递归检查。 +如果您想在数据区的表格中追加新的属性项,或修改已有项的格式、范围和长短注释,请点击数据区顶部的“配置表格”按钮,并参照已有的项去追加和修改,具体可查阅[修改编辑器](editor)。 -如果您想在数据区的表格中追加新的属性项,或修改已有项的格式、范围和长短注释,请点击数据区顶部的“配置表格”按钮,并参照已有的项去追加和修改,具体可查阅@zhaouv撰写的另一篇文档。 ## 楼层属性(快捷键V) -![image](img/v2.7/floorsV.png) -1. 楼层ID:project\\floors中的文件名,不允许使用中文也不能直接修改。修改方法见上图底部,修改后必须立即刷新浏览器页面。 -2. 楼层名:楼层在楼传、上下楼黑屏和浏览地图界面的名称。 -3. 状态栏显示:勇士在此楼层时状态栏左上角上楼梯图标右边的文字,允许使用中文,但请注意控制字数。 -4. 宽度和高度:如题, - 如果地图被加宽或加高,则“偏移”表示右移或下移的格子数(左边缘或上边缘用空格子填补)。 - 如果地图被减窄或减矮,则“偏移”表示左移或上移的格子数(被移出左边缘或上边缘的图块将丢失)。 -5. 几个勾选框: - 1. 可楼传:如果不勾选,则此楼层禁止成为楼传的目标楼层,勇士在此楼层也禁止使用楼传。 - 2. 快捷商店:如果不勾选,则勇士在此楼层禁止快捷使用商店。事件中的“启用全局商店同时打开”不受影响,详见“插件编写——全局商店”。 - 3. 不可浏览:如果勾选,则此楼层无法通过PageUp/PageDown键浏览,也不会计入B键数据统计。 - 4. 不可瞬移:如果勾选,则勇士在此楼层无法用E键和单击瞬移,常用于用自动事件去监听勇士坐标时。 - 5. 是否是地下层:如果勾选,则非平面模式下勇士在此楼层原地使用楼传会传送到上楼点,详见“脚本编辑——楼层飞行”。 -6. 首次到达事件、每次到达事件:如题,详见“脚本编辑——切换楼层后”。 -7. 并行处理脚本:一个字符串,为勇士在此楼层时浏览器每帧都会执行一次(eval)的脚本,最快每秒60次。一般用来制作一些定时特效如bgs、bgv,详见“脚本编辑——并行脚本”。 -8. 上下楼点:两个自然数构成的一维数组,将作为“楼层转换”事件(在地图上以图块左下角出现绿色小方块作为标记)和“楼层切换”指令中“上下楼梯”以及非平面楼传的目标坐标。如果不设置,则在传送时会尝试从地图中搜索上下楼梯图块。因此当某个楼层没有楼梯或有多个楼梯时(如《[新新魔塔](http://ckcz123.com/games/xinxin/editor.html)》),请务必设置这个属性。点击“编辑”按钮从地图选点即可。 -9. 楼传落点:格式和设置方法同上。如果设置了此项,则楼传在此层的落点将强制变为该点,无视平面模式下的离开点和上面的上下楼点以及该层实际的楼梯位置。 -10. 地面图块:可以填写任何一个图块ID,此项也会作为手册和剧情对话中的帧动画背景。 -11. 色调:一行四列的数组,前三项为小于256的自然数(分别表示红、绿、蓝),最后一项为$[0,1]$的浮点数(表示不透明度),可以点击“编辑”按钮用取色器调色(见样板的主塔40层)。值得一提的是,很多事件也以颜色作为参数,这些都是可以使用取色器调色的。 +![image](img/floorsV.jpg) - 与RPG Maker不同,HTML5 canvas的色调合成公式是“此值×不透明度 + - 原值×(1$-$不透明度)”,所以即使给此项的红绿蓝填写相等的值也无法实现完美的灰色。如有需求,请使用[插件库](http://h5mota.com/plugins)的“仿RM光照”。 -12. 天气:一行两列的数组,第一项为字符串“rain”、“snow”或“fog”,第二项为不大于10的正整数,分别表示1—10级的雨天(见样板的主塔40层)、雪天(由大小不一的白色实心圆组成,详见样板1层)和雾天(由project\\materials\\fog.png放大后随时间加入不规则扰动得到)。 - - 色调层在天气层上方、UI层下方(如不透明色调会遮盖天气,浏览地图看不到色调),关于图层的详细说明,参见“个性化” -13. 背景音乐:如题,当在游戏中触发楼层切换时(包括读档),如果 - `core.status.hero.flags.__color__、__weather__、__bgm__`没有值,游戏当时的画面色调、天气、背景音乐就会变为楼层属性中的这三个设置项,详见“脚本编辑——切换楼层中”。 -14. 宝石血瓶效果:如题,必须填写且必须为非负数。此项的用法为core.status.thisMap.ratio,请参考四种血瓶和三种宝石的捡拾效果。 - - 您还可以将其用于其他各种场合作为系数,如血网的伤害、中毒后每步的损血等。 -15. 楼层贴图:至此我们会发现,图块只有32×32px和32×48px两种尺寸,且后者只能画在事件层,每个图块最多只能有4帧。 - -所以您可以在npcs.png中看到魔龙和章鱼被大卸八块,使用起来非常不方便。 - -所幸样板提供了“楼层贴图”,该项允许您使用任何尺寸、任何帧数的素材, - -唯一的缺点是不支持伸缩、移动跳跃和淡入淡出效果。 - -点击“编辑”按钮进入事件编辑器,每张图片的写法为(可从入口方块拖出,然后双击预览第一帧的效果): -1. 图片名(name):如题,图片需要放在project\images文件夹并注册。 -2. 翻转(:x/:y/:o):您可以对贴图的每帧进行三种翻转,当然,帧顺序在原图中依然是从左到右的。 -3. 图层(bg/fg/auto):此项决定贴图绘制在哪个图层,您可以全部画在背景层或前景层。也可以选择“自适配”让贴图的上半部分画在前景层,下半部分画在背景层,比如树木等。如果选择了自适配,最好让下面的绘制坐标和宽高都是32的倍数。 -4. 绘制坐标(x,y):贴图在地图中的左上角像素坐标,譬如x和y都填32则表示贴图左上角和“地图左上角格子的右下角”重合。 -5. 初始禁用(Y/N):如果勾选了此项,则此贴图初始时不显示,您可以在事件中再将其显示出来。 -6. 裁剪起点坐标(x,y)和宽高(w,h):此项规定了贴图在按帧切分前从原图中取哪一部分,x和y为所取部分在原图中的左上角坐标(不填视为两个0),w和h为所取部分的宽高(不填表示一直取到右下角)。 -7. 帧数(frame):不填视为1,如果填写了大于1的整数,就会把上述裁剪得到的结果再从左到右等分为若干份,并在实际绘制时从左到右逐帧(可能还带有翻转)循环绘制,每帧的持续时间和其他图块一致。 - -总之,每张贴图是按照“裁剪”—“左右等分”—“逐帧翻转”的顺序得到的。 - -贴图本身只具有观赏性,您仍然需要使用空气墙等手段去控制其绘制区域各个点的通行性。在使用贴图来表现魔龙和章鱼这类大型怪物时,可以预先注册两种一样属性的怪物。一种透明,另一种为缩小到32×32px且只有两到四帧的版本。将前者画在地图上,怪物属性的“手册映射ID”填后者,最后在该点的战后事件中隐藏贴图即可。最后附上贴图和图块绘制顺序的修改方法:(libs\maps.js) -``` js +1. **楼层ID:**`project/floors`中的文件名,不允许使用中文也不能直接修改。修改方法见上图底部,修改后必须立即刷新浏览器页面。 +2. **楼层名:**楼层在楼传、上下楼黑屏和浏览地图界面的名称。 +3. **状态栏显示:**勇士在此楼层时状态栏左上角上楼梯图标右边的文字,允许使用中文,但请注意控制字数。 +4. **地图宽度和高度:**可在表格最下方修改。 + * 如果地图被加宽或加高,则“偏移”表示右移或下移的格子数(左边缘或上边缘用空格子填补)。 + * 如果地图被减窄或减矮,则“偏移”表示左移或上移的格子数(被移出左边缘或上边缘的图块将丢失)。 +5. **几个勾选框:** + * 可楼传:如果不勾选,则此楼层禁止成为楼传的目标楼层,勇士在此楼层也禁止使用楼传。 + * 快捷商店:如果不勾选,则勇士在此楼层禁止快捷使用商店。事件中的“启用全局商店同时打开”不受影响,详见“插件编写——全局商店”。 + * 不可浏览:如果勾选,则此楼层无法通过PageUp/PageDown键浏览,也不会计入B键数据统计。 + * 不可瞬移:如果勾选,则勇士在此楼层无法用E键和单击瞬移,常用于用自动事件去监听勇士坐标时。 + * 是否是地下层:如果勾选,则非平面模式下勇士在此楼层原地使用楼传会传送到上楼点,详见“脚本编辑——楼层飞行”。 +6. **首次到达事件、每次到达事件:**如题,详见“脚本编辑——切换楼层后”。 +7. **并行处理脚本:**一个字符串,为勇士在此楼层时浏览器每帧都会执行一次(eval)的脚本,最快每秒60次。一般用来制作一些定时特效如bgs、bgv,详见“脚本编辑——并行脚本”。 +8. **上下楼点:**两个自然数构成的一维数组,将作为“楼层转换”事件(在地图上以图块左下角出现绿色小方块作为标记)和“楼层切换”指令中“上下楼梯”以及非平面楼传的目标坐标。 + * 如果不设置,则在传送时会尝试从地图中搜索上下楼梯图块。因此当某个楼层没有楼梯或有多个楼梯时(如《[新新魔塔](http://ckcz123.com/games/xinxin/editor.html)》),请务必设置这个属性。点击“编辑”按钮从地图选点即可。 +9. **楼传落点:**格式和设置方法同上。如果设置了此项,则楼传在此层的落点将强制变为该点,无视平面模式下的离开点和上面的上下楼点以及该层实际的楼梯位置。 +10. **地面图块:**可以填写任何一个图块ID,此项也会作为手册和剧情对话中的帧动画背景。 +11. **色调:**一行四列的数组,前三项为小于256的自然数(分别表示红、绿、蓝),最后一项为0到1的浮点数表示不透明度,可以点击“编辑”按钮用取色器调色(见样板的主塔40层)。 + * 值得一提的是,很多事件也以颜色作为参数,这些都是可以使用取色器调色的。 +12. **天气:**一行两列的数组,第一项为字符串“rain”、“snow”或“fog”,第二项为不大于10的正整数,分别表示1—10级的雨天(见样板的主塔40层)、雪天(由大小不一的白色实心圆组成,详见样板1层)和雾天(由`project/materials/fog.png`放大后随时间加入不规则扰动得到)。 + * 色调层在天气层上方、UI层下方(如不透明色调会遮盖天气,浏览地图看不到色调),关于图层的详细说明,参见“个性化” +13. **背景音乐:**如题,当在游戏中触发楼层切换时(包括读档),如果`flag:__color__、flag:__weather__、flag:__bgm__`没有值,游戏当时的画面色调、天气、背景音乐就会变为楼层属性中的这三个设置项,详见“脚本编辑——切换楼层中”。 +14. **宝石血瓶效果:**如题,必须填写且必须为非负数。此项的用法为core.status.thisMap.ratio,请参考四种血瓶和三种宝石的捡拾效果。 + * 您还可以将其用于其他各种场合作为系数,如血网的伤害、中毒后每步的损血等。 +15. **楼层贴图:** + * 由于样板提供的图块只有32×32px和32×48px两种尺寸,且后者只能画在事件层,每个图块最多只能有4帧,因此对于一些大图块十分不便。 + * 你可以使用“楼层贴图”,该项允许您使用任何尺寸、任何帧数的素材,唯一的缺点是不支持伸缩、移动跳跃和淡入淡出效果。 + * 点击“编辑”按钮进入事件编辑器,每张图片的写法为(可从入口方块拖出,然后双击预览第一帧的效果): + 1. 图片名(name):如题,图片需要放在`project/images`文件夹并注册。 + 2. 翻转(:x/:y/:o):您可以对贴图的每帧进行三种翻转,当然,帧顺序在原图中依然是从左到右的。 + 3. 图层(bg/fg/auto):此项决定贴图绘制在哪个图层,您可以全部画在背景层或前景层。也可以选择“自适配”让贴图的上半部分画在前景层,下半部分画在背景层,比如树木等。如果选择了自适配,最好让下面的绘制坐标和宽高都是32的倍数。 + 4. 绘制坐标(x,y):贴图在地图中的左上角像素坐标,譬如x和y都填32则表示贴图左上角和“地图左上角格子的右下角”重合。 + 5. 初始禁用(Y/N):如果勾选了此项,则此贴图初始时不显示,您可以在事件中再将其显示出来。 + 6. 裁剪起点坐标(x,y)和宽高(w,h):此项规定了贴图在按帧切分前从原图中取哪一部分,x和y为所取部分在原图中的左上角坐标(不填视为两个0),w和h为所取部分的宽高(不填表示一直取到右下角)。 + 7. 帧数(frame):不填视为1,如果填写了大于1的整数,就会把上述裁剪得到的结果再从左到右等分为若干份,并在实际绘制时从左到右逐帧(可能还带有翻转)循环绘制,每帧的持续时间和其他图块一致。 + * 贴图本身只具有观赏性,您仍然需要使用空气墙等手段去控制其绘制区域各个点的通行性。 + * 在使用贴图来表现魔龙和章鱼这类大型怪物时,可以预先注册两种一样属性的怪物。一种透明,另一种为缩小到32×32px且只有两到四帧的版本。将前者画在地图上,怪物属性的“手册映射ID”填后者,最后在该点的战后事件中隐藏贴图即可。 + * 你可以在插件重复写`drawBg`和`drawFg`函数以控制贴图和图块的绘制顺序,详见[脚本](script)。 + ``` js ////// 绘制背景层 ////// - maps.prototype.drawBg = function (floorId, ctx) { + core.maps.drawBg = function (floorId, ctx) { var onMap = ctx == null; if (onMap) { ctx = core.canvas.bg; @@ -191,54 +189,40 @@ PC端按下Ctrl+0—9可以保存当前套装,Alt+0—9快速更换套装。 } this._drawBg_drawBackground(floorId, ctx); // ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块 + // 后绘制的覆盖先绘制的。 this._drawFloorImages(floorId, ctx, 'bg'); this._drawBgFgMap(floorId, ctx, 'bg', onMap); -} // 后绘制的覆盖先绘制的。 -``` + } + ``` + ## 全塔属性(快捷键B) + 全塔属性共分为四部分:文件注册、初始勇士、全局数值、系统开关,您可以随时折叠其中任何一个部分。 -![image](img/v2.7/firstDataB.png) + +![image](img/firstDataB.jpg) + ### 文件注册 + 这部分基本上都是经由多选框半自动完成的,下面逐一讲解: -1. 楼层列表:project\floors文件夹中的文件名(不含后缀),此数组的顺序决定了楼传和上下楼器(fly、upFly、downFly)的顺序。 - - 如果您不慎将勇士的出生楼层注销了或不慎删除了某些楼层的js文件,导致编辑器页面打开后一片白屏,请手动打开project\data.js去小心地修改floorIds以和实际的文件名相匹配,并将出生楼层改为一个存在的楼层。 - - 其他更复杂的白屏请在控制台根据报错信息(安卓手机则使用ES文件浏览器查看日志)去小心地修改文件(如某个楼层文件有问题则可以注销它),如果难以独立解决,欢迎加QQ群959329661寻求帮助。 -2. 使用图片:project\images文件夹中的文件名(需要后缀,必须全英数),单击“编辑”按钮,编辑器会自动扫描文件系统中格式合适的图片(如jpg、png和gif)。 - - 您可以预览并将需要的图片勾选。请注意,勇士的初始行走图必须在这里注册。另外,winskin.png只许替换为相同规格的图片而不要注销,否则道具商店插件无法正常绘制。 -3. 额外素材:project\tilesets中的文件名(需要后缀,只支持png)。 - 注册方法同上,最大的区别在于这个数组的顺序必须保持好。如果随意调换其中的顺序,或注销不在数组末尾的图片,就会导致地图上最终呈现的素材发生错位。因此,新勾选的图片总会被自动追加到数组的末尾。 - - 比起常规素材,额外素材最大的好处有几点: - 1. 图片没有数量限制。常规素材的总数量最多只允许不到一千个,而额外素材每张图片上的图块数量最多允许一千个。 - 2. 查看和绘制更为方便。常规素材每个图块独占一行,每列为一帧,导致不方便观察,且用多个图块拼图必须逐图块绘制。额外素材都是静止的,所以每个图块只占一格,多个图块可以在准备素材时就直接以相邻的样子绘制在同一张图片上,绘制地图时直接从素材区拖动来批量框选,再在地图区单击成片绘制或拖动平铺。 - 3. 批量替换也更为方便。譬如您如果想制作形如“一场大战/天灾过后/多年以后,村庄/城镇化为了一片废墟”的效果,可以预先准备两张甚至更多张相同规格的额外素材图片,然后在适当的时候遍历某个/某些楼层的图块ID,将以“X1”开头的图块统一替换为“X2”开头等。发布单机版游戏时,您也可以提供多张相同规格的额外素材图片供玩家直接替换。当然,使用这类做法的话就没法再使用“额外素材合并”了。 - - 当您即将发布您的游戏时,可以使用“额外素材合并”工具将用到的额外素材图块重新拼成更少的图片,以减少游戏体积和加快在线游戏的加载。执行此操作后,额外素材的图块ID和数字(包括第一位)都将被打乱,因此请勿在制作中以任何方式直接引用其ID和数字。如确有此需求,请间接引用、等量代换,如“将$(x_1,y_1)$处的图块设置为和$(x_2,y_2)$处一样”、“判断$(x_3,y_3)$和$(x_4,y_4)$处的图块是否相同”。 -4. 使用动画:project\\animates文件夹中的文件名(不含后缀,请注意与`animates.png`相区分)。 - - 要使用动画,您可以使用“RM动画导出”工具从RPG Maker XP - 1.03及其制作的游戏中导出动画,也可以用动画编辑器修改已有的动画或用图片新建。但这些办法都只适用于Windows系统,非Windows系统建议直接从我们的官网下载他人的作品取用其中的动画。 - - 动画不支持在编辑器中预览,Windows系统可以使用“动画编辑器”预览但没有音效。 - - RPG Maker的动画存储方式是将用到的图片独立存放,而所有动画的帧信息(包括第几帧该用什么音效,会闪烁整个画面或当前图块)会集结在同一个文件中。 - - 而我们的存储方式则不同,是对每个动画将其用到的各张图片直接以base64硬编码进同一个animate文件,每个动画为一个animate文件。 - - 这样做的缺点是如果多个动画使用了相同的图片那么图片会被重复存储,优点则是跨作品迁移动画更加方便。 - - animate文件为文本文件,文件末尾记录了动画的帧信息,文件开头则记录了动画的伸缩比和唯一音效(会和动画同时开播)。 - - 在导出动画时,会出现一个输入框并提示动画的唯一音效名。不管该文件名是什么语种,请直接点击下一步。音效文件会被尝试自动复制,随后您只需手动注册该动画和音效并将音效文件名改为全英数。如果复制失败,则需要您手动去该RPG - Maker XP 1.03项目的SE文件夹中将这个文件复制出来(所以刚才最好记一下这个名字),放在您的H5魔塔项目的project\sounds文件夹中并改名为全英数,然后手动注册该动画和音效。 - - 如果要查看或修改一个动画和音效的对应关系(比如从官网上别的作品扒来的动画),请直接在注册时预览并修改。 - - 动画的播放速度为20FPS,即每帧50毫秒。这里给出几个相关API: -``` js +1. **楼层列表:**`project/floors`文件夹中的文件名(不含后缀),此数组的顺序决定了楼传和上下楼器(fly、upFly、downFly)的顺序。 + * 如果您不慎将勇士的出生楼层注销了或不慎删除了某些楼层的js文件,导致编辑器页面打开后一片白屏,请手动打开`project/data.js`去小心地修改floorIds以和实际的文件名相匹配,并将出生楼层改为一个存在的楼层。 + * 其他更复杂的白屏请在控制台根据报错信息(安卓手机则使用ES文件浏览器查看日志)去小心地修改文件(如某个楼层文件有问题则可以注销它),如果难以独立解决,欢迎加QQ群959329661寻求帮助。 +2. **使用图片:**`project/images`文件夹中的文件名(需要后缀,必须全英数),单击“编辑”按钮,编辑器会自动扫描文件系统中格式合适的图片(如jpg、png和gif)。 + * 您可以预览并将需要的图片勾选。请注意,勇士的初始行走图必须在这里注册。另外,`winskin.png`只许替换为相同规格的图片而不要注销,否则道具商店插件无法正常绘制。 +3. **额外素材:**`project/tilesets`中的文件名(需要后缀,只支持png)。 + * 注册方法同上,最大的区别在于这个数组的顺序必须保持好。如果随意调换其中的顺序,或注销不在数组末尾的图片,就会导致地图上最终呈现的素材发生错位。因此,新勾选的图片总会被自动追加到数组的末尾。 + * 比起常规素材,额外素材最大的好处有几点: + 1. 图片没有数量限制。常规素材的总数量最多只允许不到一千个,而额外素材每张图片上的图块数量最多允许一千个。 + 2. 查看和绘制更为方便。常规素材每个图块独占一行,每列为一帧,导致不方便观察,且用多个图块拼图必须逐图块绘制。额外素材都是静止的,所以每个图块只占一格,多个图块可以在准备素材时就直接以相邻的样子绘制在同一张图片上,绘制地图时直接从素材区拖动来批量框选,再在地图区单击成片绘制或拖动平铺。 + 3. 批量替换也更为方便。譬如您如果想制作形如“一场大战/天灾过后/多年以后,村庄/城镇化为了一片废墟”的效果,可以预先准备两张甚至更多张相同规格的额外素材图片,然后在适当的时候遍历某个/某些楼层的图块ID,将以“X1”开头的图块统一替换为“X2”开头等。发布单机版游戏时,您也可以提供多张相同规格的额外素材图片供玩家直接替换。当然,使用这类做法的话就没法再使用“额外素材合并”了。 + * 当您即将发布您的游戏时,可以使用“额外素材合并”工具将用到的额外素材图块重新拼成更少的图片,以减少游戏体积和加快在线游戏的加载。执行此操作后,额外素材的图块ID和数字(包括第一位)都将被打乱,因此请勿在制作中以任何方式直接引用其ID和数字。如确有此需求,请间接引用、等量代换。 +4. **使用动画:**`project/animates`文件夹中的文件名(不含后缀,请注意与`animates.png`相区分)。 + * 要使用动画,您可以使用“RM动画导出”工具从RPG Maker XP 1.03及其制作的游戏中导出动画,也可以用动画编辑器修改已有的动画或用图片新建。但这些办法都只适用于Windows系统,非Windows系统建议直接从我们的官网下载他人的作品取用其中的动画。 + * 每个动画将其用到的各张图片直接以base64硬编码进同一个animate文件,每个动画为一个animate文件。这样做的缺点是如果多个动画使用了相同的图片那么图片会被重复存储,优点则是跨作品迁移动画更加方便。animate文件为文本文件,文件末尾记录了动画的帧信息,文件开头则记录了动画的伸缩比和唯一音效(会和动画同时开播)。 + * 在导出动画时,会出现一个输入框并提示动画的唯一音效名。不管该文件名是什么语种,请直接点击下一步。音效文件会被尝试自动复制,随后您只需手动注册该动画和音效并将音效文件名改为全英数。 + * 可以在编辑器中预览动画和修改音效。 + * 可以使用如下动画相关的脚本对动画进行处理,或在事件中使用「播放动画」事件。 + ``` js core.drawAnimate(name, x, y, alignWindow, callback); // 播放一个动画,name为不带后缀的动画文件名,x和y为播放的格子坐标。 // alignWindow表示该坐标在大地图中是绝对坐标还是相对坐标,填true表示相对坐标。 @@ -248,136 +232,98 @@ PC端按下Ctrl+0—9可以保存当前套装,Alt+0—9快速更换套装。 core.drawHeroAnimate(name, callback); // 和上面类似,但该动画会跟随勇士移动。 // 每场战斗后,都会根据怪物坐标尝试用前者播放普攻动画。若坐标不存在 // (天降强制战斗),则会尝试用后者播放。看上去就像勇士在打自己,请自行注意。 -``` - 详见“脚本编辑——战后脚本”。上述两个函数都会返回一个每次不同的正整数id,您可以使用`core.stopAnimate(id, doCallback)`函数来立即停止一个正在播放的动画,其中doCallback为true表示停止时执行原动画的回调。 -1. 使用音乐:project\bgms文件夹中的文件名(需要后缀,默认只支持wav、mp3和ogg)。 - - 如果玩家使用的是手机且没有连接WiFi(iOS和部分浏览器无法获知网络状态,将始终视为流量党),那么背景音乐默认不会开启,可以在标题画面点击右下角的圆形按钮来开启。 - - 发布到官网的作品还可以从远程加载背景音乐,您可以点击此链接试听和下载其他作品的背景音乐。是否启用远程加载、以及启用时远程加载的根目录,由main.js指定。因此从官网下载其他作品的离线版本后请先关闭远程加载功能,才能正常加载本地注册的音乐。 - - 使用core.material.bgms可以查看所有的背景音乐,如果需要同时播放多个背景音乐并独立控制时刻和音量,请直接对它们使用play()方法并修改其currentTime(可读)和volume属性。 -2. 使用音效:project\sounds文件夹中的文件名(写法同上)。和动画不同, - - 音效的播放不支持回调,只支持提前停止,而且一停就会停止所有的。 - - 音效的音量是固定的,无法调节。此外,样板没有背景音效(bgs、bgv)的默认实现。如有需求,请使用并行脚本处理。 - - 音乐和音效在使用多选框注册时都支持试听,您可以看到它们的总时长和已播时长(精确到秒),从而指定音乐的开播秒数或配合使用“等待n毫秒”事件或并行脚本处理。 -3. 使用字体:project\fonts文件夹中的文件名(只支持ttf格式,不写后缀)。 - - 不建议给在线游戏版本添加中文字体,因为文件真的很大…… -4. 文件映射:如前所述,样板所有需要加载的文件名都必须是全英数。 - - 这一项允许你给文件取别名,别名可以使用任何语言的文字。 -5. 装备孔:见“道具的装备属性”。 -6. 标题音乐:如题,请注意部分浏览器不会在刚打开某个页面时就播放音频,必须用户操作一下才行。 -7. 主样式:一些css设置项,单击“编辑”按钮可以看到具体含义和用法,这里不再赘述(横竖屏标题画面背景支持gif动图)。 -8. 游戏名:标题画面和网页选项卡上显示的名字,可以和官网别的作品重名。 -9. 唯一英文标识符:必须修改,且不得和官网别的作品重名。只能使用全英数,如果您不确定一个标识符是否已被别的作品使用,请输入 ckcz123.com/games/xxx ,如出现404就说明xxx未被使用。 -10. 游戏版本:当您的游戏发生版本更迭后,旧版本的存档直接读取可能会出现bug.因此届时您可以修改此项来让旧存档无法直接读取,只能回放其录像。 -11. 难度分歧:单击“编辑”按钮进入事件编辑器,每个难度分为以下几项。 - 1. 名称:标题界面单击“开始游戏”后出现的二级菜单中的文字。 - - 一般为该难度的最简要的介绍,如减伤比例、初始福利等。 - - 2. 简写:横屏状态栏左下角(竖屏右下角,也作为数字键切换按钮)和存读档界面缩略图上的文字,也会出现在在线游戏排行榜和旧版官网的作品卡片上。允许使用中文但请注意控制字数,用core.status.hard表示。 - 3. 变量hard值:若同一结局有多个难度有人通关,则上述排行榜只统计此值最高的难度。 - 4. 颜色:上述“简写”的颜色,用`core.status.hero.flags.__hardColor__`表示,默认为红色。详见“脚本编辑——更新状态栏”。 - 5. 事件:此事件比下述的“开场剧情”更早执行,一般用来设置初始福利。 -如果将难度分歧数组留空,那么标题界面单击“开始游戏”就会直接进入开场剧情。即core.hideStartAnimate(core.startGame) + core.stopAnimate(id, doCallback); // 停止一段动画 + ``` +5. **使用音乐:**`project/bgms`文件夹中的文件名(需要后缀,默认只支持wav、mp3和ogg)。 + * 如果玩家使用的是手机且没有连接WiFi(iOS和部分浏览器无法获知网络状态,将始终视为流量党),那么背景音乐默认不会开启,可以在标题画面点击右下角的圆形按钮来开启。 + * 发布到官网的作品还可以从远程加载背景音乐,您可以点击此链接试听和下载其他作品的背景音乐。 + * 是否启用远程加载、以及启用时远程加载的根目录,由main.js指定。因此从官网下载其他作品的离线版本后请先关闭远程加载功能,才能正常加载本地注册的音乐。 + * 使用core.material.bgms可以查看所有的背景音乐,如果需要同时播放多个背景音乐并独立控制时刻和音量,请直接对它们使用play()方法并修改其currentTime(可读)和volume属性。 +6. **使用音效:**`project/sounds`文件夹中的文件名(写法同上)。和动画不同,音效的播放不支持回调,只支持提前停止,而且一停就会停止所有的。 + * 音效的音量是固定的,无法调节。此外,样板没有背景音效(bgs、bgv)的默认实现。如有需求,请使用并行脚本处理。 + * 音乐和音效在使用多选框注册时都支持试听,您可以看到它们的总时长和已播时长(精确到秒),从而指定音乐的开播秒数或配合使用“等待n毫秒”事件或并行脚本处理。 +7. **使用字体:**project\fonts文件夹中的文件名(只支持ttf格式,不写后缀)。不建议给在线游戏版本添加中文字体,因为文件真的很大…… +8. **文件映射:**如前所述,样板所有需要加载的文件名都必须全部是英文或数字。这一项允许你给文件取别名,别名可以使用任何语言的文字。 +9. **装备孔:**见“道具的装备属性”。 +10. **标题音乐:**如题,请注意部分浏览器不会在刚打开某个页面时就播放音频,必须用户操作一下才行。 +11. **主样式:**一些css设置项,单击“编辑”按钮可以看到具体含义和用法,这里不再赘述(横竖屏标题画面背景支持gif动图)。 +12. **游戏名:**标题画面和网页选项卡上显示的名字,可以和官网别的作品重名。 +13. **唯一英文标识符:** **必须修改,且不得和官网别的作品重名**。只能使用字母数字下划线,如果您不确定一个标识符是否已被别的作品使用,请输入[https://h5mota.com/games/xxx](https://h5mota.com/games/xxx),如出现404就说明此项未被使用。 +14. **游戏版本:**当您的游戏发生版本更迭后,旧版本的存档直接读取可能会出现bug.因此届时您可以修改此项来让旧存档无法直接读取,只能回放其录像。 +15. **难度分歧:**单击“编辑”按钮进入事件编辑器,每个难度分为以下几项。 + * 名称:标题界面单击“开始游戏”后出现的二级菜单中的文字。一般为该难度的最简要的介绍,如减伤比例、初始福利等。 + * 简写:横屏状态栏左下角(竖屏右下角,也作为数字键切换按钮)和存读档界面缩略图上的文字,也会出现在在线游戏排行榜和旧版官网的作品卡片上。允许使用中文但请注意控制字数,用core.status.hard表示。 + * 变量hard值:若同一结局有多个难度有人通关,则上述排行榜只统计此值最高的难度。 + * 颜色:上述“简写”的颜色,用`core.status.hero.flags.__hardColor__`表示,默认为红色。详见“脚本编辑——更新状态栏”。 + * 事件:此事件比下述的“开场剧情”更早执行,一般用来设置初始福利。 + * 如果将难度分歧数组留空,那么标题界面单击“开始游戏”就会直接进入开场剧情。 ### 初始勇士 -1. 初始楼层、朝向和坐标:如题,请注意初始楼层必须在上述的“楼层列表”中。初始坐标一般通过右击地图上的空地快速绑定,但您也可以手动在这里填写负数或超出初始楼层宽高的值。然后使用“无视地形移动勇士”或“跳跃勇士”等改变勇士位置的事件指令,做出“勇士从地图外进入”的演出效果。 - 如需根据难度分歧或用户选项来改变它们,请在“开场剧情”中修改core.firstData.floorId和core.firstData.hero.loc -2. 行走图:如题,必须在“使用图片”中注册过。宽高必须为4的倍数,宽度至少为128px(即每帧32px)。高度不限,剧情对话中和状态栏中会尝试保持比例压缩到每帧32px宽。 - - 在游戏中,勇士当前的行走图文件名用core.status.hero.flags.heroIcon表示(只读)。 -3. 帧动画:勾选此项后,勇士在剧情对话中(朝上视为朝下)和原地不动时会循环播放四帧踏步动画,一般用于长翅膀的勇士。 -4. 勇士名:如题,也会作为剧情对话中`\t[hero]`的默认标题。 -5. 初始等级:如果开启了自动进阶功能,请不要修改此项。 -6. 生命上限、魔力上限、初始生命/魔力/攻防/护盾/金经:如题。 - - 注意生命上限和金经需要在系统开关中勾选后才会启用,魔力上限填负数代表没有上限。 -7. 初始装备、游戏变量:建议留空(事件中的变量初始时都会视为0,脚本中也有办法做到)。 -8. 永久道具、消耗道具、初始拥有装备个数:点击“注释”按钮,按照提示进行修改。 -9. 标题事件:需要配合系统开关中勾选“标题开启事件化”来使用,可以在“开始游戏”、“读取存档”之余添加一些额外的功能。如成就系统、音像和回想鉴赏,但这并不是唯一的方法,请自行研究。 -10. 开场剧情:会在难度分歧事件之后执行,可以在这里设置各种变量的初始值、穿上初始拥有的装备、隐藏勇士和一些初始不希望显示的图层块、追加跟随者等。 -11. 全局商店:详见“QTE与全局商店”。 -12. 等级提升:需要配合系统开关中勾选“等级”、“经验”和“升级”来使用,每个等级分为以下几项: - 1. 需求:刷新状态栏时,如果勇士当前等级是此等级的前一级,且经验值大于等于此需求,就会触发升级。 - - 因此如果您想设计“低难度初始等级较高”,请直接增加经验。 - - 触发升级后会再次检查下一个等级,直到经验不足或等级已满。 - - 所以您不必担心一次获得太多经验连续触发升级会出bug. - - 2. 称号:状态栏显示的等级默认是个正整数,会尝试替换为这里的称号(调用core.getLvName()函数),请注意控制字数。 - 3. 是否扣除经验:如果勾选了此项,则触发升级时经验值会扣除需求值。 - 4. 事件:触发升级时执行的事件,如全面提升属性。 +1. **初始楼层、朝向和坐标:**如题,请注意初始楼层必须在上述的“楼层列表”中。初始坐标一般通过右击地图上的空地快速绑定,但您也可以手动在这里填写负数或超出初始楼层宽高的值。然后使用“无视地形移动勇士”或“跳跃勇士”等改变勇士位置的事件指令,做出“勇士从地图外进入”的演出效果。 + * 如需根据难度分歧或用户选项来改变它们,请在“开场剧情”中修改core.firstData.floorId和core.firstData.hero.loc +2. **行走图:**如题,必须在“使用图片”中注册过。宽高必须为4的倍数,宽度至少为128px(即每帧32px)。高度不限,剧情对话中和状态栏中会尝试保持比例压缩到每帧32px宽。 + * 在游戏中,勇士当前的行走图文件名用core.status.hero.image表示(只读)。 +3. **帧动画:**勾选此项后,勇士在剧情对话中(朝上视为朝下)和原地不动时会循环播放四帧踏步动画,一般用于长翅膀的勇士。 +4. **勇士名:**如题,也会作为剧情对话中`\t[hero]`的默认标题。 +5. **初始等级:**如果开启了自动进阶功能,请不要修改此项。 +6. **生命上限、魔力上限、初始生命/魔力/攻防/护盾/金经:**如题。注意生命上限和金经需要在系统开关中勾选后才会启用,魔力上限填负数代表没有上限。 +7. **初始装备、游戏变量:**建议留空(事件中的变量初始时都会视为0,脚本中也有办法做到)。 +8. **永久道具、消耗道具、初始拥有装备个数:**点击“注释”按钮,按照提示进行修改。 +9. **标题事件:**需要配合系统开关中勾选“标题开启事件化”来使用,可以在“开始游戏”、“读取存档”之余添加一些额外的功能。如成就系统、音像和回想鉴赏,但这并不是唯一的方法,请自行研究。 +10. **开场剧情:**会在难度分歧事件之后执行,可以在这里设置各种变量的初始值、穿上初始拥有的装备、隐藏勇士和一些初始不希望显示的图层块、追加跟随者等。 +11. **全局商店:**详见“QTE与全局商店”。 +12. **等级提升:**需要配合系统开关中勾选“等级”、“经验”和“升级”来使用,每个等级分为以下几项: + * 需求:刷新状态栏时,如果勇士当前等级是此等级的前一级,且经验值大于等于此需求,就会触发升级。 + * 称号:状态栏显示的等级默认是个正整数,会尝试替换为这里的称号(调用core.getLvName()函数),请注意控制字数。 + * 是否扣除经验:如果勾选了此项,则触发升级时经验值会扣除需求值。 + * 事件:触发升级时执行的事件,如全面提升属性。 ### 全局数值 -![image](img/v2.7/values&flagsB.png) -这个类型的数值会保存在core.values中,可以直接在游戏中修改。 -1. 血网伤害和中毒伤害:如题,如果不想用常数,请修改“脚本编辑”的“阻激夹域伤害”和“每步后操作”。 -2. 衰弱效果:填小于1的正数代表扣减的比例,否则为扣减的常数。 - 扣减和恢复的原理和装备相同,详见“公共事件——毒衰咒处理”、解衰药水和万能药水的使用效果。 -3. 三种宝石和四种血瓶的值:如题,此值为基础值。实际效果还需乘以楼层属性最下面的“宝石血瓶效果”(限即捡即用类,详见这七种道具的属性。此外,B键数据统计是按照此值乘以“宝石血瓶效果”统计的,与道具的实际效果无关,请自行注意。 -4. 反击、破甲、净化比例:如果反击、破甲、净化怪物没有指定atkValue、defValue和n,就会用这三个值。请注意反击的总回合数是勇士的攻击回合数,净化比例填1表示单纯无视护盾。 -5. 仇恨增值:每进行一场战斗,core.status.hero.flags.hatred的增加量。如果不想用常数,请修改“脚本编辑——战后脚本”。 -6. 全局帧动画时间:即怪物和NPC的振动速度,建议改为300毫秒。 -7. 竖状态栏自绘行数:需要配合系统开关“开启自绘状态栏”使用,建议改为4. +![image](img/values_flagsB.jpg) + +这个类型的数值会保存在core.values中,可以直接在游戏中修改。 + +1. **血网伤害和中毒伤害:**如题,如果不想用常数,请修改“脚本编辑”的“阻激夹域伤害”和“每步后操作”。 +2. **衰弱效果:**填小于1的正数代表扣减的比例,否则为扣减的常数。扣减和恢复的原理和装备相同,详见“公共事件——毒衰咒处理”、解衰药水和万能药水的使用效果。 +3. **三种宝石和四种血瓶的值:**如题,此值为基础值。实际效果还需乘以楼层属性最下面的“宝石血瓶效果”(限即捡即用类,详见这七种道具的属性。此外,B键数据统计是按照此值乘以“宝石血瓶效果”统计的,与道具的实际效果无关,请自行注意。 +4. **反击、破甲、净化比例:**如果反击、破甲、净化怪物没有指定atkValue、defValue和n,就会用这三个值。请注意反击的总回合数是勇士的攻击回合数,净化比例填1表示单纯无视护盾。 +5. **仇恨增值:**每进行一场战斗,core.status.hero.flags.hatred的增加量。如果不想用常数,请修改“脚本编辑——战后脚本”。 +6. **全局帧动画时间:**即怪物和NPC的振动速度,建议改为300毫秒。 +7. **竖状态栏自绘行数:**需要配合系统开关“开启自绘状态栏”使用,建议改为4. ### 系统开关 + 这个类型的开关会保存在core.flags中(只读),请注意和core.status.hero.flags相区分。如需在游戏中修改,请使用“设置系统开关”事件。 -1. 状态栏显示项:如题,总个数请控制在12个以内,否则竖屏可能塞不下。 - 多说一句,这些项的图标都在`project\materials\icons.png`中。 - - 该文件夹下也提供了一个`icons_old.png`可供替换。 - - “血限”、“金币”和“经验”必须勾选才会启用(指会处理生命溢出、金经会显示在手册、打怪也会掉落), - - 必须勾选“升级”才会启用自动进阶,“升级扣除模式”如果不勾选就会同时显示下一级的需求(NEXT)和当前经验(EXP,如果勾选了的话),否则会只显示两者的差(依然用NEXT图标)。 - - 如果同时勾选了“钥匙”和“绿钥”,则每种钥匙的数量都会被缩小尺寸显示,因此如非必要请不要勾选“绿钥”。 -2. 楼传需在楼梯边:如果勾选了此项,则只有勇士在楼梯旁边(如果开启了下述的平面模式则还包括四种三帧箭头旁边)时才允许使用楼传。 - - 请注意,此项是在楼传道具使用条件之外额外进行的判定,目的是给出不同的提示信息。因此如果您要修改楼传的使用条件(指总的使用条件,具体能否飞到某层的条件则在“脚本编辑——楼层飞行”),则可能需要一并取消此勾选。 -3. 楼传开平面模式:如果勾选了此项,则勇士在使用楼传飞往某层时会落在上次离开该层的位置。此外,上述“在楼梯边”也会包括“在四种三帧箭头旁边”。 -4. 铁门不消耗钥匙:如果勾选了此项,则铁门无需钥匙也能撞开。 - - 勾选后,您可以将铁门的开门动画ps为墙壁状,来批量制作暗道。 - - 直接把三色墙等的图块的“触发器”改为openDoor也是可以的。 -5. 首次道具进行提示:勾选后,首次捡到非即捡即用类道具都会弹窗提示(晚于afterGetItem事件被执行)。 -6. 状态栏装备按钮:勾选后,状态栏的楼传按钮会变为装备栏按钮,但玩家仍然可以双击道具栏来呼出装备栏。 -7. 加点和负伤:前者勾选后怪物的加点值会在“脚本编辑——战后脚本”中作为参数core.status.hero.flags.arg1被传递给“公共事件——加点事件”。 - - 后者勾选后,战斗结束时如果勇士的护盾没有完全被打破,则剩余的护盾值会加到其生命上。所以勾选此项后,护盾可以这样“间接”抵消掉仇恨伤害和固伤。 - -8. 夹击不超伤害值:勾选此项后,夹击伤害将封顶至夹击怪的战损。 - - 同时被四只怪夹击时,取两个战损中较小的。 -9. 二分临界:我们知道,打败怪物所需的回合数,取决于勇士的攻击减去怪物的防御。这个值并非每增大1都能使回合数减少,因而有了“临界”的说法,即“再至少增加多少攻击力,才能减少回合数”。然而,当您修改“脚本编辑——战斗伤害信息”函数后,攻击力的增加可能反而导致回合数也增加,于是临界值计算出错。您可以勾选此开关来修复,代价是游戏可能较卡,请自行权衡。 -10. 标题开启事件化:勾选此项后,标题画面将改为执行前述的“标题事件”,请自行研究。 -11. 开启自绘状态栏:勾选此项后,状态栏将改用“脚本编辑——自绘状态栏”来绘制,同时“脚本编辑——点击状态栏”也将启用,请自行研究。 -12. 三个显伤:略,玩家依然可以在设置菜单中开关之。 -13. 允许轻按:勾选此项后,玩家可以按下空格/大键盘数字7/双击勇士来拾取相邻的唯一道具,或面前的道具。 -14. 允许穿透楼梯:在狭窄的区域拦路放置一个可通行的“楼层转换”事件时(图块左下角出现绿色标记),玩家可能希望勇士能直接走过去。您可以逐个去设置其能否被这样走过,或者让其依据本勾选项。 - - 值得注意的是,当玩家从允许穿透的楼梯向一个不可走的方向(如旁边是墙,或不勾选下一个开关时的致命领域)手动寻路时,可以停在楼梯上(进而再轻按拾取周围物品等)。不建议您利用这类极端情况去迫使玩家进行非常规操作,毕竟穿透楼梯和不能踏入致命领域的本意是方便玩家,不是么? -15. 允许将死领域:“脚本编辑——阻激夹域伤害”会将地图中每个点的阻激夹域和血网伤害加总,如果不勾选此开关,则当勇士生命小于等于相邻空格子的总伤害(没有则视为0)时,勇士无法走向该格子。 - - 值得注意的是,这种判定方式并没有考虑“走这一步后、结算该点伤害前”可能的加血或该点伤害变化,因此您可能需要根据“脚本编辑——每步后操作”去修改core.canMoveHero()函数。 -16. 允许瞬移:若不勾选此开关,将全程禁用瞬移功能。一般只建议在需要的楼层逐层勾选禁止瞬移(主要为了用自动事件去监听勇士的坐标),详见`core.maps._canMoveDirectly_checkGlobal()`函数。 -17. 伤害禁用商店:勾选此项后,每当勇士踩到阻激夹域和血网并受到伤害时,所有全局商店都将被禁用,需要重新去启用(譬如勇士去撞击该商店的实体NPC)。详见`core.control._checkBlock_disableQuickShop()`函数。 -18. 虚化前景层:前景层会遮挡事件层,这对魔塔来说有时可能不太友好。 - - 勾选此项后,事件层有东西(如道具)时将虚化该格子的前景层,使得该东西以半透明状态可见。 +1. **状态栏显示项:**如题,总个数请控制在12个以内,否则竖屏可能塞不下。 + * 这些项的图标都在`project\materials\icons.png`中。该文件夹下也提供了一个`icons_old.png`可供替换。 + * “血限”、“金币”和“经验”必须勾选才会启用(指会处理生命溢出、金经会显示在手册、打怪也会掉落), + * 必须勾选“升级”才会启用自动进阶,“升级扣除模式”如果不勾选就会同时显示下一级的需求(NEXT)和当前经验(EXP,如果勾选了的话),否则会只显示两者的差(依然用NEXT图标)。 + * 如果同时勾选了“钥匙”和“绿钥”,则每种钥匙的数量都会被缩小尺寸显示,因此如非必要请不要勾选“绿钥”。 +2. **楼传需在楼梯边:**如果勾选了此项,则只有勇士在楼梯旁边(如果开启了下述的平面模式则还包括四种三帧箭头旁边)时才允许使用楼传。 + * 请注意,此项是在楼传道具使用条件之外额外进行的判定,目的是给出不同的提示信息。 + * 因此如果您要修改楼传的使用条件(指总的使用条件,具体能否飞到某层的条件则在“脚本编辑——楼层飞行”),则可能需要一并取消此勾选。 +3. **楼传开平面模式:**如果勾选了此项,则勇士在使用楼传飞往某层时会落在上次离开该层的位置。此外,上述“在楼梯边”也会包括“在四种三帧箭头旁边”。 +4. **铁门不消耗钥匙:**如果勾选了此项,则铁门无需钥匙也能撞开。 +5. **首次道具进行提示:**勾选后,首次捡到非即捡即用类道具都会弹窗提示(晚于afterGetItem事件被执行)。 +6. **状态栏装备按钮:**勾选后,状态栏的楼传按钮会变为装备栏按钮,但玩家仍然可以双击道具栏来呼出装备栏。 +7. **加点:**勾选后怪物的加点值会在“脚本编辑——战后脚本”中作为参数core.status.hero.flags.arg1被传递给“公共事件——加点事件”。 +8. **负伤:**勾选后,战斗结束时如果勇士的护盾没有完全被打破,则剩余的护盾值会加到其生命上。所以勾选此项后,护盾可以这样“间接”抵消掉仇恨伤害和固伤。 +9. **夹击不超伤害值:**勾选此项后,夹击伤害将封顶至夹击怪的战损。同时被四只怪夹击时,取两个战损中较小的。 +10. **二分临界:**我们知道,打败怪物所需的回合数,取决于勇士的攻击减去怪物的防御。这个值并非每增大1都能使回合数减少,因而有了“临界”的说法,即“再至少增加多少攻击力,才能减少回合数”。然而,当您修改“脚本编辑——战斗伤害信息”函数后,攻击力的增加可能反而导致回合数也增加,于是临界值计算出错。您可以勾选此开关来修复,代价是游戏可能较卡,请自行权衡。 +11. **标题开启事件化:**勾选此项后,标题画面将改为执行前述的“标题事件”,请自行研究。 +12. **开启自绘状态栏:**勾选此项后,状态栏将改用“脚本编辑——自绘状态栏”来绘制,同时“脚本编辑——点击状态栏”也将启用,请自行研究。 +13. **三个显伤:**略,玩家依然可以在设置菜单中开关之。 +14. **允许轻按:**勾选此项后,玩家可以按下空格/大键盘数字7/双击勇士来拾取相邻的唯一道具,或面前的道具。 +15. **允许穿透楼梯:**在狭窄的区域拦路放置一个可通行的“楼层转换”事件时(图块左下角出现绿色标记),玩家可能希望勇士能直接走过去。您可以逐个去设置其能否被这样走过,或者让其依据本勾选项。 + * 值得注意的是,当玩家从允许穿透的楼梯向一个不可走的方向(如旁边是墙,或不勾选下一个开关时的致命领域)手动寻路时,可以停在楼梯上(进而再轻按拾取周围物品等)。不建议您利用这类极端情况去迫使玩家进行非常规操作,毕竟穿透楼梯和不能踏入致命领域的本意是方便玩家,不是么? +16. **允许将死领域:**“脚本编辑——阻激夹域伤害”会将地图中每个点的阻激夹域和血网伤害加总,如果不勾选此开关,则当勇士生命小于等于相邻空格子的总伤害(没有则视为0)时,勇士无法走向该格子。 + * 值得注意的是,这种判定方式并没有考虑“走这一步后、结算该点伤害前”可能的加血或该点伤害变化,因此如有必要可根据“脚本编辑——每步后操作”去修改core.canMoveHero()函数。 +17. **允许瞬移:**若不勾选此开关,将全程禁用瞬移功能。一般只建议在需要的楼层逐层勾选禁止瞬移。 +18. **伤害禁用商店:**勾选此项后,每当勇士踩到阻激夹域和血网并受到伤害时,所有全局商店都将被禁用,需要重新去启用(譬如勇士去撞击该商店的实体NPC)。 +19. **虚化前景层:**前景层会遮挡事件层,这对魔塔来说有时可能不太友好。勾选此项后,事件层有东西(如道具)时将虚化该格子的前景层,使得该东西以半透明状态可见。 上面就是整个样板中的各个元件说明。通过这种方式,你就已经可以做出一部没有任何事件的塔了。 diff --git a/_docs/event.md b/_docs/event.md index ccd86d5f..a1be436a 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -1,72 +1,82 @@ # 事件 -?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} *
+ +?> 在这一节中,让我们来了解事件系统的基本原理 + ## 事件编辑(地图选点,快捷键X) -![image](img/v2.7/eventsX.png) + +![image](img/eventsX.jpg) + 样板所有的事件都是依靠“触发器”完成的。例如,勇士碰到(绑定好的)楼梯可以触发changeFloor,碰到门可以触发openDoor,碰到怪物可以触发battle,碰到道具可以触发getItem,碰到箱子可以触发pushBox,走上冰面(背景层)可以触发ski. -这些触发器都是系统自带的,已经存在处理机制,不需要我们操心。我们真正所需要关心的,其实只是自定义的事件(如NPC)。 +这些触发器都是系统自带的(称为系统事件),已经存在处理机制,不需要我们操心。我们真正所需要关心的,其实只是自定义的事件(如NPC)。 地图选点(快捷键X)一共有七项,在地图中以图块左下角用七色小方块标记。 -红色为普通事件,橙色为自动事件,黄色为战后事件,绿色为楼层转换,青色为(拾获)道具后事件,靛色(不是事件)为勇士站在该点不能朝哪些方向走,紫(粉)色为开门后事件。此外还有一些事件不在地图上,如“首次到达”、“每次到达”(这两个的触发原理,详见“脚本编辑——切换楼层后”)、“道具效果”、“公共事件”和全塔属性中那五个事件。 +* **红色:**普通事件 +* **橙色:**自动事件 +* **黄色:**战后事件 +* **绿色:**楼层转换 +* **青色:**获得道具后事件 +* **靛色:**不是事件,为勇士站在该点不能朝哪些方向走 +* **紫(粉)色:**开门后事件。 + +此外还有一些事件不在地图上,如“首次到达”、“每次到达”(这两个的触发原理,详见“脚本编辑——切换楼层后”)、“道具效果”、“公共事件”和全塔属性中那五个事件。 ### 事件的机制 + 地图上的所有事件都存在两种状态:启用和禁用。 -- 启用状态下,该事件才处于可见状态,可被触发、交互与处理。 -- 禁用状态下,该事件几乎相当于不存在,不可见、不可被触发、不可交互,只能通过“插入事件”指令远程调用。 + +* 启用状态下,该事件才处于可见状态,可被触发、交互与处理。 +* 禁用状态下,该事件几乎相当于不存在,不可见、不可被触发、不可交互,只能通过“插入事件”指令远程调用。 所有事件默认情况下初始都是启用的,只有普通事件可以通过不勾选“启用”来初始隐藏。 在事件列表中使用“显示事件”和“隐藏事件”可以将一个禁用事件给启用,或将一个启用事件给禁用,甚至直接从地图中删除。 -如想让一个普通事件(红)或楼层转换事件(绿)隐形但不禁用,请将其“转变图块为”0(空地)或17(空气墙)。 - -【重要警告】: +**【重要警告】:** 1. 打怪开门捡道具后,如果有对应的坐标,则该点的事件会被从地图中删除(重生怪除外,它只会被暂时隐藏)。然后会尝试执行该点的战后事件、开门后事件或(拾获)道具后事件(您可以勾选“轻按时不触发”)。如果执行,则“当前点坐标”(core.status.event.data的坐标)也会变为该点。 - - 所以,这三个XX后事件,其实是有可能被多次触发或意外触发的(如打死或炸掉某个有战后事件的怪,推了个阻击怪过去打死),请自行注意。 + * 所以,这三个XX后事件,其实是有可能被多次触发或意外触发的(如打死或炸掉某个有战后事件的怪,推了个阻击怪过去打死),请自行注意。 2. “移动事件”(如阻击和捕捉)和“跳跃事件”(如支援)会将起点处的事件从地图中删除,如果不勾选“不消失”(如阻击),则会在终点处“转变图块”并“显示事件”。但事件的内容不会被跟着移动到终点,推箱子同理,但在终点只转变图块而不予显示。 + ### 楼梯、传送门事件 -![image](img/v2.7/changeFloor.png) + +![image](img/changeFloor.jpg) 当您在地图上绘制楼梯、或绘制四种三帧箭头并右击绑定后,就创建了一个“楼层转换”事件,您可以在事件编辑器右侧看到一行代码(json),请注意对照。 -此事件与core.changeFloor(floorId, stair, heroLoc, time, -callback)函数相对应,只是多了一项“穿透性”。 +此事件与`core.changeFloor(floorId, stair, heroLoc, time, callback)`函数相对应,只是多了一项“穿透性”。 每个这样的事件都是上图的写法,下面逐一讲解其各项的含义和用法: -1. 目标楼层(floorId):如题,如果选择了“楼层ID”就需要在第二个框中输入目标楼层的ID(会自动提示补全,也可以双击整个紫色块从地图选点)。如果选择了其他三种,则json代码中“:before”、“:next”、“:now”分别表示“前一楼”、“后一楼”(顺序由“全塔属性——楼层列表”指定,上下楼器同理)和“当前楼”,函数中也是一样的写法。 -2. 目标位置(stair):如果选择了“坐标”则需要在后面两个框里输入(同样可以地图选点,在函数中则将stair填null并填写heroLoc),也可以选择下拉框中的其他几项(在函数中则将heroLoc填null),如保持不变(:now)、中心对称(:symmetry)、左右对称(`:symmetry_x`)、上下对称(`:symmetry_y`)或任何一个图块ID. - 填写三种对称位置时请注意,坐标计算以当前楼层而不是目标楼层为准,尤其要注意防止勇士出界。 - - 填写图块ID时请注意,“上下楼梯”提供在了下拉框中,实际传送时会优先尝试取用目标层的“楼层属性——上下楼点”。其次尝试像其他ID一样从目标楼层搜索,因此请确保该图块在目标楼层中存在且唯一。 -3. 朝向:有八种写法,可以直接填写改变后的朝向(up、down、left、right),也可以填写转身的角度(:left、:right、:back)或不变。 - -4. 动画时间:指黑屏的毫秒数,可以填0或不小于100的整数,不填则使用玩家设定值。 - -5. 穿透性:见[系统开关]允许穿透楼梯。 +1. **目标楼层(floorId):**如题,如果选择了“楼层ID”就需要在第二个框中输入目标楼层的ID(会自动提示补全,也可以双击整个紫色块从地图选点)。如果选择了其他三种,则json代码中`:before`、`:next`、`:now`分别表示“前一楼”、“后一楼”(顺序由“全塔属性——楼层列表”指定,上下楼器同理)和“当前楼”,函数中也是一样的写法。 +2. **目标位置(stair):**如果选择了“坐标”则需要在后面两个框里输入(同样可以地图选点,在函数中则将`stair`填`null`并填写`heroLoc`),也可以选择下拉框中的其他几项(在函数中则将`heroLoc`填`null`),如保持不变(`:now`)、中心对称(`:symmetry`)、左右对称(`:symmetry_x`)、上下对称(`:symmetry_y`)或任何一个图块ID. + * 填写三种对称位置时请注意,坐标计算以当前楼层而不是目标楼层为准,尤其要注意防止勇士出界。 + * 填写图块ID时请注意,“上下楼梯”提供在了下拉框中,实际传送时会优先尝试取用目标层的“楼层属性——上下楼点”。其次尝试像其他ID一样从目标楼层搜索,因此请确保该图块在目标楼层中存在且唯一。 +3. **朝向:**有八种写法,可以直接填写改变后的朝向(`up, down, left, right`),也可以填写转身的角度(`:left, :right, :back`)或不变。 +4. **动画时间:**指黑屏的毫秒数,可以填0或不小于100的整数,不填则使用玩家设定值。 +5. **穿透性:**见[系统开关](start)允许穿透楼梯。 值得注意的是,绑定了楼层转换事件的门、怪物、道具、箱子,其系统行为(开门、战斗、拾取、推行)将不再发生(阻激夹域等地图属性不受影响),而是被覆盖为上下楼。 + ## 普通事件(红) + 普通事件在启用后可以被勇士碰触而触发,它们都有着这样的开头: -覆盖触发器(Y/N)启用(Y/N)通行状态(Y/N?)显伤(Y/N) -1. 覆盖触发器:如前所述,门、怪物、道具、箱子都已经被绑定了系统触发器。如果您需要让地图上的个别这类图块在被勇士碰触时不发生系统行为(开门、战斗、拾取、推行),而是执行您在下面自定义的事件(比如触碰boss先进行一段对话再强制战斗),请勾选此项。(阻激夹域等地图属性不受影响) -2. 启用:如果不勾选此项,则此事件初始时是隐藏的。 +`覆盖触发器(Y/N) 启用(Y/N) 通行状态(Y/N?) 显伤(Y/N)` - 如前所述,非常不推荐仅仅为了初始隐藏一些图块(如战利品、陷阱门墙、埋伏怪等)就去绑定一堆没有指令的普通事件。更安全的做法是“从0转变图块”(支持淡入效果)和“关门”(这样还有音效,多香)。 -3. 通行状态:除怪物和道具外,所有图块本身都具有“可通行性”属性。 +1. **覆盖触发器:**如前所述,门、怪物、道具、箱子都已经被绑定了系统触发器。如果您需要让地图上的个别这类图块在被勇士碰触时不发生系统行为(开门、战斗、拾取、推行),而是执行您在下面自定义的事件(比如触碰boss先进行一段对话再强制战斗),请勾选此项。(阻激夹域等地图属性不受影响) +2. **启用:**如果不勾选此项,则此事件初始时是隐藏的。 + * 如前所述,非常不推荐仅仅为了初始隐藏一些图块(如战利品、陷阱门墙、埋伏怪等)就去绑定一堆没有指令的普通事件。 + * 更安全的做法是“从0转变图块”(支持淡入效果)和“关门”(这样还有音效,多香)。 +3. **通行状态:**除怪物和道具外,所有图块本身都具有“可通行性”属性。 + * 您可以设置此项去覆盖地图中这一点的可通行性,譬如强行让一格空地不可通行,勇士撞击时出现一堵墙(51层魔塔第23层的效果)。 +4. **显伤:**在对怪物使用覆盖触发器后,表面上看不出它和一般怪物的不同。 + * 如有必要(比如触碰这怪物根本不战斗),可不勾选显伤以示区别。 + * 如数量较多,可注册一个相同素材的NPC,比如样板中的仙子。 + * 如需在一段剧情中关闭所有显伤,可以简单移除怪物手册 - 您可以设置此项去覆盖地图中这一点的可通行性,譬如强行让一格空地不可通行,勇士撞击时出现一堵墙(51层魔塔第23层的效果)。 -4. 显伤:在对怪物使用覆盖触发器后,表面上看不出它和一般怪物的不同。 - -如有必要(比如触碰这怪物根本不战斗),可不勾选显伤以示区别。 - -如数量较多,可注册一个相同素材的NPC,比如样板中的仙子。 - -如需在一段剧情中关闭所有显伤,请调用core.removeItem(’book’) ## 自动事件(橙) + 在“右键绑定机关门”中,我们已经初见了自动事件的端倪。 在游戏中,我们经常需要监听大量乱七八糟的状态,根据状态的变化去做出及时的处理,比如勇士生命小于等于0会触发游戏失败。比如51层魔塔第39层监听9扇黄门的状态来触发中心对称飞行器的出现、第49层监听8名魔法警卫的状态来封印假魔王。 @@ -76,25 +86,31 @@ callback)函数相对应,只是多了一项“穿透性”。 而自动事件则不然,它不需要您去主动考虑所有“改变状态”的原因,而是简单地在每次刷新状态栏时,检查是否满足触发条件,满足的话就执行。 每个自动事件具有以下几个属性: -1. 触发条件:自动事件最重要的属性,为支持冒号缩写量的逻辑表达式。 - 譬如上述两个例子中,触发条件就是“某两个点没有图块而某7个点图块为黄门”和“某四个点没有图块而某四个点图块为魔法警卫”。 +1. **触发条件:**自动事件最重要的属性,为支持冒号缩写量的逻辑表达式。 + * 譬如上述两个例子中,触发条件就是“某两个点没有图块而某7个点图块为黄门”和“某四个点没有图块而某四个点图块为魔法警卫”。 + * 关于冒号缩写量,详见[只读块]值块和冒号缩写量。 +2. **优先级:**一般不需要改动。当多个自动事件的条件同时满足时,优先执行此级别较大的。 + * 此级别也相等时,允许跨层触发则优先执行楼层较矮的。 + * 同一楼层优先执行横坐标较小的,横坐标相等时优先执行纵坐标较小的,同一点处优先执行页码较小的。 +3. **仅在本层检测:**如题,一般不需要改动。除非您要制作一些全局的效果,如“勇士生命低于上限的1/3时改变背景音乐”。 +4. **事件流中延迟执行:**勾选此项后,在执行其他事件时触发此自动事件则会将其内容追加到待执行事件的末尾,否则插队到待执行事件的开头。 +5. **允许多次执行:**如果不勾选,则此事件最多只会被触发一次。即使勾选了,每次执行的过程中也会暂时禁止自己被触发。勾选后,请记得在此事件的指令中将条件变得不满足。 + +每个点初始提供了两个自动事件页,您还可以再在数据区最上面单击“添加自动事件页”。 - 关于冒号缩写量,详见[只读块]值块和冒号缩写量。 -2. 优先级:一般不需要改动。当多个自动事件的条件同时满足时,优先执行此级别较大的。此级别也相等时,允许跨层触发则优先执行楼层较矮的。同一楼层优先执行横坐标较小的,横坐标相等时优先执行纵坐标较小的,同一点处优先执行页码较小的。每个点初始提供了两个自动事件页,您还可以再在数据区最上面单击“添加自动事件页”。 -3. 仅在本层检测:如题,一般不需要改动。除非您要制作一些全局的效果,如“勇士生命低于上限的1/3时改变背景音乐”。 -4. 事件流中延迟执行:勾选此项后,在执行其他事件时触发此自动事件则会将其内容追加到待执行事件的末尾,否则插队到待执行事件的开头。 -5. 允许多次执行:如果不勾选,则此事件最多只会被触发一次。即使勾选了,每次执行的过程中也会暂时禁止自己被触发。勾选后,请记得在此事件的指令中将条件变得不满足。 ## 公共事件(逗号键) 有几个事件,如战后加点、毒衰咒处理、回收钥匙商店,会在战后脚本或全局商店等处频繁用到。于是它们被整理成了公共事件,您也可以追加自己的。 -公共事件在内容上和其他事件并无不同,只是在插入公共事件时(如core.insertCommonEvent(“回收钥匙商店”))可以提供一个“参数列表”。 +公共事件在内容上和其他事件并无不同,只是在插入公共事件时(如`core.insertCommonEvent("回收钥匙商店")`)可以提供一个`参数列表`。 -参数列表是一个一维数组,其每项会被依次代入core.status.hero.flags.arg1、arg2、……,而arg0则会记录公共事件的中文名,因此请不要在一个公共事件里又插入另一个公共事件。 +参数列表是一个一维数组,其每项会被依次代入`core.status.hero.flags.arg1、arg2、……`,而`arg0`则会记录公共事件的中文名。 在整个事件流结束后(即勇士恢复行动,请注意不是公共事件结束后),这些以arg加纯数字命名的变量、以及以@temp开头的临时变量都会被清空。 + ## 滑冰事件 + 滑冰(ski)是一个非常特殊的触发器,使用此触发器的图块需要画在背景层。 冰上可以画门、怪物、道具等任何图块,您还可以在前景层画上四种单向通行箭头(样板1层右下方那些),把三个图层的游戏性都发挥出来。 @@ -103,43 +119,39 @@ callback)函数相对应,只是多了一项“穿透性”。 比如撞到怪物会强制战斗,打不过直接游戏失败。走到道具上会捡起来,撞到门则要看有没有钥匙,有的话会把门打开。 -默认情况下,触发事件后勇士会停下来。如果要继续滑冰,可以在这些点的战后事件、开门后事件、(拾获)道具后事件(这里最好勾选“轻按时不触发”)中判断勇士还在不在冰上(core.onSki()函数),在冰上的话就命令“勇士前进一格或撞击”。 +默认情况下,触发事件后勇士会停下来。如果要继续滑冰,可以在这些点的战后事件、开门后事件、(拾获)道具后事件(这里最好勾选“轻按时不触发”)中判断勇士还在不在冰上(`core.onSki()`函数),在冰上的话就命令“勇士前进一格或撞击”。 + ## 事件编辑器 -![image](img/v2.7/blockly.png) + +![image](img/blockly.jpg) + 当您从数据区单击任何一个事件类属性的“编辑”按钮时,就会呼出事件编辑器,上图给出了事件编辑器的全貌。 左下角为指令类别,可以点击它们呼出各类指令菜单,如左上方的值块菜单。 中央为指令区,被一个标识事件类型的紫色块包覆(即左下角的“入口方块”,图中为开门后事件),所有的指令都塞在里面。 -右上角为json区,会随着指令区的编辑而自动变化。core.insertAction()函数的自变量就是它们,所以学有余力的话也建议您经常左右对照去了解每个指令对应的json写法。 +右上角为json区,会随着指令区的编辑而自动变化。`core.insertAction()`函数的自变量就是它们,所以学有余力的话也建议您经常左右对照去了解每个指令对应的json写法。 右下角为调色器,当您单击指令块中的颜色按钮时(如图中“画面闪烁”指令的白块)就会自动呼出,可以进行诸如十进制和十六进制颜色格式互转等操作。 左上角为功能区,各功能的含义和用法如下: -1. 确认(Ctrl+S):将指令区的指令组翻译为json写回表格和文件,并关闭事件编辑器。如果手动修改了json区却没有点击变黄的解析按钮,或指令区存在异步事件没有用“等待所有异步事件执行完毕”(图中第二条褐色指令)去等待,则单击确认按钮会弹窗警告。此时如果想放弃对json区的修改,请随便点一下指令区的一个块即可。 -2. 解析:将手动修改后的json区翻译回指令组同步到指令区,一般用于跨作品复制事件,或长距离批量挪动和复制指令。因为blockly使用Ctrl+V粘贴出的块总是出现在原块的旁边,而拖动块时块又跟不上滚轮`-_-`|| -3. 取消:放弃本次编辑,关闭事件编辑器,表格和文件会停留在打开事件编辑器前的状态。 -4. 搜索事件块:当您想不起来需要的指令在哪个类别时,请使用此项,如输入“勇”字就会列出所有带有“勇士”一词的指令。 -5. 地图选点:在编辑事件尤其是大篇幅事件的过程中,如果需要频繁保存并退出事件编辑器去浏览地图尤其是浏览别的楼层就很不方便。单击此按钮,您可以浏览所有楼层及其全景。通过点击地图去确认一个点的坐标,并复制任何一个楼层ID以填入需要的地方。需要填坐标的指令也可以直接双击其指令块从地图选点填入坐标和楼层,从而避免了肉眼数格子和手敲的麻烦和出错的隐患。 -6. 变量出现位置搜索:您可以搜索所有以“变量:xxx”形式出现在事件中的变量的出现位置,请注意“形式”和“事件”。以下形式都是无法被搜索到的(比如仇恨值、阻激夹域捕的禁用开关): -``` js - core.status.hero.flags.xxx - hero.flags.xxx、flags.xxx - core.getFlag('xxx') - core.hasFlag('xxx') - core.getBuff('xxx') -``` -在碰触脚本、道具使用条件和装备条件等会被eval的项,以及脚本编辑、插件编写等处直接core.insertAction()的自变量中,也是无法搜索到的。 -7. 开启中文名替换:勾选此项后,“flag、status、item、switch、temp、global、enemy”等冒号缩写量的前缀以及怪物和道具的ID才会允许用中文在指令块中书写,如“变量、状态、物品、独立开关、临时变量、全局存储、怪物”。\ - 当然,json中还是只能用英文的。此外,如果您需要使用中文名相同的道具或怪物,或在`${}`以外的文本中将上述几个词和冒号连用,则也需要关闭此功能以避免blockly和json互译出错。 -8. 展开值块逻辑运算:在值块菜单中我们可以看到第一个就是二元运算块,但是它并不完整。比如没有位运算(包括逻辑异或)和取余,因此如果解析的优先级与js的优先级不一致,请在表达式中适当的位置添加圆括弧,或取消勾选此项。 +1. **确认(Ctrl+S):**将指令区的指令组翻译为json写回表格和文件,并关闭事件编辑器。如果手动修改了json区却没有点击变黄的解析按钮,或指令区存在异步事件没有用“等待所有异步事件执行完毕”(图中第二条褐色指令)去等待,则单击确认按钮会弹窗警告。此时如果想放弃对json区的修改,请随便点一下指令区的一个块即可。 +2. **解析:**将手动修改后的json区翻译回指令组同步到指令区,一般用于跨作品复制事件,或长距离批量挪动和复制指令。因为blockly使用Ctrl+V粘贴出的块总是出现在原块的旁边,而拖动块时块又跟不上滚轮。 +3. **取消:**放弃本次编辑,关闭事件编辑器,表格和文件会停留在打开事件编辑器前的状态。 +4. **搜索事件块:**当您想不起来需要的指令在哪个类别时,请使用此项,如输入“勇”字就会列出所有带有“勇士”一词的指令。 +5. **地图选点:**在编辑事件尤其是大篇幅事件的过程中,如果需要频繁保存并退出事件编辑器去浏览地图尤其是浏览别的楼层就很不方便。单击此按钮,您可以浏览所有楼层及其全景。通过点击地图去确认一个点的坐标,并复制任何一个楼层ID以填入需要的地方。需要填坐标的指令也可以直接双击其指令块从地图选点填入坐标和楼层,从而避免了肉眼数格子和手敲的麻烦和出错的隐患。 +6. **变量出现位置搜索:**您可以搜索所有以“变量:xxx”形式出现在事件中的变量的出现位置,请注意“形式”和“事件”。以下形式都是无法被搜索到的(比如仇恨值、阻激夹域捕的禁用开关): +7. **开启中文名替换:**勾选此项后,“flag、status、item、switch、temp、global、enemy”等冒号缩写量的前缀以及怪物和道具的ID才会允许用中文在指令块中书写,如“变量、状态、物品、独立开关、临时变量、全局存储、怪物”。当然,json中还是只能用英文的。此外,如果您需要使用中文名相同的道具或怪物,或在`${}`以外的文本中将上述几个词和冒号连用,则也需要关闭此功能以避免blockly和json互译出错。 +8. **展开值块逻辑运算:**在值块菜单中我们可以看到第一个就是二元运算块,但是它并不完整。比如没有位运算(包括逻辑异或)和取余,因此如果解析的优先级与js的优先级不一致,请在表达式中适当的位置添加圆括弧,或取消勾选此项。 ## 值块和冒号缩写量 -值块并不能单独构成指令,但它们可以被嵌入数值操作、设置怪物属性和很多事件控制类指令。而冒号缩写量的用法就更多了,比如用于`${表达式计算}`和其他任何支持填表达式的地方。\ +值块并不能单独构成指令,但它们可以被嵌入数值操作、设置怪物属性和很多事件控制类指令。而冒号缩写量的用法就更多了,比如用于`${表达式计算}`和其他任何支持填表达式的地方。 + 值块大体上分为三种:勾选框与运算块、只读块、可读写块,其中后两类对应着冒号缩写量。 + ### 勾选框与运算块(附js比较运算大图鉴) 包括勾选框块(true和false两个逻辑常量)、否定运算块和二元运算块。 @@ -154,7 +166,7 @@ callback)函数相对应,只是多了一项“穿透性”。 `'2' < 10; 10 <= '10'; '10' < 2; null >= 0; null <= 0; 1/0 > 1/-0` -![image](img/v2.7/compare.png) +![image](img/compare.jpg) 弱(不)等于(==和!=)非常难用,建议放弃,统一使用(不)等于(===和!==)。 @@ -177,78 +189,40 @@ undefined倒是不用担心,它除了和null弱相等外,和其他值都没 所以样板中充斥着形如x=x||y和z=x||y的代码,y算是x的默认值。 若干个由“异或”连起来的true或false,总结果取决于其中true的个数的奇偶,奇数个true则总结果为1,偶数个true则总结果为0. -### 只读块(怪物属性、图块ID、图块类别、装备孔) {#只读块} + +### 只读块(怪物属性、图块ID、图块类别、装备孔) + 尽管这几个值块是只读的,但您仍然可以使用“设置怪物属性”、“穿脱装备”和“转变图块”等指令去改变它们。 -1. 怪物属性:冒号缩写量写作“怪物:绿头怪:生命”,json代码中写作“enemy:greenSlime:hp”。怪物中文名有重复的话请在事件编辑器顶部关闭中文替换功能,道具中文名同理。 - 常见的怪物属性都提供在了下拉框中,如果下拉框里没有(如通过配置表格新增的属性),可以修改`_server\MotaAction.g4`文件最后的那些表来追加其中文简称,也可以放弃解析回中文块而是就用缩写量。 -2. 图块ID:冒号缩写量写作“图块ID:x,y”,json代码中写作“blockId:x,y” +1. **怪物属性:**冒号缩写量写作`怪物:绿头怪:生命`,json代码中写作`enemy:greenSlime:hp`。怪物中文名有重复的话请在事件编辑器顶部关闭中文替换功能,道具中文名同理。 + * 常见的怪物属性都提供在了下拉框中,如果下拉框里没有(如通过配置表格新增的属性),可以修改`_server\MotaAction.g4`文件最后的那些表来追加其中文简称,也可以放弃解析回中文块而是就用缩写量。 +2. **图块ID:**冒号缩写量写作`图块ID:x,y`,json代码中写作`blockId:x,y`。请注意逗号始终要用英文的,此值块实际直接调用的API为`core.getBlockId(x,y)`,即本值块和对应的冒号缩写量只支持本层,可以获知本层某个点的图块ID. +3. **图块类别:**冒号缩写量写作`图块类别:x,y`,json代码中写作`blockCls:x,y`。同上,实际调用`core.getBlockCls(x,y)`,可以获知本层某个点的图块类别。 +4. **装备孔:**冒号缩写量写作`装备孔:n`,json代码中写作`equip:n`。实际调用`core.getEquip(n)`,可以获知勇士第n个装备孔中的装备ID. - 请注意逗号始终要用英文的,此值块实际直接调用的API为core.getBlockId(x,y),即本值块和对应的冒号缩写量只支持本层,可以获知本层某个点的图块ID. -3. 图块类别:冒号缩写量写作“图块类别:x,y”,json代码中写作“blockCls:x,y” - - 同上,实际调用core.getBlockCls(x,y),可以获知本层某个点的图块类别。 -4. 装备孔:冒号缩写量写作“装备孔:n”,json代码中写作“equip:n”. - - 实际调用core.getEquip(n),可以获知勇士第(n+1)个装备孔中的装备ID. ### 可读写块(status、item、flag、switch、temp、global) 比起只读块,可读写块允许作为“数值操作”指令的左块: - -1. 状态:冒号缩写量为“状态:生命”等,json代码中写作“status:hp”等。\ - 作为左块时会调用core.setStatus(),其他时候会调用core.getStatus()[^34]\ - 当前楼层的ID不属于勇士状态,请使用core.status.floorId获取(只读)。\ - core.setStatus()和core.getStatus()的第一个自变量为“x”、“y”或“direction”时会被特殊处理为core.setHeroLoc()和core.getHeroLoc(),来读写core.status.hero.loc,此外还有一些勇士状态也不支持中文替换。 - -2. 物品:冒号缩写量为“物品:炸弹”等,json代码中写作“item:bomb”等。\ - 作为左块时会调用core.getItem()或core.setItem(),其他时候会调用core.itemCount()来统计背包中的道具数量。\ - 此外,最常用的9个勇士状态和三色钥匙提供在了下拉框中。您可以修改`_server\MotaAction.g4`文件最后的`FixedId_List`来追加,向“楼层转换”、“门信息”和“装备属性”的下拉框追加新的楼梯ID、钥匙ID和勇士状态名也是一样的道理,当然不追加也不影响手写。 - -3. 变量:冒号缩写量为“变量:hatred”等,json代码中写作“flag:hatred”等。 - - 道具中文名有重复的话请在事件编辑器顶部关闭中文替换功能,怪物中文名同理。 - 作为左块时会调用core.setFlag(),其他时候会调用core.getFlag(’xxx’, 0) - 这类最多,而且冒号的右侧本身就支持中文。 - - 这两个API实际操作的就是前文多次提到的core.status.hero.flags,只不过在事件中未定义的变量都视为0,更为安全。 - - 如果您忘记了自己在哪些事件用过哪些变量,请善用事件编辑器顶部的“搜索变量出现位置”。 - -4. 独立开关:如果您有一大批NPC都具有“首次对话不同于之后各次对话”之类的特点,那么为他们设置一大批不重名的变量就很繁琐。独立开关(叫独立变量更准确)就是为这种场合而生的,它对每层楼(首次到达和每次到达中)和每个坐标都是独立的。 - - 冒号缩写量写作“独立开关:A—Z”,json代码中写作“switch:A—Z” - - 每个坐标处的独立开关有26个,用大写拉丁字母A—Z表示。MTn层(x,y)点的独立开关A,本质上是一个flag变量——`core.status.hero.flags.MTn@x@y@A`,如果需要在其他点访问,就需要用这样的写法。 - - 这里以51层魔塔的商人们为例,涉及到的指令在后面会一一讲解: - - 如果 独立开关:A - 标题:商人,图像:this,对话框效果:this,正文:xxx - 隐藏事件(同时删除):500毫秒 - 否则 - 显示确认框:我有n个yyy道具,你出zzz金币就卖给你。 - 确定的场合: - 如果 zzz > 状态:金币 - 标题:商人,图像:this,对话框效果:this,正文:你的金钱不足! - 否则 - 数值操作 状态:金币 减少 zzz - 数值操作 物品:yyy 增加 n - 数值操作 独立开关:A 设为 √ - 取消的场合; - -5. 临时变量:冒号缩写量写作“临时变量:A—Z”,json代码中写作`temp:A-Z`, - 临时变量泛指所有“以@temp”开头的flag变量,一共也有26个。 - - 临时变量一般用于计数循环和数组迭代,每当事件流结束(勇士恢复行动)时,临时变量和参数变量(以arg+纯数字命名)都会被清空。 -6. 全局存储:冒号缩写量写作“全局存储:xxx”,json代码中写作`global:xxx`, - 和变量一样,冒号右侧本身支持中文。全局存储一般用来保存一些跨存档的信息,如成就系统、回想和音像鉴赏的收集进度、多周目数据等。 - - 用于左块时会调用core.setGlobal(),其他时候会调用core.getGlobal() - - 前者在正常游戏中会一并将设置值计入录像,录像回放时则忽略。 - - 后者会从浏览器localForage中读取数据,回放时则直接从录像中读取。 +1. **状态:**冒号缩写量为`状态:生命`等,json代码中写作`status:hp`等。 + * 作为左块时会调用`core.setStatus()`,其他时候会调用`core.getStatus()` +2. **物品:**冒号缩写量为`物品:炸弹`等,json代码中写作`item:bomb`等 + * 作为左块时会调用`core.getItem()`或`core.setItem()`,其他时候会调用`core.itemCount()`来统计背包中的道具数量。 + * 此外,最常用的9个勇士状态和三色钥匙提供在了下拉框中。您可以修改`_server/MotaAction.g4`文件最后的`FixedId_List`来追加,向“楼层转换”、“门信息”和“装备属性”的下拉框追加新的楼梯ID、钥匙ID和勇士状态名也是一样的道理,当然不追加也不影响手写。 +3. **变量:**冒号缩写量为`变量:hatred`等,json代码中写作`flag:hatred`等。 + * 作为左块时会调用`core.setFlag()`,其他时候会调用`core.getFlag(’xxx’, 0)` + * 请注意:变量类型支持中文,如`变量:开门个数` + * 这两个API实际操作的就是前文多次提到的`core.status.hero.flags`,只不过在事件中未定义的变量都视为0,更为安全。 + * 如果您忘记了自己在哪些事件用过哪些变量,请善用事件编辑器顶部的“搜索变量出现位置”。 +4. **独立开关:**如果您有一大批NPC都具有“首次对话不同于之后各次对话”之类的特点,那么为他们设置一大批不重名的变量就很繁琐。独立开关(叫独立变量更准确)就是为这种场合而生的,它对每层楼(首次到达和每次到达中)和每个坐标都是独立的。 + * 冒号缩写量写作`独立开关:A—Z`,json代码中写作`switch:A—Z` + * 每个坐标处的独立开关有26个,用大写拉丁字母A—Z表示。MTn层(x,y)点的独立开关A,本质上是一个flag变量——`flag:MTn@x@y@A`,如果需要在其他点访问,就需要用这样的写法 +5. **临时变量:**冒号缩写量写作“临时变量:A—Z”,json代码中写作`temp:A-Z`, + * 临时变量泛指所有以`@temp@`开头的flag变量,一共也有26个。 + * 临时变量一般用于计数循环和数组迭代,每当事件流结束(勇士恢复行动)时,临时变量和参数变量(以arg+纯数字命名)都会被清空。 +6. **全局存储:**冒号缩写量写作`全局存储:xxx`,json代码中写作`global:xxx`, + * 和变量一样,冒号右侧本身支持中文。全局存储一般用来保存一些跨存档的信息,如成就系统、回想和音像鉴赏的收集进度、多周目数据等。 + * 用于左块时会调用`core.setGlobal()`,其他时候会调用`core.getGlobal()` ========================================================================================== -[继续阅读下一章:个性化](personalization) +[继续阅读下一章:事件指令](instruction) diff --git a/_docs/img/autoEvent.png b/_docs/img/autoEvent.png deleted file mode 100644 index 06dd923e..00000000 Binary files a/_docs/img/autoEvent.png and /dev/null differ diff --git a/_docs/img/bigKey.png b/_docs/img/bigKey.png deleted file mode 100644 index 384d53b8..00000000 Binary files a/_docs/img/bigKey.png and /dev/null differ diff --git a/_docs/img/blockly.jpg b/_docs/img/blockly.jpg new file mode 100644 index 00000000..0ff70dd8 Binary files /dev/null and b/_docs/img/blockly.jpg differ diff --git a/_docs/img/blood.png b/_docs/img/blood.png deleted file mode 100644 index 53d52171..00000000 Binary files a/_docs/img/blood.png and /dev/null differ diff --git a/_docs/img/changefloor.jpg b/_docs/img/changefloor.jpg new file mode 100644 index 00000000..6b72cc3c Binary files /dev/null and b/_docs/img/changefloor.jpg differ diff --git a/_docs/img/changefloor.png b/_docs/img/changefloor.png deleted file mode 100644 index ef7170a5..00000000 Binary files a/_docs/img/changefloor.png and /dev/null differ diff --git a/_docs/img/changefloorBlockly.png b/_docs/img/changefloorBlockly.png deleted file mode 100644 index 558bb804..00000000 Binary files a/_docs/img/changefloorBlockly.png and /dev/null differ diff --git a/_docs/img/checkblock.png b/_docs/img/checkblock.png deleted file mode 100644 index 26635177..00000000 Binary files a/_docs/img/checkblock.png and /dev/null differ diff --git a/_docs/img/chrome.png b/_docs/img/chrome.png deleted file mode 100644 index 4f0f6e48..00000000 Binary files a/_docs/img/chrome.png and /dev/null differ diff --git a/_docs/img/commonEvent.png b/_docs/img/commonEvent.png deleted file mode 100644 index d6358b89..00000000 Binary files a/_docs/img/commonEvent.png and /dev/null differ diff --git a/_docs/img/compare.jpg b/_docs/img/compare.jpg new file mode 100644 index 00000000..a34601bd Binary files /dev/null and b/_docs/img/compare.jpg differ diff --git a/_docs/img/console.jpg b/_docs/img/console.jpg index 76d59378..b70afa4c 100644 Binary files a/_docs/img/console.jpg and b/_docs/img/console.jpg differ diff --git a/_docs/img/console.png b/_docs/img/console.png deleted file mode 100644 index 68f55019..00000000 Binary files a/_docs/img/console.png and /dev/null differ diff --git a/_docs/img/console1.jpg b/_docs/img/console1.jpg index 46d1f5ba..7b198e4d 100644 Binary files a/_docs/img/console1.jpg and b/_docs/img/console1.jpg differ diff --git a/_docs/img/console2.jpg b/_docs/img/console2.jpg new file mode 100644 index 00000000..470e54ec Binary files /dev/null and b/_docs/img/console2.jpg differ diff --git a/_docs/img/control_itemsg.jpg b/_docs/img/control_itemsg.jpg new file mode 100644 index 00000000..9dff8061 Binary files /dev/null and b/_docs/img/control_itemsg.jpg differ diff --git a/_docs/img/debuff.png b/_docs/img/debuff.png deleted file mode 100644 index a087cdd1..00000000 Binary files a/_docs/img/debuff.png and /dev/null differ diff --git a/_docs/img/drawmap.jpg b/_docs/img/drawmap.jpg deleted file mode 100644 index 3f3f324c..00000000 Binary files a/_docs/img/drawmap.jpg and /dev/null differ diff --git a/_docs/img/editor.jpg b/_docs/img/editor.jpg new file mode 100644 index 00000000..d91510f1 Binary files /dev/null and b/_docs/img/editor.jpg differ diff --git a/_docs/img/elements.jpg b/_docs/img/elements.jpg index d32ebaf2..398389f7 100644 Binary files a/_docs/img/elements.jpg and b/_docs/img/elements.jpg differ diff --git a/_docs/img/enemy.png b/_docs/img/enemy.png deleted file mode 100644 index cc64f9b8..00000000 Binary files a/_docs/img/enemy.png and /dev/null differ diff --git a/_docs/img/enemyarray.png b/_docs/img/enemyarray.png deleted file mode 100644 index d8022c57..00000000 Binary files a/_docs/img/enemyarray.png and /dev/null differ diff --git a/_docs/img/eventdebug.png b/_docs/img/eventdebug.png deleted file mode 100644 index 0bf2ebe3..00000000 Binary files a/_docs/img/eventdebug.png and /dev/null differ diff --git a/_docs/img/events/1.jpg b/_docs/img/events/1.jpg deleted file mode 100644 index 6cc44ab5..00000000 Binary files a/_docs/img/events/1.jpg and /dev/null differ diff --git a/_docs/img/events/10.jpg b/_docs/img/events/10.jpg deleted file mode 100644 index 9e7166a6..00000000 Binary files a/_docs/img/events/10.jpg and /dev/null differ diff --git a/_docs/img/events/11.jpg b/_docs/img/events/11.jpg deleted file mode 100644 index c6f3aa1b..00000000 Binary files a/_docs/img/events/11.jpg and /dev/null differ diff --git a/_docs/img/events/12.jpg b/_docs/img/events/12.jpg deleted file mode 100644 index 12551990..00000000 Binary files a/_docs/img/events/12.jpg and /dev/null differ diff --git a/_docs/img/events/13.jpg b/_docs/img/events/13.jpg deleted file mode 100644 index 075b0814..00000000 Binary files a/_docs/img/events/13.jpg and /dev/null differ diff --git a/_docs/img/events/14.jpg b/_docs/img/events/14.jpg deleted file mode 100644 index 53221968..00000000 Binary files a/_docs/img/events/14.jpg and /dev/null differ diff --git a/_docs/img/events/15.jpg b/_docs/img/events/15.jpg deleted file mode 100644 index 14aa4cd2..00000000 Binary files a/_docs/img/events/15.jpg and /dev/null differ diff --git a/_docs/img/events/15.png b/_docs/img/events/15.png deleted file mode 100644 index b1fe91cc..00000000 Binary files a/_docs/img/events/15.png and /dev/null differ diff --git a/_docs/img/events/16.jpg b/_docs/img/events/16.jpg deleted file mode 100644 index 4e77816f..00000000 Binary files a/_docs/img/events/16.jpg and /dev/null differ diff --git a/_docs/img/events/17.jpg b/_docs/img/events/17.jpg deleted file mode 100644 index a8e94528..00000000 Binary files a/_docs/img/events/17.jpg and /dev/null differ diff --git a/_docs/img/events/18.jpg b/_docs/img/events/18.jpg deleted file mode 100644 index 8cbe6f94..00000000 Binary files a/_docs/img/events/18.jpg and /dev/null differ diff --git a/_docs/img/events/19.jpg b/_docs/img/events/19.jpg deleted file mode 100644 index e250b7bd..00000000 Binary files a/_docs/img/events/19.jpg and /dev/null differ diff --git a/_docs/img/events/2.jpg b/_docs/img/events/2.jpg deleted file mode 100644 index e2461d34..00000000 Binary files a/_docs/img/events/2.jpg and /dev/null differ diff --git a/_docs/img/events/20.jpg b/_docs/img/events/20.jpg deleted file mode 100644 index 3c616d9e..00000000 Binary files a/_docs/img/events/20.jpg and /dev/null differ diff --git a/_docs/img/events/21.jpg b/_docs/img/events/21.jpg deleted file mode 100644 index 6cccb422..00000000 Binary files a/_docs/img/events/21.jpg and /dev/null differ diff --git a/_docs/img/events/22.jpg b/_docs/img/events/22.jpg deleted file mode 100644 index e814be0c..00000000 Binary files a/_docs/img/events/22.jpg and /dev/null differ diff --git a/_docs/img/events/23.jpg b/_docs/img/events/23.jpg deleted file mode 100644 index 5cad5714..00000000 Binary files a/_docs/img/events/23.jpg and /dev/null differ diff --git a/_docs/img/events/24.jpg b/_docs/img/events/24.jpg deleted file mode 100644 index 2852e509..00000000 Binary files a/_docs/img/events/24.jpg and /dev/null differ diff --git a/_docs/img/events/25.jpg b/_docs/img/events/25.jpg deleted file mode 100644 index d5492386..00000000 Binary files a/_docs/img/events/25.jpg and /dev/null differ diff --git a/_docs/img/events/26.jpg b/_docs/img/events/26.jpg deleted file mode 100644 index f2b11f44..00000000 Binary files a/_docs/img/events/26.jpg and /dev/null differ diff --git a/_docs/img/events/27.jpg b/_docs/img/events/27.jpg deleted file mode 100644 index 021b48e6..00000000 Binary files a/_docs/img/events/27.jpg and /dev/null differ diff --git a/_docs/img/events/28.jpg b/_docs/img/events/28.jpg deleted file mode 100644 index 5f6c6a19..00000000 Binary files a/_docs/img/events/28.jpg and /dev/null differ diff --git a/_docs/img/events/29.jpg b/_docs/img/events/29.jpg deleted file mode 100644 index a04439c1..00000000 Binary files a/_docs/img/events/29.jpg and /dev/null differ diff --git a/_docs/img/events/3.jpg b/_docs/img/events/3.jpg deleted file mode 100644 index f4c6ddde..00000000 Binary files a/_docs/img/events/3.jpg and /dev/null differ diff --git a/_docs/img/events/30.jpg b/_docs/img/events/30.jpg deleted file mode 100644 index c1e9aca2..00000000 Binary files a/_docs/img/events/30.jpg and /dev/null differ diff --git a/_docs/img/events/31.jpg b/_docs/img/events/31.jpg deleted file mode 100644 index 663f3a30..00000000 Binary files a/_docs/img/events/31.jpg and /dev/null differ diff --git a/_docs/img/events/32.jpg b/_docs/img/events/32.jpg deleted file mode 100644 index 9a0fddfa..00000000 Binary files a/_docs/img/events/32.jpg and /dev/null differ diff --git a/_docs/img/events/33.jpg b/_docs/img/events/33.jpg deleted file mode 100644 index 10246b96..00000000 Binary files a/_docs/img/events/33.jpg and /dev/null differ diff --git a/_docs/img/events/34.jpg b/_docs/img/events/34.jpg deleted file mode 100644 index 222ad18b..00000000 Binary files a/_docs/img/events/34.jpg and /dev/null differ diff --git a/_docs/img/events/35.jpg b/_docs/img/events/35.jpg deleted file mode 100644 index ff8ef556..00000000 Binary files a/_docs/img/events/35.jpg and /dev/null differ diff --git a/_docs/img/events/36.jpg b/_docs/img/events/36.jpg deleted file mode 100644 index 40a951fa..00000000 Binary files a/_docs/img/events/36.jpg and /dev/null differ diff --git a/_docs/img/events/37.jpg b/_docs/img/events/37.jpg deleted file mode 100644 index 5267ed13..00000000 Binary files a/_docs/img/events/37.jpg and /dev/null differ diff --git a/_docs/img/events/38.jpg b/_docs/img/events/38.jpg deleted file mode 100644 index b6ccf550..00000000 Binary files a/_docs/img/events/38.jpg and /dev/null differ diff --git a/_docs/img/events/39.jpg b/_docs/img/events/39.jpg deleted file mode 100644 index d30c8d79..00000000 Binary files a/_docs/img/events/39.jpg and /dev/null differ diff --git a/_docs/img/events/4.jpg b/_docs/img/events/4.jpg deleted file mode 100644 index d447565f..00000000 Binary files a/_docs/img/events/4.jpg and /dev/null differ diff --git a/_docs/img/events/40.jpg b/_docs/img/events/40.jpg deleted file mode 100644 index e10f56b7..00000000 Binary files a/_docs/img/events/40.jpg and /dev/null differ diff --git a/_docs/img/events/41.jpg b/_docs/img/events/41.jpg deleted file mode 100644 index ec9b7e49..00000000 Binary files a/_docs/img/events/41.jpg and /dev/null differ diff --git a/_docs/img/events/42.jpg b/_docs/img/events/42.jpg deleted file mode 100644 index 24d0c2f4..00000000 Binary files a/_docs/img/events/42.jpg and /dev/null differ diff --git a/_docs/img/events/43.jpg b/_docs/img/events/43.jpg deleted file mode 100644 index cb8f1c31..00000000 Binary files a/_docs/img/events/43.jpg and /dev/null differ diff --git a/_docs/img/events/44.jpg b/_docs/img/events/44.jpg deleted file mode 100644 index 59b3ecb7..00000000 Binary files a/_docs/img/events/44.jpg and /dev/null differ diff --git a/_docs/img/events/45.jpg b/_docs/img/events/45.jpg deleted file mode 100644 index 44dec550..00000000 Binary files a/_docs/img/events/45.jpg and /dev/null differ diff --git a/_docs/img/events/46.jpg b/_docs/img/events/46.jpg deleted file mode 100644 index 0fff3f91..00000000 Binary files a/_docs/img/events/46.jpg and /dev/null differ diff --git a/_docs/img/events/47.jpg b/_docs/img/events/47.jpg deleted file mode 100644 index dd7bb88e..00000000 Binary files a/_docs/img/events/47.jpg and /dev/null differ diff --git a/_docs/img/events/48.jpg b/_docs/img/events/48.jpg deleted file mode 100644 index 4a0d31a8..00000000 Binary files a/_docs/img/events/48.jpg and /dev/null differ diff --git a/_docs/img/events/49.jpg b/_docs/img/events/49.jpg deleted file mode 100644 index f81e0451..00000000 Binary files a/_docs/img/events/49.jpg and /dev/null differ diff --git a/_docs/img/events/5.jpg b/_docs/img/events/5.jpg deleted file mode 100644 index 333c972c..00000000 Binary files a/_docs/img/events/5.jpg and /dev/null differ diff --git a/_docs/img/events/50.jpg b/_docs/img/events/50.jpg deleted file mode 100644 index 568eabf0..00000000 Binary files a/_docs/img/events/50.jpg and /dev/null differ diff --git a/_docs/img/events/51.jpg b/_docs/img/events/51.jpg deleted file mode 100644 index 1a3f70c3..00000000 Binary files a/_docs/img/events/51.jpg and /dev/null differ diff --git a/_docs/img/events/52.jpg b/_docs/img/events/52.jpg deleted file mode 100644 index b66d2a22..00000000 Binary files a/_docs/img/events/52.jpg and /dev/null differ diff --git a/_docs/img/events/52.png b/_docs/img/events/52.png deleted file mode 100644 index 3c0c13c8..00000000 Binary files a/_docs/img/events/52.png and /dev/null differ diff --git a/_docs/img/events/53.jpg b/_docs/img/events/53.jpg deleted file mode 100644 index c3e488bb..00000000 Binary files a/_docs/img/events/53.jpg and /dev/null differ diff --git a/_docs/img/events/54.jpg b/_docs/img/events/54.jpg deleted file mode 100644 index 6dbfc95e..00000000 Binary files a/_docs/img/events/54.jpg and /dev/null differ diff --git a/_docs/img/events/55.jpg b/_docs/img/events/55.jpg deleted file mode 100644 index fff606c2..00000000 Binary files a/_docs/img/events/55.jpg and /dev/null differ diff --git a/_docs/img/events/56.jpg b/_docs/img/events/56.jpg deleted file mode 100644 index 15fac681..00000000 Binary files a/_docs/img/events/56.jpg and /dev/null differ diff --git a/_docs/img/events/57.jpg b/_docs/img/events/57.jpg deleted file mode 100644 index 60196800..00000000 Binary files a/_docs/img/events/57.jpg and /dev/null differ diff --git a/_docs/img/events/58.jpg b/_docs/img/events/58.jpg deleted file mode 100644 index e9ff8af9..00000000 Binary files a/_docs/img/events/58.jpg and /dev/null differ diff --git a/_docs/img/events/59.jpg b/_docs/img/events/59.jpg deleted file mode 100644 index 48c58e01..00000000 Binary files a/_docs/img/events/59.jpg and /dev/null differ diff --git a/_docs/img/events/6.jpg b/_docs/img/events/6.jpg deleted file mode 100644 index 7be2810b..00000000 Binary files a/_docs/img/events/6.jpg and /dev/null differ diff --git a/_docs/img/events/60.jpg b/_docs/img/events/60.jpg deleted file mode 100644 index 408cebb3..00000000 Binary files a/_docs/img/events/60.jpg and /dev/null differ diff --git a/_docs/img/events/7.jpg b/_docs/img/events/7.jpg deleted file mode 100644 index 546a8bab..00000000 Binary files a/_docs/img/events/7.jpg and /dev/null differ diff --git a/_docs/img/events/7.png b/_docs/img/events/7.png deleted file mode 100644 index 80b15c87..00000000 Binary files a/_docs/img/events/7.png and /dev/null differ diff --git a/_docs/img/events/8.jpg b/_docs/img/events/8.jpg deleted file mode 100644 index 1c78a313..00000000 Binary files a/_docs/img/events/8.jpg and /dev/null differ diff --git a/_docs/img/events/9.jpg b/_docs/img/events/9.jpg deleted file mode 100644 index bb6d752d..00000000 Binary files a/_docs/img/events/9.jpg and /dev/null differ diff --git a/_docs/img/eventsx.jpg b/_docs/img/eventsx.jpg new file mode 100644 index 00000000..0527c32b Binary files /dev/null and b/_docs/img/eventsx.jpg differ diff --git a/_docs/img/firstdatab.jpg b/_docs/img/firstdatab.jpg new file mode 100644 index 00000000..632a741c Binary files /dev/null and b/_docs/img/firstdatab.jpg differ diff --git a/_docs/img/flag.png b/_docs/img/flag.png deleted file mode 100644 index b042ca8e..00000000 Binary files a/_docs/img/flag.png and /dev/null differ diff --git a/_docs/img/floor.png b/_docs/img/floor.png deleted file mode 100644 index 7b606550..00000000 Binary files a/_docs/img/floor.png and /dev/null differ diff --git a/_docs/img/floordata.png b/_docs/img/floordata.png deleted file mode 100644 index ed28b628..00000000 Binary files a/_docs/img/floordata.png and /dev/null differ diff --git a/_docs/img/floorid.png b/_docs/img/floorid.png deleted file mode 100644 index 63efa3d3..00000000 Binary files a/_docs/img/floorid.png and /dev/null differ diff --git a/_docs/img/floorset.png b/_docs/img/floorset.png deleted file mode 100644 index 67ea6f67..00000000 Binary files a/_docs/img/floorset.png and /dev/null differ diff --git a/_docs/img/floorsv.jpg b/_docs/img/floorsv.jpg new file mode 100644 index 00000000..5eef9466 Binary files /dev/null and b/_docs/img/floorsv.jpg differ diff --git a/_docs/img/flowctrl.jpg b/_docs/img/flowctrl.jpg new file mode 100644 index 00000000..a2987041 Binary files /dev/null and b/_docs/img/flowctrl.jpg differ diff --git a/_docs/img/forEach.png b/_docs/img/forEach.png deleted file mode 100644 index 0b9ed39d..00000000 Binary files a/_docs/img/forEach.png and /dev/null differ diff --git a/_docs/img/getspecialtext.png b/_docs/img/getspecialtext.png deleted file mode 100644 index 4dd167b0..00000000 Binary files a/_docs/img/getspecialtext.png and /dev/null differ diff --git a/_docs/img/images_texty.jpg b/_docs/img/images_texty.jpg new file mode 100644 index 00000000..670402ad Binary files /dev/null and b/_docs/img/images_texty.jpg differ diff --git a/_docs/img/imginfo.png b/_docs/img/imginfo.png deleted file mode 100644 index a05321b9..00000000 Binary files a/_docs/img/imginfo.png and /dev/null differ diff --git a/_docs/img/init.png b/_docs/img/init.png deleted file mode 100644 index 15e01205..00000000 Binary files a/_docs/img/init.png and /dev/null differ diff --git a/_docs/img/keyboard.png b/_docs/img/keyboard.png deleted file mode 100644 index 0a89fc52..00000000 Binary files a/_docs/img/keyboard.png and /dev/null differ diff --git a/_docs/img/logo.png b/_docs/img/logo.png deleted file mode 100644 index 389b77c8..00000000 Binary files a/_docs/img/logo.png and /dev/null differ diff --git a/_docs/img/map1.png b/_docs/img/map1.png deleted file mode 100644 index 1f06abb5..00000000 Binary files a/_docs/img/map1.png and /dev/null differ diff --git a/_docs/img/maparray.png b/_docs/img/maparray.png deleted file mode 100644 index 3c6cefef..00000000 Binary files a/_docs/img/maparray.png and /dev/null differ diff --git a/_docs/img/mapgui.png b/_docs/img/mapgui.png deleted file mode 100644 index d66c73ef..00000000 Binary files a/_docs/img/mapgui.png and /dev/null differ diff --git a/_docs/img/mapmean.png b/_docs/img/mapmean.png deleted file mode 100644 index b8213091..00000000 Binary files a/_docs/img/mapmean.png and /dev/null differ diff --git a/_docs/img/maps_waits_raw.jpg b/_docs/img/maps_waits_raw.jpg new file mode 100644 index 00000000..9288c0b4 Binary files /dev/null and b/_docs/img/maps_waits_raw.jpg differ diff --git a/_docs/img/mapsc.jpg b/_docs/img/mapsc.jpg new file mode 100644 index 00000000..362dc3cb Binary files /dev/null and b/_docs/img/mapsc.jpg differ diff --git a/_docs/img/moddata.png b/_docs/img/moddata.png deleted file mode 100644 index dfa7b3bb..00000000 Binary files a/_docs/img/moddata.png and /dev/null differ diff --git a/_docs/img/nattack.png b/_docs/img/nattack.png deleted file mode 100644 index 011b0c55..00000000 Binary files a/_docs/img/nattack.png and /dev/null differ diff --git a/_docs/img/plugin.jpg b/_docs/img/plugin.jpg index d0d69bef..fabc1e70 100644 Binary files a/_docs/img/plugin.jpg and b/_docs/img/plugin.jpg differ diff --git a/_docs/img/plugin.png b/_docs/img/plugin.png deleted file mode 100644 index 5c65cd4d..00000000 Binary files a/_docs/img/plugin.png and /dev/null differ diff --git a/_docs/img/point.png b/_docs/img/point.png deleted file mode 100644 index b218411f..00000000 Binary files a/_docs/img/point.png and /dev/null differ diff --git a/_docs/img/ps.png b/_docs/img/ps.png deleted file mode 100644 index 9e28c864..00000000 Binary files a/_docs/img/ps.png and /dev/null differ diff --git a/_docs/img/quickshops.jpg b/_docs/img/quickshops.jpg new file mode 100644 index 00000000..e6996a68 Binary files /dev/null and b/_docs/img/quickshops.jpg differ diff --git a/_docs/img/register.png b/_docs/img/register.png deleted file mode 100644 index 88ade048..00000000 Binary files a/_docs/img/register.png and /dev/null differ diff --git a/_docs/img/rmxp1.png b/_docs/img/rmxp1.png deleted file mode 100644 index 7dfee78f..00000000 Binary files a/_docs/img/rmxp1.png and /dev/null differ diff --git a/_docs/img/rmxp2.png b/_docs/img/rmxp2.png deleted file mode 100644 index af62c402..00000000 Binary files a/_docs/img/rmxp2.png and /dev/null differ diff --git a/_docs/img/rmxp3.png b/_docs/img/rmxp3.png deleted file mode 100644 index 137d6a9b..00000000 Binary files a/_docs/img/rmxp3.png and /dev/null differ diff --git a/_docs/img/rmxp4.jpg b/_docs/img/rmxp4.jpg deleted file mode 100644 index 081ab580..00000000 Binary files a/_docs/img/rmxp4.jpg and /dev/null differ diff --git a/_docs/img/sample0.png b/_docs/img/sample0.png deleted file mode 100644 index 6598e611..00000000 Binary files a/_docs/img/sample0.png and /dev/null differ diff --git a/_docs/img/save.png b/_docs/img/save.png deleted file mode 100644 index b17b584a..00000000 Binary files a/_docs/img/save.png and /dev/null differ diff --git a/_docs/img/script.png b/_docs/img/script.png deleted file mode 100644 index 981b1964..00000000 Binary files a/_docs/img/script.png and /dev/null differ diff --git a/_docs/img/server.jpg b/_docs/img/server.jpg new file mode 100644 index 00000000..fd48fc65 Binary files /dev/null and b/_docs/img/server.jpg differ diff --git a/_docs/img/server.png b/_docs/img/server.png deleted file mode 100644 index 74488f31..00000000 Binary files a/_docs/img/server.png and /dev/null differ diff --git a/_docs/img/sources.jpg b/_docs/img/sources.jpg index 7fce53b3..607b35d9 100644 Binary files a/_docs/img/sources.jpg and b/_docs/img/sources.jpg differ diff --git a/_docs/img/tuihua.png b/_docs/img/tuihua.png deleted file mode 100644 index de7d1836..00000000 Binary files a/_docs/img/tuihua.png and /dev/null differ diff --git a/_docs/img/uievent.jpg b/_docs/img/uievent.jpg new file mode 100644 index 00000000..52598bae Binary files /dev/null and b/_docs/img/uievent.jpg differ diff --git a/_docs/img/v2.7/blockly.png b/_docs/img/v2.7/blockly.png deleted file mode 100644 index 8d5b576c..00000000 Binary files a/_docs/img/v2.7/blockly.png and /dev/null differ diff --git a/_docs/img/v2.7/changeFloor.png b/_docs/img/v2.7/changeFloor.png deleted file mode 100644 index 74a94df2..00000000 Binary files a/_docs/img/v2.7/changeFloor.png and /dev/null differ diff --git a/_docs/img/v2.7/compare.png b/_docs/img/v2.7/compare.png deleted file mode 100644 index ed4c7f43..00000000 Binary files a/_docs/img/v2.7/compare.png and /dev/null differ diff --git a/_docs/img/v2.7/console.png b/_docs/img/v2.7/console.png deleted file mode 100644 index 1ffddc15..00000000 Binary files a/_docs/img/v2.7/console.png and /dev/null differ diff --git a/_docs/img/v2.7/control&itemsG.png b/_docs/img/v2.7/control&itemsG.png deleted file mode 100644 index 75fbdfc8..00000000 Binary files a/_docs/img/v2.7/control&itemsG.png and /dev/null differ diff --git a/_docs/img/v2.7/drawTip.png b/_docs/img/v2.7/drawTip.png deleted file mode 100644 index 22572d53..00000000 Binary files a/_docs/img/v2.7/drawTip.png and /dev/null differ diff --git a/_docs/img/v2.7/editor.png b/_docs/img/v2.7/editor.png deleted file mode 100644 index 875a8e5a..00000000 Binary files a/_docs/img/v2.7/editor.png and /dev/null differ diff --git a/_docs/img/v2.7/eventsX.png b/_docs/img/v2.7/eventsX.png deleted file mode 100644 index 130ff919..00000000 Binary files a/_docs/img/v2.7/eventsX.png and /dev/null differ diff --git a/_docs/img/v2.7/firstDataB.png b/_docs/img/v2.7/firstDataB.png deleted file mode 100644 index 9737fea5..00000000 Binary files a/_docs/img/v2.7/firstDataB.png and /dev/null differ diff --git a/_docs/img/v2.7/floorsV.png b/_docs/img/v2.7/floorsV.png deleted file mode 100644 index e710503a..00000000 Binary files a/_docs/img/v2.7/floorsV.png and /dev/null differ diff --git a/_docs/img/v2.7/flowCtrl.png b/_docs/img/v2.7/flowCtrl.png deleted file mode 100644 index 73e25371..00000000 Binary files a/_docs/img/v2.7/flowCtrl.png and /dev/null differ diff --git a/_docs/img/v2.7/images&textY.png b/_docs/img/v2.7/images&textY.png deleted file mode 100644 index c83e89bf..00000000 Binary files a/_docs/img/v2.7/images&textY.png and /dev/null differ diff --git a/_docs/img/v2.7/keyboard.png b/_docs/img/v2.7/keyboard.png deleted file mode 100644 index 0a89fc52..00000000 Binary files a/_docs/img/v2.7/keyboard.png and /dev/null differ diff --git a/_docs/img/v2.7/maps&waits&raw.png b/_docs/img/v2.7/maps&waits&raw.png deleted file mode 100644 index 8f145f04..00000000 Binary files a/_docs/img/v2.7/maps&waits&raw.png and /dev/null differ diff --git a/_docs/img/v2.7/mapsC.png b/_docs/img/v2.7/mapsC.png deleted file mode 100644 index ba500429..00000000 Binary files a/_docs/img/v2.7/mapsC.png and /dev/null differ diff --git a/_docs/img/v2.7/parabola.png b/_docs/img/v2.7/parabola.png deleted file mode 100644 index 88e09b58..00000000 Binary files a/_docs/img/v2.7/parabola.png and /dev/null differ diff --git a/_docs/img/v2.7/quickShops.png b/_docs/img/v2.7/quickShops.png deleted file mode 100644 index 18ff1902..00000000 Binary files a/_docs/img/v2.7/quickShops.png and /dev/null differ diff --git a/_docs/img/v2.7/server.png b/_docs/img/v2.7/server.png deleted file mode 100644 index 096a823a..00000000 Binary files a/_docs/img/v2.7/server.png and /dev/null differ diff --git a/_docs/img/v2.7/uievent.png b/_docs/img/v2.7/uievent.png deleted file mode 100644 index 54e36276..00000000 Binary files a/_docs/img/v2.7/uievent.png and /dev/null differ diff --git a/_docs/img/v2.7/values&flagsB.png b/_docs/img/v2.7/values&flagsB.png deleted file mode 100644 index a60003a5..00000000 Binary files a/_docs/img/v2.7/values&flagsB.png and /dev/null differ diff --git a/_docs/img/values_flagsb.jpg b/_docs/img/values_flagsb.jpg new file mode 100644 index 00000000..cfb911fa Binary files /dev/null and b/_docs/img/values_flagsb.jpg differ diff --git a/_docs/img/zone.png b/_docs/img/zone.png deleted file mode 100644 index e5577a9f..00000000 Binary files a/_docs/img/zone.png and /dev/null differ diff --git a/_docs/index.html b/_docs/index.html index c721b4b3..1c9733fd 100644 --- a/_docs/index.html +++ b/_docs/index.html @@ -3,7 +3,7 @@ HTML5魔塔样板 - + diff --git a/_docs/index.md b/_docs/index.md index 198994d5..9899d8ec 100644 --- a/_docs/index.md +++ b/_docs/index.md @@ -1,5 +1,5 @@ # HTML5 魔塔样板说明文档 -?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} * + 当您打开这份帮助文档的瞬间,相信您一定是抱着幼年时的游戏开发梦想前来的。众所周知,即时游戏的开发要比非即时游戏难上许多,像素级游戏的开发又要比网格地图游戏难上许多。 在非即时网格地图游戏(譬如策略战棋)中,有一类叫做“固定数值RPG”,简称“魔塔”。这是一种基于运筹学的数学优化建模游戏,虽然小众,却不失有自己的圈子。 diff --git a/_docs/instruction.md b/_docs/instruction.md index 7047a078..f047db5d 100644 --- a/_docs/instruction.md +++ b/_docs/instruction.md @@ -1,23 +1,27 @@ # 事件指令 -?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} * + +?> 在这一节中,让我们来了解每一类事件的具体介绍 本样板之所以敢宣称“零编程基础的您也能大展身手”,就是因为它搭载了强大的图形化json编辑器(blockly)。 -熟悉Antlr语法的读者可以根据@zhaouv的另一篇文档去自行修改`_server\MotaAction.g4`等文件去扩展其功能。 +熟悉Antlr语法的读者可以根据[修改编辑器](editor)去自行修改`_server\MotaAction.g4`等文件去扩展其功能。 -json代码本身则可以作为core.insertAction()函数的自变量,去执行临时事件。 +json代码本身则可以作为`core.insertAction()`函数的自变量,去插入一段事件执行。 ## 指令的分类(注意区分块的颜色和地图的七彩点) -尽管本章的标题暗示了事件指令和`core.events._action_xxx()`函数是一一对应的,但它们进一步调用的底层函数却分布在libs文件夹的不同文件中。 +尽管本章的标题暗示了事件指令和`core.events._action_xxx()`函数是一一对应的,但它们进一步调用的底层函数却分布在libs文件夹的不同文件中,大致上: -大致上,显示文字类(严格来说需要玩家操作的事件还涉及到actions.js)和UI绘制类在ui.js,数据相关类(这类也有不少道具相关在items.js)和特效声音类在control.js,地图处理类在maps.js,事件控制类(或许应该叫流程控制类)则在events.js,请注意区分libs和project的同名文件。 +* 显示文字类(严格来说需要玩家操作的事件还涉及到actions.js)和UI绘制类在ui.js +* 数据相关类(这类也有不少道具相关在items.js)和特效声音类在control.js +* 地图处理类在maps.js +* 事件控制类(或许应该叫流程控制类)则在events.js,请注意区分libs和project的同名文件。 另一种分类方法则是按照同步和异步,分成以下几类: -1. 瞬间就能执行完的:如UI绘制、设置XX属性、显隐和转变图层块等。 -2. 阻塞直到玩家操作的:如显示文章/选择项/确认框、接受用户输入、等待用户操作、呼出xxx等。 -3. 阻塞一段固定时间的:如开关门、显示动画、移动跳跃、淡入淡出等。 -4. 耗时但不阻塞的:如播放音效、显示提示等,会和后面的指令同时执行。 +1. **瞬间就能执行完的:**如UI绘制、设置XX属性、显隐和转变图层块等。 +2. **阻塞直到玩家操作的:**如显示文章/选择项/确认框、接受用户输入、等待用户操作、呼出xxx等。 +3. **阻塞一段固定时间的:**如开关门、显示动画、移动跳跃、淡入淡出等。 +4. **耗时但不阻塞的:**如播放音效、显示提示等,会和后面的指令同时执行。 上述第3类指令都可以勾选“不等待执行完毕”(即前面提到的异步事件)变为第4类,从而实现诸如同步开关多个门的效果。 @@ -26,232 +30,156 @@ json代码本身则可以作为core.insertAction()函数的自变量,去执行 data为整个指令对象,x和y为当前点坐标,prefix为独立开关的楼层前缀。 -您可以自行在libs\events.js中追加这样的函数,这样就可以自定义新指令啦。 - -如果需要把新指令做成像已有的指令一样有类别、名称、取色器、勾选框、下拉框、输入框等部件,请查阅@zhaouv撰写的另一篇文档。 - -![image](img/v2.7/images&textY.png) +您可以自行在使用`core.registerEvent`注册一个新的事件。如果需要把新指令做成像已有的指令一样有类别、名称、取色器、勾选框、下拉框、输入框等部件,请查阅[修改编辑器](editor)。 ## 显示文字类(黄色) + +![image](img/images_textY.jpg) + 这个类别的指令会负责UI层图文的处理,如图片的移动和淡入淡出,游戏的胜败和重启等。 + ### 显示文章 + 最基本的就是最灵活的。本指令的讲解将占用大量篇幅,请做好准备。 上述函数中,第一个自变量为字符串数组或单个字符串,每个字符串为一段需要玩家按下确认键或点击屏幕才会消失的剧情文本,第二个自变量(可选)为全部文本消失后的回调函数。 每条显示文章分为五部分:标题、图像、对话框效果、正文、立绘。 -写成一个字符串就是“\t[标题,图像]\b[对话框效果]\f[立绘]正文”。 -1. 标题:可选,一般填说话人的名字。如果不填,则尝试根据图像取中文名(道具除外,如图像填hero但不填标题则以勇士名字作为标题)。还可以填null强制不显示标题。 -2. 图像:可选,可以填hero(勇士行走图,如果勇士开了帧动画则会取当前朝向,但朝上会视为朝下)或任何图块ID,或者填this来尝试取当前点图块。也可以填一个png格式的图片文件名(需要后缀),甚至还可以填null来避免以图块ID为标题被解释成图像。 -3. 对话框效果:可选,填法非常灵活,如下。 - 1. up,x,y:对话框显示在点(x,y)上方,尖角朝下指着这个点(绝对坐标,具体指的高度取决于图像。没有图像则判断该点是32×32px还是32×48px的图块,该点没有图块则没有尖角)。 - 2. down,x,y:对话框显示在点(x,y)下方,尖角朝上指着这个点。比起上面,这个没有高度问题,不过该点没有图块的话则还是没有尖角。 +写成一个字符串就是`\t[标题,图像]\b[对话框效果]\f[立绘]正文`。 - 上述两种写法中,如果把坐标换成hero则显示在勇士上方或下方。 - - 上方时如果没有图像则勇士高度视为32×32px. - 3. this,x,y:在大地图中,点(x,y)可能位于视野上半部分也可能位于下半部分,写this就能让对话框自动适配上下来防止越界。 - 4. hero:在大地图上下边缘或小地图,勇士可能在上半或下半场,只写hero也能自动适配。 - 5. hero,n:n为正整数,显示给勇士的第n名跟随者,自动适配上下。 - 6. up,null:显示在屏幕最上方,同理up换成down则为最下方。 - 7. center:强制显示在屏幕中央,宽度为视野宽度。 - 除最后两种外,其余写法都会给对话框进行宽度自适配: - - 如果正文没有自动换行,则会先尝试取一个让文本总行数最接近“几行半”的宽度,可能会再适当加宽来防止标题出界。 - - 如果正文有自动换行,则会尝试连同标题在内取最长的一行作为宽度。 - - 最终绘制时会尽量让尖角居中,除非尖角所指的点实在太靠左或太靠右。 - - 值得注意的是,使用project\images\winskin.png或类似的图片作为文章背景时,尖角的绘制用的是用图片右下角64×32的两格进行的,所以往往需要您自己准备好。 -4. 正文:双击指令块,进入多行编辑。正文中允许使用很多转义序列,当您键入一个\字符时就会提示补全,后面逐一介绍。 -5. 立绘:显示文章的同时可以绘制一张或多张立绘图,请双击预览各张图的效果。每张立绘由一大堆参数组成: - -\f[name(:x/:y/:o,sx,sy,sw,sh,)x,y(,w,h,alpha,angle)] -1. 文件名:需要放在project\images文件夹中并注册,这里需要带后缀。 -2. 翻转:和楼层贴图一样,支持三种翻转,在json代码中以文件的后缀名之后追加“:x、:y、:o”来表示。 -3. 绘制坐标:立绘在视野中的左上角像素坐标,后面的参数一旦省略其中一个则必须省略其后所有。 -4. 绘制的宽高:立绘被伸缩后在视野中实际显示的宽高,必须同时填写,不填则不伸缩。 -5. 裁剪坐标和宽高:必须同时填写,为从原图中裁剪区域的左上角坐标和区域宽高,不填则取全图。 -6. 不透明度和旋转角度:可选,前者填一个不大于1的正数,请自行双击预览。 +1. **标题:**可选,一般填说话人的名字。如果不填,则尝试根据图像取中文名(道具除外,如图像填hero但不填标题则以勇士名字作为标题)。还可以填null强制不显示标题。 +2. **图像:**可选,可以填hero(勇士行走图,如果勇士开了帧动画则会取当前朝向,但朝上会视为朝下)或任何图块ID,或者填this来尝试取当前点图块。 + * 也可以填一个png格式的图片文件名(需要后缀),甚至还可以填null来避免以图块ID为标题被解释成图像。 +3. **对话框效果:**可选,填法非常灵活,如下。 + 1. `up,x,y`:对话框显示在点(x,y)上方,尖角朝下指着这个点(绝对坐标,具体指的高度取决于图像。没有图像则判断该点是32×32px还是32×48px的图块,该点没有图块则没有尖角)。 + 2. `down,x,y`:对话框显示在点(x,y)下方,尖角朝上指着这个点。比起上面,这个没有高度问题,不过该点没有图块的话则还是没有尖角。 + * 上述两种写法中,如果把坐标换成hero则显示在勇士上方或下方。 + 3. `this,x,y`:在大地图中,点(x,y)可能位于视野上半部分也可能位于下半部分,写this就能让对话框自动适配上下来防止越界。 + 4. `hero`:在大地图上下边缘或小地图,勇士可能在上半或下半场,只写hero也能自动适配。 + 5. `hero,n`:n为正整数,显示给勇士的第n名跟随者,自动适配上下。 + 6. `up,null`:显示在屏幕最上方,同理up换成down则为最下方。 + 7. `center`:强制显示在屏幕中央,宽度为视野宽度。 + 8. 除最后两种外,其余写法都会给对话框进行宽度自适配: + * 如果正文没有自动换行,则会先尝试取一个让文本总行数最接近“几行半”的宽度,可能会再适当加宽来防止标题出界。 + * 如果正文有自动换行,则会尝试连同标题在内取最长的一行作为宽度。 + 9. 最终绘制时会尽量让尖角居中,除非尖角所指的点实在太靠左或太靠右。 + 10. 值得注意的是,使用`project/images/inskin.png`或类似的图片作为文章背景时,尖角的绘制用的是用图片右下角64×32的两格进行的,所以往往需要您自己准备好。 +4. **正文:**双击指令块,进入多行编辑。正文中允许使用很多转义序列,当您键入一个\字符时就会提示补全,后面逐一介绍。 +5. **立绘:**显示文章的同时可以绘制一张或多张立绘图,请双击预览各张图的效果。每张立绘由一大堆参数组成:`\f[name(:x/:y/:o,sx,sy,sw,sh,)x,y(,w,h,alpha,angle)]` + 1. **文件名:**需要放在project\images文件夹中并注册,这里需要带后缀。 + 2. **翻转:**和楼层贴图一样,支持三种翻转,在json代码中以文件的后缀名之后追加“:x、:y、:o”来表示。 + 3. **绘制坐标:**立绘在视野中的左上角像素坐标,后面的参数一旦省略其中一个则必须省略其后所有。 + 4. **绘制的宽高:**立绘被伸缩后在视野中实际显示的宽高,必须同时填写,不填则不伸缩。 + 5. **裁剪坐标和宽高:**必须同时填写,为从原图中裁剪区域的左上角坐标和区域宽高,不填则取全图。 + 6. **不透明度和旋转角度:**可选,前者填一个不大于1的正数,请自行双击预览。 立绘是画在UI层的,下一个指令执行前就会擦除。如需持续显示请使用“显示图片”指令,另外立绘会被“图像”遮挡。 + ### 显示文章正文的转义序列 -除变色和换行外,使用其余转义序列(`\\c, \\d, \\e, \\i, \\z`)时请注意: -1. 表达式计算:使用`${}`可以计算一个js表达式,式子中允许使用所有的冒号缩写量和API,详见core.calValue()函数。此语法也可以用于“道具描述”和“即捡即用提示”,只不过那里就不支持中文替换了。 - 如“勇士当前的攻防相乘是\${状态:攻击\*状态:防御}”(中文替换), - - “持有三色钥匙共\${item:yellowKey+item:blueKey+item:redKey}把。”(json) -2. 局部文字变色:使用\r[颜色英文名]或\r[\#RrGgBb](十六进制)来将这之后的文本变为另一种颜色。 - - 最常用的17种颜色提供了自动补全,十六进制颜色可以随便找个有颜色参数的指令,呼出调色器去自己调配。只使用\r不带方括号则变回默认颜色。 -3. 局部字号调节:使用`\\c[正整数]`改变这之后文本的字号,只使用`\\c`不加方括号则恢复默认字号。 -4. 手动换行、局部加粗和斜体:退出多行编辑后,手动换行写作\n,另外可以使用`\\d`将局部文本加粗或取消加粗,使用`\\e`将局部文本变为斜体或取消斜体。 -5. 32×32px图标的绘制:使用`\\i[图标ID]`绘制一个32×32px的图块的第一帧或系统图标,您可以使用core.statusBar.icons查看所有的系统图标。 -6. 打字速度调节:开启打字机效果后,文本的打字速度总是匀速的。 - - 所以样板提供了名为“时间占位符”的转义序列,使用`\\z[正整数]`可以暂停相当于打这么多个字的时间。 +1. **表达式计算:**使用`${}`可以计算一个js表达式,式子中允许使用所有的冒号缩写量和API,详见core.calValue()函数。 + * 此语法也可以用于“道具描述”和“即捡即用提示”,只不过那里就不支持中文替换了。 + * 如`勇士当前的攻防相乘是\${状态:攻击\*状态:防御}`(中文替换),`持有三色钥匙共\${item:yellowKey+item:blueKey+item:redKey}把。`(json) +2. **局部文字变色:**使用`\r[颜色英文名]`或`\r[\#RrGgBb]`(十六进制)来将这之后的文本变为另一种颜色。 + * 最常用的17种颜色提供了自动补全,十六进制颜色可以随便找个有颜色参数的指令,呼出调色器去自己调配。只使用\r不带方括号则变回默认颜色。 +3. **局部字号调节:**使用`\\c[正整数]`改变这之后文本的字号,只使用`\\c`不加方括号则恢复默认字号。 +4. **手动换行、局部加粗和斜体:**退出多行编辑后,手动换行写作`\n`,另外可以使用`\\d`将局部文本加粗或取消加粗,使用`\\e`将局部文本变为斜体或取消斜体。 +5. **32×32px图标的绘制:**使用`\\i[图标ID]`绘制一个32×32px的图块的第一帧或系统图标,您可以使用`core.statusBar.icons`查看所有的系统图标。 +6. **打字速度调节:**开启打字机效果后,文本的打字速度总是匀速的。所以样板提供了名为“时间占位符”的转义序列,使用`\\z[正整数]`可以暂停相当于打这么多个字的时间。 ### 其他文字类指令 -1. 自动剧情文本:和上面的显示文章基本相同,只不过不是由玩家按下确认键或点击屏幕,而是一定毫秒后自动消失,录像回放中则忽略。 - - 比起那个,这个不能通过长按Ctrl键或长按屏幕快进,大量使用时一般用来搭配语音。否则对魔塔这种快餐游戏来说可能会非常不友好,建议统一塞进“显示确认框”指令的场合之一。 -2. 滚动剧情文本:将一段文字从屏幕最下方滚动到最上方,不支持自动换行,常用于op和ed. -3. 显示提示:即诸如打败怪物、捡到道具、打不开门时左上角的提示,只支持`${表达式计算}`。 - - 可以填写一个图标ID显示在提示文本的左侧(支持32×48px但只画靠上的2/3,也可以使用系统图标)。 - - 此指令对应core.drawTip(text, icon, frame)函数,这里text就不支持`${}`表达式计算了。自然数frame表示绘制第几帧,默认为0表示第一帧。 - - 帧参数在事件中默认没有提供,图中那个是小秋橙自己加的。加的方法也非常简单,在@zhaouv撰写的另一篇文档中有讲解。只不过那篇文档中的两个例子更为复杂,所以小秋橙决定在这里亲自讲一下这个例子。 - - 首先,事件编辑器和事件执行的原理是: - 1. 点击数据区表格的“编辑”按钮,如果这一项是json类型就会跳转到事件编辑器,并根据初始的json内容解析出初始的blockly指令块。 - - 这一步由`_server\MotaActionParser.js`完成,每次修改完json区点击变黄的“解析”按钮时也是如此。 - - 2. 拖拽拼接并填写blockly指令块,实时同步到json区。 - - 这一步由`_server\MotaAction.g4`完成,刚打开事件编辑器时初始解析出的指令块也会立即再同步到json区,所以可能和表格中看到的不一样。 - - 3. 最后,事件的执行就和blockly没有任何关系了。所有`{"type": "xxx"}`的事件都是由`libs\events.js的core.events._action_xxx(data, x, y, prefix)`函数执行的,其中data就是json指令对象。 - - ![image](img/v2.7/drawTip.png) - 搞清楚这个以后,就可以开始动手修改了。首先打开上面所说的events.js,搜索`_action_tip`,鼠标悬停在其中的drawTip一词上,就能查看这个API的参数注解。可以看到有第三个参数frame没有使用,于是补上一项data.frame(蓝色选中区)。 - - 接下来要去修改`_server\MotaAction.g4`,搜索“显示提示”。可以看到指令块的参数有很多类型,比如EvalString(支持`${}`表达式计算的文本)、IdString(填写图块ID)、Bool(勾选框)、expression(值块)等,而我们需要的是类型是Int(整数)。 - - 于是补写在指令文本中,同时还要修改下面的default(默认模板)和最后的json拼接式子。 - - 这个式子比较难改,要注意双引号的匹配和冒号、逗号的位置。 - - 在这个例子中需要追加蓝色选中区以及两个红框中的内容。 - - 最后要去修改`_server\MotaActionParser.js`,搜索“`case "tip":`”,简单地追加蓝色选中区的内容。 -4. 游戏胜败和重启:游戏胜败分别对应“脚本编辑”(快捷键N)的win和lose函数,在线游戏排行榜中每个结局的每个难度都有一张榜。 - - 但同一结局只有最高难度有效,您可以勾选“不计入榜单”来让这个本来有效的结局也无效。还可以勾选“不结束游戏”来先停止录制,再演出ed. - - 重启游戏对应的函数为core.showStartAnimate() -5. 设置剧情文本的属性: - -可用core.status.textAttribute获取当前的剧情文本属性(只读)。各项含义: -1. 位置:“显示文章”不使用\b对话框效果时文本的位置,默认为屏幕中央。如果您有大量集中的剧情文本都欲使用“up,null”的对话框效果,则可以直接将此项设置为“顶部”,而将剩余的个别剧情文本使用“center”或“down,null”的对话框效果,反之亦然。 -2. 偏移像素:上面的“位置”选择“顶部”或“底部”时和屏幕上下边缘的距离,也作为滚动剧情文本和左边缘的距离。 -3. 对齐:默认为左对齐,可以修改此项来让显示文章的标题和正文都居中或都右对齐。 -4. 标题色:准确地说是“标题和图像边框色”,格式和楼层画面色调一致,可以点击调色器按钮呼出调色器调色。 -5. 正文色:如题,修改方法同上,从而避免频繁使用\r进行局部文本变色。 -6. 背景色:如题,修改方法同上。但比起前两个,这个也允许填写一个类似winskin.png的图片文件名。 -7. 标题和正文字号:如题,正文字号推荐设置为偶数。 -8. 行距和字符间距:如题,单位都是像素,行距推荐为正文字号的一倍半。 -9. 粗体(Y/N):文本是否默认加粗,推荐在大量粗体文本中穿插少量细体文本时使用,以免频繁的`\\d`切换。 -10. 打字间隔:0表示不启用打字机效果而是一次显示完,正整数表示每打一个字的毫秒数,也作为`\\z`暂停的单位时间。 +1. **自动剧情文本:**和上面的显示文章基本相同,只不过不是由玩家按下确认键或点击屏幕,而是一定毫秒后自动消失,录像回放中则忽略。 + * 比起那个,这个不能通过长按Ctrl键或长按屏幕快进,大量使用时一般用来搭配语音。否则对魔塔这种快餐游戏来说可能会非常不友好,建议统一塞进“显示确认框”指令的场合之一。 +2. **滚动剧情文本:**将一段文字从屏幕最下方滚动到最上方,不支持自动换行,常用于op和ed. +3. **显示提示:**即诸如打败怪物、捡到道具、打不开门时左上角的提示,只支持`${表达式计算}`。 + * 可以填写一个图标ID显示在提示文本的左侧(支持32×48px但只画靠上的2/3,也可以使用系统图标)。 + * 此指令对应`core.drawTip(text, icon, frame)`函数。自然数`frame`表示绘制第几帧,默认为0表示第一帧。 +4. **游戏胜败和重启:**游戏胜败分别对应“脚本编辑”(快捷键N)的`win`和`lose`函数,在线游戏排行榜中每个结局的每个难度都有一张榜。 + * 但同一结局只有最高难度有效,您可以勾选“不计入榜单”来让这个本来有效的结局也无效。还可以勾选“不结束游戏”来先停止录制,再演出ed. + * 重启游戏对应的函数为`core.showStartAnimate()` +5. **设置剧情文本的属性:**可用`core.status.textAttribute`获取当前的剧情文本属性(只读)。各项含义: + 1. **位置:**“显示文章”不使用`\b`对话框效果时文本的位置,默认为屏幕中央。如果您有大量集中的剧情文本都欲使用`up,null`的对话框效果,则可以直接将此项设置为“顶部”,而将剩余的个别剧情文本使用`center`或`down,null`的对话框效果,反之亦然。 + 2. **偏移像素:**上面的“位置”选择“顶部”或“底部”时和屏幕上下边缘的距离,也作为滚动剧情文本和左边缘的距离。 + 3. **对齐:**默认为左对齐,可以修改此项来让显示文章的标题和正文都居中或都右对齐。 + 4. **标题色:**准确地说是“标题和图像边框色”,格式和楼层画面色调一致,可以点击调色器按钮呼出调色器调色。 + 5. **正文色:**如题,修改方法同上,从而避免频繁使用\r进行局部文本变色。 + 6. **背景色:**如题,修改方法同上。但比起前两个,这个也允许填写一个类似`winskin.png`的图片文件名。 + 7. **标题和正文字号:**如题,正文字号推荐设置为偶数。 + 8. **行距和字符间距:**如题,单位都是像素,行距推荐为正文字号的一倍半。 + 9. **粗体(Y/N):**文本是否默认加粗,推荐在大量粗体文本中穿插少量细体文本时使用,以免频繁的`\\d`切换。 + 10. **打字间隔:**0表示不启用打字机效果而是一次显示完,正整数表示每打一个字的毫秒数,也作为`\\z`暂停的单位时间。 ### 图片类指令 -1. 显示图片:和立绘的语法基本类似,只不过多了编号(1—50)和淡入时间。 +1. **显示图片:**和立绘的语法基本类似,只不过多了编号(1—50)和淡入时间。 + * 可以双击预览效果,还可以勾选“不等待执行完毕”来和后面的指令同时执行,比如同时淡入两张图片,或者淡入一张同时淡出/移动另一张。 + * 编号较大的图片会遮盖较小的,1—24号图片会被色调层遮盖,25—40号图片会遮盖UI层,41—50号图片会遮盖UI层。 + * 此指令对应`core.showImage()`函数,编号真正的意义,详见[个性化](personalization) +2. **清除图片:**如题,需要指定要清除的图片编号和淡出时间。 + * 此指令对应`core.hideImage(code, time, callback)` +3. **图片移动:**其实还包括了透明度渐变,“终点像素位置”指移动结束后的图片在视野中的左上角像素坐标(不填则表示单纯的透明度渐变),“不透明度”指渐变结束后的新的不透明度(不填表示单纯的移动),移动和透明度渐变都是匀速直线进行的。对应`core.moveImage(code, to, opacityVal, time, callback)` +4. **显示或清除动图:**需要填写动图的文件名(带.gif后缀),“起点像素位置”含义如前且必须填写,可以双击指令块来预览第一帧的效果。 + * 动图不支持淡入淡出和伸缩移动,如果不填任何参数则清除所有动图。 + * 该指令对应`core.showGif(name, x, y)`函数。 +5. **显示图片化文本:**这是您唯一显示镜像文字或旋转180°文字的机会。 + * 显示出来后就会视为一张通常的图片,可以被清除和移动。 + * 该指令对应`core.drawScrollText(content, time, lineHeight, callback)` - 可以双击预览效果,还可以勾选“不等待执行完毕”来和后面的指令同时执行,比如同时淡入两张图片,或者淡入一张同时淡出/移动另一张。 - - 编号较大的图片会遮盖较小的,1—24号图片会被色调层遮盖,25—40号图片会遮盖UI层,41—50号图片会遮盖UI层。 - - 此指令对应core.showImage()函数,编号真正的意义,详见“个性化” -2. 清除图片:如题,需要指定要清除的图片编号和淡出时间。 - - 此指令对应core.hideImage(code, time, callback) -3. 图片移动:其实还包括了透明度渐变,“终点像素位置”指移动结束后的图片在视野中的左上角像素坐标(不填则表示单纯的透明度渐变),“不透明度”指渐变结束后的新的不透明度(不填表示单纯的移动),移动和透明度渐变都是匀速直线进行的。对应`core.moveImage(code, to, opacityVal, time, callback)` -4. 显示或清除动图:需要填写动图的文件名(带.gif后缀),“起点像素位置”含义如前且必须填写,可以双击指令块来预览第一帧的效果。 - - 动图不支持淡入淡出和伸缩移动,如果不填任何参数则清除所有动图。 - - 该指令对应core.showGif(name, x, y)函数。 -5. 显示图片化文本:这是您唯一显示镜像文字或旋转180°文字的机会。 - - 显示出来后就会视为一张通常的图片,可以被清除和移动。 - - 该指令对应core.drawScrollText(content, time, lineHeight, callback) - -### QTE与全局商店 +### 显示确认框,选择项,QTE与全局商店 QTE,即快速反应事件。一般表现为需要玩家在收到某信号后尽快做出正确操作,如新新魔塔2中面对白银史莱姆王的猜拳战斗就需要根据其出拳的颜色尽快按下相克的数字键。 样板同样支持这类事件,一共有三种,这里先介绍两种。 -一是“显示确认框”,它会显示一段支持`${表达式求值}`但不支持自动换行和其他转义序列的文字。然后要求玩家在一定毫秒数内选择“确定”或“取消”之一,如果超时就视为哪个都没选,直接继续执行后面的事件。\ +一是**显示确认框**,它会显示一段支持`${表达式求值}`但不支持自动换行和其他转义序列的文字。然后要求玩家在一定毫秒数内选择“确定”或“取消”之一,如果超时就视为哪个都没选,直接继续执行后面的事件。 + 您可以指定闪烁光标的初始停留位置是确定还是取消,还可以指定超时毫秒数为0表示不限时间但玩家必须做出二选一。 -此指令对应core.drawConfirmBox(text, yesCallback, noCallback)函数,其中两个Callback分别为选择确定和取消后的回调函数。 +此指令对应`core.drawConfirmBox(text, yesCallback, noCallback)`函数,其中两个Callback分别为选择确定和取消后的回调函数。 -二是“显示选择项”,和RPG Maker不同,我们的选择项不会和它之前的“显示文章”同时出现,可以直接配上除对话框和打字机外的所有文字效果。 +二是**显示选择项**,和RPG Maker不同,我们的选择项不会和它之前的“显示文章”同时出现,可以直接配上除对话框和打字机外的所有文字效果。 -此指令对应core.drawChoices(content, choices)函数,其中content为提示文字,choices为各子选项文字组成的字符串数组。是的,比起上面的函数,这个不直接支持回调。 +此指令对应`core.drawChoices(content, choices)`函数,其中content为提示文字,choices为各子选项文字组成的字符串数组。是的,比起上面的函数,这个不直接支持回调。 -在没有提示文字的情况下,一次能同时显示的子选项最多为13或15个。 +在没有提示文字的情况下,一次能同时显示的子选项最多为13或15个。和确认框一样,选择项的超时值填0表示不限时间但玩家必须从中选择一个。大于0的话超时视为什么都没选,直接继续执行后面的事件。 -和确认框一样,选择项的超时值填0表示不限时间但玩家必须从中选择一个。 - -大于0的话超时视为什么都没选,直接继续执行后面的事件。 - -每个子选项的文字只支持`${表达式求值}`和整行变色,请注意控制字数。 - -文字左侧也支持追加一个图标(多帧图块取第一帧),支持系统图标。 +每个子选项的文字只支持`${表达式求值}`和整行变色,请注意控制字数。文字左侧也支持追加一个图标(多帧图块取第一帧),支持系统图标。 每个子选项还可以指定“出现条件”(不指定则一定出现),条件的写法和自动事件的触发条件一样,从而做出形如“怒气值满才显示大招选项”的效果。 -如果实际执行时所有子选项都不满足出现条件,则直接跳过。 - -当然,如果非要做出“显示但选了没反应”的禁用项也不是不可以, - -只不过往往需要套在一个死循环里并让其他子选项负责跳出这个循环。 +如果实际执行时所有子选项都不满足出现条件,则直接跳过。当然,如果非要做出“显示但选了没反应”的禁用项也不是不可以,只不过往往需要套在一个死循环里并让其他子选项负责跳出这个循环。 为了方便地做出这种效果,样板提供了“全局商店”。 -![image](img/v2.7/quickShops.png) +![image](img/quickShops.jpg) + 在“全塔属性——全局商店”中可以编辑各个商店,商店一共有三种: -1. 公共事件商店:最简单的一种商店,或者应该叫做给玩家准备的快捷功能更合适,因为它的内容完全不一定非得是个做买卖做交易的“商店”,也可以是诸如“开启或关闭主动技能”、“快速换上最强套装”之类的便捷功能。 +1. **公共事件商店:**最简单的一种商店,或者应该叫做给玩家准备的快捷功能更合适,因为它的内容完全不一定非得是个做买卖做交易的“商店”,也可以是诸如“开启或关闭主动技能”、“快速换上最强套装”之类的便捷功能。 + * 多说一句,鉴于全局商店列表最多只能同时显示12或14项(还有一项是关闭列表),因此您也可以准备一些永久道具,设置适当的使用条件,并在使用效果事件中去实现这些给玩家的快捷功能。当然全局商店的使用条件更加统一,请自行权衡。 + * 公共事件商店在用法上和一般的“插入公共事件”并无二致,同样可以提供一个参数列表。 +2. **道具商店:**这种商店也很简单,由第三种QTE指令实现但没有限时。 + * 您可以在其中随意填写买卖的道具ID、存量、买卖价和出现条件。 + * 存量不填视为无限,买入价不填视为只能卖(回收),卖出价不填视为只能买,出现条件的含义和选择项一致。 + * 如果需要在游戏中对买卖价和对存量进行读写,请读写`core.status.shops` + * 请注意,使用道具商店的话务必保留`project/images/winskin.png`及其注册信息,可以换成相同规格的同名图片。 +3. **新版商店:**用法非常灵活的一种商店,其外形酷似“显示选择项”但有一些不同。 + * 首先和其他两种商店一样,它多出了“商店id、快捷名称、未开启不显示”。 + * 商店id只能使用全英数,且必须两两不同。 + * “快捷名称”为显示在V键快捷菜单的名称,请注意控制字数,最好也两两不同以免玩家混淆。 + * 勾选“未开启不显示”则此商店在开启前或禁用后不会出现在V键菜单中,当商店总个数超过12或14个且随着游戏流程进度依次开新的关旧的时,这个勾选项就很有必要了。 + * 其次,和其他两种商店不同,您可以允许玩家预览它(前提是V键菜单中显示了),这对魔塔这种倡导完全信息的游戏来说非常有意义。 + * 最后,比起常规的“显示选择项”,它不能指定超时毫秒数,每个子选项除“出现条件”外还多出一个“使用条件”。 + * 实际执行中在所有子选项的最后会自动追加一个“离开”选项,选择其他子选项并执行后商店并不会立即关闭而是停在那个界面。就像胖老鼠和两部新新魔塔一样,只不过不支持长按连续购买。 + * “出现条件”和“使用条件”相搭配,让您能够很轻松地做出形如“消耗金币和各种材料的装备合成路线”这样的设定。 + * 在预览模式下除“离开”外的子选项、以及交易模式下不满足“使用条件”的子选项,都会显示为灰色。 + * 子选项的执行内容中需要手动处理扣费等问题,此外,在制作像两部新新魔塔一样会涨价的商店时,您也需要自己准备变量(变量名不必与商店id相同)去记录已购次数或者直接记录价格,并手动处理涨价问题。 - 多说一句,鉴于全局商店列表最多只能同时显示12或14项(还有一项是关闭列表),因此您也可以准备一些永久道具,设置适当的使用条件,并在使用效果事件中去实现这些给玩家的快捷功能。当然全局商店的使用条件更加统一,请自行权衡。 +有关全局商店的详细实现,请参见“插件编写”(句号键,`project/plugin.js`)。 - 公共事件商店在用法上和一般的“插入公共事件”并无二致,同样可以提供一个参数列表。 - -2. 道具商店:这种商店也很简单,由第三种QTE指令实现但没有限时。 - - 您可以在其中随意填写买卖的道具ID、存量、买卖价和出现条件。 - - 存量不填视为无限,买入价不填视为只能卖(回收),卖出价不填视为只能买,出现条件的含义和选择项一致。 - - 如果需要在游戏中对买卖价和对存量进行读写,请读写core.status.shops - - 请注意,使用道具商店的话务必保留project\images\winskin.png及其注册信息,可以换成相同规格的同名图片。 -3. 新版商店:用法非常灵活的一种商店,其外形酷似“显示选择项”但有一些不同。 - - 首先和其他两种商店一样,它多出了“商店id、快捷名称、未开启不显示”。 - - 商店id只能使用全英数,且必须两两不同。 - - “快捷名称”为显示在V键快捷菜单的名称,请注意控制字数,最好也两两不同以免玩家混淆。 - - 勾选“未开启不显示”则此商店在开启前或禁用后不会出现在V键菜单中,当商店总个数超过12或14个且随着游戏流程进度依次开新的关旧的时,这个勾选项就很有必要了。 - -其次,和其他两种商店不同,您可以允许玩家预览它(前提是V键菜单中显示了),这对魔塔这种倡导完全信息的游戏来说非常有意义。 - -最后,比起常规的“显示选择项”,它不能指定超时毫秒数,每个子选项除“出现条件”外还多出一个“使用条件”。 - -实际执行中在所有子选项的最后会自动追加一个“离开”选项,选择其他子选项并执行后商店并不会立即关闭而是停在那个界面。就像胖老鼠和两部新新魔塔一样,只不过不支持长按连续购买。 - -“出现条件”和“使用条件”相搭配,让您能够很轻松地做出形如“消耗金币和各种材料的装备合成路线”这样的设定。 - -在预览模式下除“离开”外的子选项、以及交易模式下不满足“使用条件”的子选项,都会显示为灰色。 - -子选项的执行内容中需要手动处理扣费等问题,此外,在制作像两部新新魔塔一样会涨价的商店时,您也需要自己准备变量(变量名不必与商店id相同)去记录已购次数或者直接记录价格,并手动处理涨价问题。 - -有关全局商店的详细实现,请参见“插件编写”(句号键,project\plugin.js)。 - -其中还提供了一个core.canUseQuickShop(id)函数来控制勇士什么时候可以通过V键菜单快捷使用哪些商店,自变量id为商店id. +其中还提供了一个`core.canUseQuickShop(id)`函数来控制勇士什么时候可以通过V键菜单快捷使用哪些商店,自变量id为商店id. 本质上,新版商店是套在一个死循环里的。您可以在子选项的执行内容中使用“跳出当前循环”指令来打断该子选项剩余的未执行内容而强制离开商店, @@ -260,608 +188,347 @@ QTE,即快速反应事件。一般表现为需要玩家在收到某信号后 同理,公共事件(包括公共事件商店)和自动事件本质上是“一次性”的条件为false的后置条件循环,因此使用这两个指令都能跳出它们。 ## 数据相关类(绿色) -![image](img/v2.7/control&itemsG.png) + +![image](img/control_itemsG.jpg) 这类的指令会设置各种数据(如怪物属性、楼层属性、全塔属性、六大可读写块),处理弹窗输入和开关全局商店,以及控制玩家最最关心的勇士的各种行为。 ### 设置各种数据的指令 -1. 数值操作:最简单的就是最灵活的,本指令能够修改六大可读写块(状态、物品、变量、独立开关、临时变量、全局存储)的值。 +1. **数值操作:**最简单的就是最灵活的,本指令能够修改六大可读写块(状态、物品、变量、独立开关、临时变量、全局存储)的值。 + * 修改的运算符有八种,“设为”会将右块的值代入左块,“增加、减少、乘以、除以”则是对左块的值进行增减和扩大缩小,除法如想只保留整数商(向零靠近)则改用“除以并取商”,如想要余数(例如想取勇士生命值的后两位)则使用“除以并取余”,“乘方”指的是将若干个(不一定是正整数)左块连乘起来的积代入左块。 + * 指令的右块为一表达式,可以使用任何值块和运算块,甚至直接使用API. + * 如果需要连续使用本指令,建议除最后一个外都勾选“不刷新状态栏”,以降低刷新状态栏的性能损耗,并且避免意外触发自动事件、生命和魔力溢出甚至死亡(生命小于等于0)。 +2. **设置怪物属性:**可以设置怪物的任何一项属性并计入存档。 + * 怪物ID在blockly块中也可以填中文(要求没有重复,有的话请在事件编辑器顶部关闭“中文替换”功能),需要设置的属性项在下拉框中选取。通过配置表格自行新增的属性下拉框里没有,但可以写在json区再单击变黄的“解析”按钮,或修改`_server\MotaAction.g4`文件最后的部分去追加。 + * 本指令对应`core.setEnemy(id, name, value)`函数,完全等价。 + * 最后的“值”和“数值操作”的右块写法一致(只支持写变化后的结果值,下同),注意设置怪物名字、映射名等字符串类型需要加引号。 +3. **设置楼层属性:**除了贴图和两个到达事件,其他属性都可以方便地修改。 + * 楼层ID不填则视为当前楼层,可以去“地图选点”浏览各楼层并复制ID. + * 注意修改“楼层中文名”、“状态栏中名称”、“默认地面ID”、“背景音乐”(需要后缀名)这些字符串类型都需要加引号,几个“能否/是否”只支持修改为true或false,三个坐标和天气、色调这些数组类型都需要加方括弧。本指令对应`core.events.setFloorInfo(name, value, floorId, prefix)` +4. **设置全局属性:**即全塔属性中的“主样式”(无需再加引号)和装备孔列表。 + * 修改装备孔列表时请注意,如果装备的道具属性中填写的装备类型是自然数,则可以【在列表结尾】随着游戏流程的推进解锁新的装备孔或移除装备孔(请先将身上的此类装备脱下)。 + * 而如果装备的道具属性中填写的装备类型是装备孔名称,则可以随着游戏流程的推进修改装备孔的类型组成,如本来是两把剑一块盾改成一把剑两块盾(同样需要注意已经穿上的装备问题)。 + * 本指令对应`core.events.setGlobalAttribute(name, value)`函数。 +5. **设置全局数值:**如题,可以修改四种宝石和三种血瓶的基础值等。 + * 如需使用脚本,请直接修改`core.values`,完全等价。 +6. **设置系统开关:**如题,可以用来随着游戏流程的推进解锁/移除状态栏的显示项或改动其他开关。 + * 比如中途开关生命上限、加点和负伤,中途显隐魔力、技能、绿钥匙和破炸飞毒衰咒。 + * 在游戏胜利时会将生命值作为分数上传到在线游戏排行榜,因此请在胜利前关闭生命上限再修改生命,比如根据钥匙等道具的持有情况进行加分。 + * 请注意,即使您在游戏中途才将楼传变为平面塔模式,访问过的楼层依然已经记录了最后离开的位置。 + * 如果想制作万能铁门钥匙,可以在适当的时候修改“铁门是否需要钥匙”。 + * 本指令对应`core.setGlobalFlag(name, value)`函数,实际会修改`core.flags`(但请不要脚本直接修改它) - 修改的运算符有八种,“设为”会将右块的值代入左块, - - “增加、减少、乘以、除以”则是对左块的值进行增减和扩大缩小, - - 除法如想只保留整数商(向零靠近)则改用“除以并取商”, - - 如想要余数(例如想取勇士生命值的后两位)则使用“除以并取余”, - - “乘方”指的是将若干个(不一定是正整数)左块连乘起来的积代入左块。 - - 如将黄钥匙数量变为其立方(3),则4把黄钥匙会变成64把(4×4×4)。 - - 指令的右块为一表达式,可以使用任何值块和运算块,甚至直接使用API. - - 如果需要连续使用本指令,建议除最后一个外都勾选“不刷新状态栏”, - - 以免意外触发自动事件、生命和魔力溢出甚至死亡(生命小于等于0)。 - -2. 设置怪物属性:可以设置怪物的任何一项属性并计入存档。 - - 怪物ID在blockly块中也可以填中文(要求没有重复,有的话请在事件编辑器顶部关闭“中文替换”功能),需要设置的属性项在下拉框中选取。通过配置表格自行新增的属性下拉框里没有,但可以写在json区再单击变黄的“解析”按钮,或修改`_server\MotaAction.g4`文件最后的部分去追加。 - - 本指令对应core.setEnemy(id, name, value)函数,完全等价。 - - 最后的“值”和“数值操作”的右块写法一致(只支持写变化后的结果值,下同),注意设置怪物名字、映射名等字符串类型需要加引号。 - -3. 设置楼层属性:除了贴图和两个到达事件,其他属性都可以方便地修改。 - - 楼层ID不填则视为当前楼层,可以去“地图选点”浏览各楼层并复制ID. - - 注意修改“楼层中文名”、“状态栏中名称”、“默认地面ID”、“背景音乐”(需要后缀名)这些字符串类型都需要加引号,几个“能否/是否”只支持修改为true或false,三个坐标和天气、色调这些数组类型都需要加方括弧。本指令对应`core.events.setFloorInfo(name, value, floorId, prefix)` - -4. 设置全局属性:即全塔属性中的“主样式”(无需再加引号)和装备孔列表。 - - 修改装备孔列表时请注意,如果装备的道具属性中填写的装备类型是自然数,则可以【在列表结尾】随着游戏流程的推进解锁新的装备孔或移除装备孔(请先将身上的此类装备脱下)。 - - 而如果装备的道具属性中填写的装备类型是装备孔名称,则可以随着游戏流程的推进修改装备孔的类型组成,如本来是两把剑一块盾改成一把剑两块盾(同样需要注意已经穿上的装备问题)。 - - 总的来说,进行这种修改后,快速换装功能(Ctrl/Alt+大键盘数字键)可能会出问题,请注意提醒玩家。 - - 本指令对应core.events.setGlobalAttribute(name, value)函数。 - -5. 设置全局数值:如题,可以修改四种宝石和三种血瓶的基础值等。 - - 如需使用脚本,请直接修改core.values,完全等价。 - -6. 设置系统开关:如题,可以用来随着游戏流程的推进解锁/移除状态栏的显示项或改动其他开关。 - - 比如中途开关生命上限、加点和负伤,中途显隐魔力、技能、绿钥匙和破炸飞毒衰咒。 - - 在游戏胜利时会将生命值作为分数上传到在线游戏排行榜,因此请在胜利前关闭生命上限再修改生命,比如根据钥匙等道具的持有情况进行加分。 - - 请注意,即使您在游戏中途才将楼传变为平面塔模式,访问过的楼层依然已经记录了最后离开的位置。 - - 如果想制作万能铁门钥匙,可以在适当的时候修改“铁门是否需要钥匙”。 - - 本指令对应core.setGlobalFlag(name, value)函数,实际会修改core.flags - -### 导致勇士位置(core.status.hero.loc)变化的指令 +### 导致勇士位置变化的指令 这类指令都支持填写负坐标、超出地图宽高的坐标或小数坐标, 当勇士在这些异常坐标时【除第一个指令外】都可以正常执行。 可以用于一些特殊演出,但请记得在事件结束(玩家恢复行动)前改回正常。 -1. 勇士前进一格或撞击:如题,会让勇士像自由行动时一样尝试前进一格。 - 如果可以前进但前方不可被踏入(如门、怪物、箱子、NPC)则会撞击并触发事件,走到道具、踩灯或路障或用普通事件制作的陷阱等也会触发。 - - 本指令可以正常触发跑毒和阻激夹域捕,滑冰事件就是在冰上执行了它。 - - 本指令对应core.moveAction(callback)函数,请勿直接调用它。 -2. 无视地形移动勇士:“动画时间”为每步的时间,不填则取玩家设定值。 - - 可以勾选“不等待执行完毕”来和后面的指令同时执行,比如让勇士和一个NPC肩并肩走。 - - 本指令不会触发跑毒和阻激夹域捕,且会无视地形可进出性、可通行性, - - 不会触发任何事件,就像“变量:debug”为true时按住Ctrl键移动一样。 - - debug模式下勇士不会因为Ctrl键走出地图,但本指令可以做到。 - - 指令的最后一个参数为步伐口诀,支持“上下左右前后”六种移动方向。连续的相同字可以合并,如“上上”可以写作“上2”。勇士后退时,跟随者们会照常前进。数不清楚格子时记得善用地图选点功能浏览地图。\ - 本指令对应core.eventMoveHero(steps, time, callback)函数,请注意不是`core.moveHero()` -3. 跳跃勇士:可以填写目标点坐标(支持双击从地图选点), - - 可以用带有冒号缩写量甚至API的表达式,比如`["core.nextX(2)", "core.nextY(2)"]`(json)表示勇士越过面前一格,即道具“跳跃靴”的效果。 - - 跳跃高度和距离有关,原地跳跃的高度只有半格(可在下述函数中修改)。跳跃过程中跟随者消失,跳跃结束时跟随者聚集。 - - 跳跃也支持异步效果(如和NPC一起跳),对应core.jumpHero(ex, ey, time, callback)函数,其中callback为异步跳跃完毕的回调函数。 - - 跳跃默认没有音效,您可以自行像支援怪和道具“跳跃靴”一样配上音效。 - - 和无视地形移动勇士一样,勇士跳跃也会无视目标点的地形和阻激击域捕,不会触发目标点的任何事件。 -4. 楼层切换:和前面的“楼梯、传送门”事件用法完全一样,但不可穿透。 - - 此指令同样支持双击从地图选点(坐标支持表达式)和在json区填写传送的目标点图块ID(在目标层唯一)再点击变黄的“解析”按钮。 - - 另外,正如本小节开头提到的,本指令比起“楼梯、传送门”事件更多地用于演出,因此您可以填写异常坐标。 -5. 位置朝向切换:“跳跃勇士”不会改变勇士朝向,“楼层切换”又会导致重生怪复活。且这两个都会导致跟随者聚集,所以同楼层内改变勇士位置可以使用本指令(坐标和跳跃一样支持双击从地图选点以及表达式)。 - - 本指令还可以用来让勇士原地转身(不填坐标,这样也不会聚集跟随者),支持4种绝对朝向和4种相对转向。 +1. **勇士前进一格或撞击:**如题,会让勇士像自由行动时一样尝试前进一格。 + * 如果可以前进但前方不可被踏入(如门、怪物、箱子、NPC)则会撞击并触发事件,走到道具、踩灯或路障或用普通事件制作的陷阱等也会触发。 + * 本指令可以正常触发跑毒和阻激夹域捕,滑冰事件就是在冰上执行了它。 + * 本指令对应`core.moveAction(callback)`函数,但请勿直接调用它。 +2. **无视地形移动勇士:**“动画时间”为每步的时间,不填则取玩家设定值。 + * 可以勾选“不等待执行完毕”来和后面的指令同时执行,比如让勇士和一个NPC肩并肩走。 + * 本指令不会触发跑毒和阻激夹域捕,且会无视地形可进出性、可通行性, + * 移动过程中不会触发任何事件,就像开启调试模式时按住Ctrl键移动一样(与之不同的是,也可以移动出地图外) + * 指令的最后一个参数为步伐口诀,支持`上下左右前后`六种移动方向。连续的相同字可以合并,如`上上`可以写作`上2`。 + * 勇士后退时,跟随者们会照常前进。 + * 数不清楚格子时记得善用地图选点功能浏览地图 + * 本指令对应`core.eventMoveHero(steps, time, callback)`函数,请注意不是`core.moveHero()` +3. **跳跃勇士:**可以填写目标点坐标(支持双击从地图选点), + * 可以用带有冒号缩写量甚至API的表达式,比如`["core.nextX(2)", "core.nextY(2)"]`(json)表示勇士越过面前一格,即道具“跳跃靴”的效果。 + * 跳跃高度和距离有关,原地跳跃的高度只有半格(可在下述函数中修改)。跳跃过程中跟随者消失,跳跃结束时跟随者聚集。 + * 跳跃也支持异步效果(如和NPC一起跳),对应`core.jumpHero(ex, ey, time, callback)`函数,其中`callback`为异步跳跃完毕的回调函数。 + * 跳跃默认没有音效,您可以自行像支援怪和道具“跳跃靴”一样配上音效。 + * 和无视地形移动勇士一样,勇士跳跃也会无视目标点的地形和阻激击域捕,不会触发目标点的任何事件。 +4. **楼层切换:**和前面的“楼梯、传送门”事件用法完全一样,但不可穿透。 + * 此指令同样支持双击从地图选点(坐标支持表达式)和在json区填写传送的目标点图块ID(在目标层唯一)再点击变黄的“解析”按钮。 + * 另外,正如本小节开头提到的,本指令比起“楼梯、传送门”事件更多地用于演出,因此您可以填写异常坐标。 +5. **位置朝向切换:**“跳跃勇士”不会改变勇士朝向,“楼层切换”又会导致重生怪复活。且这两个都会导致跟随者聚集,所以同楼层内改变勇士位置可以使用本指令(坐标和跳跃一样支持双击从地图选点以及表达式)。 + * 本指令还可以用来让勇士原地转身(不填坐标,这样也不会聚集跟随者),支持4种绝对朝向和4种相对转向。 ### “数据相关”类的其他杂牌指令 以下杂牌指令负责弹窗输入、显伤战斗、道具装备、全局商店、行走图和队伍: -1. 接受用户输入:弹窗请求用户输入一个自然数或字符串,提示文字允许使用`${表达式计算}`。 - 请求输入自然数(支持十六进制)时,负整数会被取绝对值。小数会被向0取整,其他非法输入会变为0. +1. **接受用户输入:**弹窗请求用户输入一个自然数或字符串,提示文字允许使用`${表达式计算}`。 + * 请求输入自然数(支持十六进制)时,负整数会被取绝对值。小数会被向0取整,其他非法输入会变为0. + * 请求输入字符串时,玩家点击取消则视为输入了空字符串。 + * 输入的结果会保存在值块`变量:input`(`flag:input`)中,可供后续处理。 + * 比如样板的生命魔杖就是一个例子,它允许玩家一次使用多个同种道具。 +2. **更新状态栏和地图显伤:**如题,可以勾选“不检查自动事件”来不检查。 + * 本指令实际执行“脚本编辑——更新状态栏”,即`core.updateStatusBar()` +3. **强制战斗(点名):**和天降怪物(指定ID,中文替换只支持不重复的中文名)强制战斗,不会从地图删除图块也不会触发各点的战后事件(黄点)。 + * 此指令一般用于覆盖触发器的boss,可以制作战前剧情,然后强制战斗。 + * 战后boss不立即消失,可以继续进行一些演出,如51层魔塔四区骑士队长的逃跑效果。 + * 值得注意的是,因为是天降怪物(没有坐标),所以对这只怪物在属性修正以及战损计算等处涉及到怪物坐标的代码一律不起作用(比如它不会受局部光环的加成,也不会被任何怪支援)。 + * 另一种强制战斗指令在“地图处理类”,指定的是坐标而不是怪物ID. +4. **尝试使用道具和穿脱装备:**使用道具和穿戴装备需要指定ID(中文替换规则和强制战斗一样)。 + * 不能使用怪物手册(请使用`特效声音类`的`呼出怪物手册`指令)和楼层传送器(如果`覆盖楼传事件`则没有关系),使用中心对称飞行器则会跳过确认画面。实际对应`core.useItem(itemId)`函数。 + * 穿脱装备对应`core.loadEquip(equipId)`和`core.unloadEquip(type)`函数。脱下装备需要指定类型,这里只能写自然数不能写名称。 + * 道具使用失败或穿不上装备(比如没有或不满足条件)时会提示。 +5. **开关全局商店:**本指令可以设置一个全局商店的启用和禁用状态,设为启用时也支持立即打开。 + * 一般用于商店的实体NPC处,再配合独立开关可以让勇士首次接触时先进行一些对话,然后启用(并打开)全局商店。 +6. **更改角色行走图:**如题,文件名必须填写(支持双击选文件)。 + * 文件必须放在`project/images`文件夹并注册,且规格必须符合要求(4帧总宽度至少128px,高度不限。宽高必须为4的倍数)。 + * 如果勾选“不重绘”就不会立即刷新,从而避免大地图视角重置到以勇士为中心。本指令对应`core.setHeroIcon(image, noDraw)`函数。 +7. **跟随者入队和离队:**您可以用这一对指令来让跟随者入队和离队,同样支持双击选文件。本指令对应`core.follow()`和`core.unfollow()`函数。 + * 行走图和勇士的规格要求(尺寸不需要一样)、文件位置和注册方法相同。 + * 离队可以不填文件名表示解散队伍只留勇士,如果填写文件名则尝试踢出队伍中第一个以此为行走图的跟随者。 + * 入队成功后、以及尝试离队后队伍都会聚拢,大地图视角也会重置。 - 请求输入字符串时,玩家点击取消则视为输入了空字符串。 - - 输入的结果会保存在值块“变量:input”中,可供后续处理。 - - 比如样板的生命魔杖就是一个例子,它允许玩家一次使用多个同种道具。 -2. 更新状态栏和地图显伤:如题,可以勾选“不检查自动事件”来不检查。 - - 本指令实际执行“脚本编辑——更新状态栏”,即core.updateStatusBar() -3. 强制战斗(点名):和天降怪物(指定ID,中文替换只支持不重复的中文名)强制战斗,不会从地图删除图块也不会触发各点的战后事件(黄点)。 - - 此指令一般用于覆盖触发器的boss,可以制作战前剧情,然后强制战斗。 - - 战后boss不立即消失,可以继续进行一些演出,如51层魔塔四区骑士队长的逃跑效果。 - - 值得注意的是,因为是天降怪物(没有坐标),所以对这只怪物在属性修正以及战损计算等处涉及到怪物坐标的代码一律不起作用(比如它不会受局部光环的加成,也不会被任何怪支援)。 - - 另一种强制战斗指令在“地图处理类”,指定的是坐标而不是怪物ID. -4. 尝试使用道具和穿脱装备:使用道具和穿戴装备需要指定ID(中文替换规则和强制战斗一样)。 - - 不能使用怪物手册(请使用“特效声音类”的“呼出怪物手册”指令)和楼层传送器(如果“覆盖楼传事件”则没有关系),使用中心对称飞行器则会跳过确认画面。实际对应core.useItem(itemId)函数。 - - 穿脱装备对应core.loadEquip(equipId)和core.unloadEquip(type)函数。 - - 道具使用失败或穿不上装备(比如没有或不满足条件)时会提示。 - - 脱下装备需要指定类型,这里只能写自然数不能写名称。 -5. 开关全局商店:本指令可以设置一个全局商店的启用和禁用状态,设为启用时也支持立即打开。 - - 一般用于商店的实体NPC处,再配合独立开关可以让勇士首次接触时先进行一些对话,然后启用(并打开)全局商店。 -6. 更改角色行走图:如题,文件名必须填写(支持双击选文件)。 - - 文件必须放在project\images文件夹并注册,且规格必须符合要求(4帧总宽度至少128px,高度不限。宽高必须为4的倍数)。 - - 如果勾选“不重绘”就不会立即刷新,从而避免大地图视角重置到以勇士为中心。本指令对应core.setHeroIcon(image, - noDraw)函数。 -7. 跟随者入队和离队:您可以用这一对指令来让跟随者入队和离队,同样支持双击选文件。本指令对应core.follow()和core.unfollow()函数。 - - 行走图和勇士的规格要求(尺寸不需要一样)、文件位置和注册方法相同。 - - 离队可以不填文件名表示解散队伍只留勇士,如果填写文件名则尝试踢出队伍中第一个以此为行走图的跟随者。 - - 入队成功后、以及尝试离队后队伍都会聚拢,大地图视角也会重置。 ## 地图处理类(浅蓝) -![image](img/v2.7/maps&waits&raw.png) + +![image](img/maps_waits_raw.jpg) 这个类型的指令会影响三层地图矩阵的阵元,如果您觉得三层还不够用,“插件编写”(句号键)五图层插件欢迎您。 -开始介绍前,首先明确一点:改变阵元不会立即影响事件的进程(自动事件除外)。 +开始介绍前,首先明确一点:改变地图数据不会立即影响事件的进程(自动事件除外)。 比如因为踩灯、路障和阻激夹域捕怪的分布变化导致勇士行走被妨害的区域发生变化,但不会立即触发妨害效果,而是要等到勇士下次行走。 在勇士所在点转变成(显示)一个门/怪物/道具/箱子/楼梯什么的(包括在脚下转变成/显示冰面)都不会立即触发事件,把这些图块移动/跳跃到勇士身上也是。 + 反之,“隐藏事件”(转变图块为0)也不会立即中止当前的事件处理,只是下次不会触发。 -1. 强制战斗(定点):这是另一种强制战斗,它指定坐标而不是怪物ID. - 可以双击从地图选点(只能选当前楼层的,不填则取当前点),也可以用表达式指定坐标,坐标一次只能写【一个点】。 +1. **强制战斗(定点):**这是另一种强制战斗,它指定坐标而不是怪物ID. + * 可以双击从地图选点(只能选当前楼层的,不填则取当前点),也可以用表达式指定坐标,坐标一次只能写【一个点】。 + * 战斗后会自动从地图删除该点的怪物,并尝试插入该点的战后事件(黄点),成功触发时会改变当前点坐标到该点。 +2. **开关门:**坐标写法同上(限1个点),同层开门时楼层ID可以略去不写。 + * 关门的位置必须是空地,“需要钥匙”只对同层开门有效。跨层开门请自己加判定,本指令对应`core.openDoor(x, y, needKey, callback)`函数。 + * 这对指令支持所有完整填写了“门信息”的四帧图块(自动元件除外),比如样板自带的三色墙和六色门。 + * 可以勾选“不等待执行完毕”来实现异步效果(如同时开关多个门,具体速度取决于门信息)。 + * 和上面的强制战斗一样,开门后将尝试插入该点的开门后事件(紫点),成功触发时会改变当前点坐标到该点。 +3. **显隐事件和图层块:**这两对指令可以令三层地图矩阵的某些阵元在0与非0之间切换。 + * 还以51层魔塔为例,二楼右下角的小偷在游戏开始时是不显示的,勇士进入四区后才出现。 + * 也就是说这个小偷是一个“普通事件”(红),内容是一些对话和打开35层魔龙处的暗道,只不过没有勾选“启用”。 + * 在适当的时候(这个例子中是和29楼小偷对话后),执行一个“显示MT2层(12,12)点处的事件”指令,就能显示出二楼的小偷。 + * 同理,勇士接触此小偷并处理事件,事件结束前执行一个`隐藏(同时删除)当前点事件,500毫秒`指令,小偷就会从画面中淡出,勇士可以任意在小偷存在过的位置走来走去而不会再触发什么。 + * 所以,一次性陷阱(走到某个地方关上墙/机关门、冒出埋伏怪)在触发后一定要及时隐藏。不然就会反复触发,样板1层有例子可供参考。 + * “显隐事件”都可以双击从地图选点,但是这样只能选一个点(只想要楼层ID的话可以点击“复制楼层ID”按钮)。在指令块中可以使用表达式作为坐标,甚至可以将若干个点的横坐标依次填在x处而纵坐标对应填在y处(json中写作多行两列的二维数组),从而同时显隐多个点。 + * 楼层ID省略则取当前楼层,“动画时间”用于同层显隐,从而表现出淡入淡出的效果。 + * “不等待执行完毕”的含义如前,您可以淡入一些点同时淡出另一些点。 + * 值得注意的是,“隐藏事件”还提供了一个“同时删除”勾选框,勾选后无法再用“显示事件”指令显示出来。 + * 请注意,隐藏或删除后不影响正在进行的事件流(不会立刻结束),您可以把该点安全地直接转变为别的图块或让别的图块移动/跳跃到此点,比如把箱子/阻击怪推过来。 + * 其他两个图层的图块也支持显隐,对游戏性的影响主要体现在显隐背景层的滑冰图块以及两个图层的单向通行箭头。坐标和楼层ID的填法同上,只不过这两个就没有淡入淡出效果了。因为其他两个图层的图块不支持什么初始隐藏,如有需要,可以在“开场剧情”中统一提前隐藏。 + * 显隐事件对应`core.showBlock(x, y, floorId)`和`core.hideBlock(x, y, floorId)`,同时删除对应`core.removeBlock(x, y, floorId)`函数;显隐图层块对应`core.maps._triggerFloorImage(type, loc, floorId, callback)` +4. **转变图块和图层块、事件转向:**这组指令可以修改三层地图矩阵的阵元。 + * 先说图层块吧(前景、背景),坐标和楼层的填法同上,不支持淡入淡出。转变图层块后,块的显隐状态不变,原来是隐藏还是隐藏。 + * 接着说事件层,坐标和楼层的填法同上。有几个注意事项: + 1. 新图块为0时“动画时间”全部用来淡出,用于没有普通事件和“楼梯、传送门”的点会视为删除。 + 2. 转变图块也不影响显隐状态,该点原来是隐藏还是隐藏。 + 3. 同层把一种非0图块转变为另一种非0图块,“动画时间”的前一半用来淡出原图块,后一半用来淡入新图块。 + 4. 同层把0图块转变为非0图块,“动画时间”全部用来淡入。 + * 这对指令可以填写新图块的ID也可以填写数字(如17是空气墙,201起是怪物)。 + * 如需让绑定了“行走图朝向”的npc48转向,也可以直接使用“事件转向”指令(和勇士一样支持7种转法),从而避免一个个手写行走图ID的麻烦。 + * 转变图块和图层块对应`core.setBlock(number, x, y, floorId)`和`core.maps._triggerBgFgMap(type, name, loc, floorId, callback)` +5. **显隐贴图:**这个指令可以用来显隐之前在“楼层属性”中介绍的楼层贴图。 + * 显隐贴图不支持淡入淡出,坐标为贴图左上角的【像素坐标】,楼层ID不填则取当前层。实际执行`core.maps._triggerFloorImage(type, loc, floorId, callback)` +6. **移动和跳跃事件:**这两个指令可以将地图一点的图块转移到另一点。 + * 首先明确一点,这两个指令转移的**仅仅是图块**。起点的七彩事件不会被一同转移,终点的七彩事件也不会被覆盖。 + * 从游戏性上讲,最终的效果是起点被“隐藏事件+同时删除”,勾选“不消失”时终点被“转变图块+显示事件”(终点原来的图块被覆盖)。 + * 比如,阻击怪是“移动后不消失”,捕捉怪是“移动后消失”,支援怪是“跳跃后消失”。 + * 这两个指令一次只能转移一个图块,双击从地图选点选择的是移动的起点和跳跃的终点(跳跃的起点请右击选取)。 + * 任何一个坐标不填都视为当前点,比如“跳跃事件”什么坐标都不填就会让当前点图块原地跳跃。 + * 和无视地形移动勇士一样,“移动事件”也没有碰撞效果,移动过程中会穿过勇士和一切地形。 + * “动画时间”为每步移动的时间和跳跃的用时,以及不勾选“不消失”时淡出的时间。 + * 和“跳跃勇士”一样,“跳跃事件”默认也没有音效,可以自己搭配。 + * 移动和跳跃实际对应`core.moveBlock(x, y, steps, time, keep, callback)`和`core.jumpBlock(sx, sy, ex, ey, time, keep, callback)`函数。 + * “移动事件”的步伐口诀只支持“上下左右”四个方向,不支持“前后”,即使是绑定了行走图朝向的NPC48也一样。 + * “不等待执行完毕”的用法如前,但几个图块再加上勇士以各异的速度和总步数移动时安排起来很麻烦,需要用到下述的“等待三姐妹”。 - 战斗后会自动从地图删除该点的怪物,并尝试插入该点的战后事件(黄点),成功触发时会改变当前点坐标到该点。 - -2. 开关门:坐标写法同上(限1个点),同层开门时楼层ID可以略去不写。 - - 关门的位置必须是空地,“需要钥匙”只对同层开门有效。跨层开门请自己加判定,本指令对应core.openDoor(x, y, needKey, callback)函数。 - - 这对指令支持所有完整填写了“门信息”的四帧图块(自动元件除外),比如样板自带的三色墙和六色门。 - - 可以勾选“不等待执行完毕”来实现异步效果(如同时开关多个门,具体速度取决于门信息)。 - - 和上面的强制战斗一样,开门后将尝试插入该点的开门后事件(紫点),成功触发时会改变当前点坐标到该点。 -3. 显隐事件和图层块:这两对指令可以令三层地图矩阵的某些阵元在0与非0之间切换。 - - 还以51层魔塔为例,二楼右下角的小偷在游戏开始时是不显示的,勇士进入四区后才出现。 - - 也就是说这个小偷是一个“普通事件”(红),内容是一些对话和打开35层魔龙处的暗道,只不过没有勾选“启用”。 - - 在适当的时候(这个例子中是和29楼小偷对话后),执行一个“显示MT2层(12,12)点处的事件”指令,就能显示出二楼的小偷。 - - 同理,勇士接触此小偷并处理事件,事件结束前执行一个“隐藏(同时删除)当前点事件,500毫秒”指令,小偷就会从画面中淡出,勇士可以任意在小偷存在过的位置走来走去而不会再触发什么。 - - 所以,一次性陷阱(走到某个地方关上墙/机关门、冒出埋伏怪)在触发后一定要及时隐藏。不然就会反复触发,样板1层有例子可供参考。 - - “显隐事件”都可以双击从地图选点,但是这样只能选一个点(只想要楼层ID的话可以点击“复制楼层ID”按钮)。在指令块中可以使用表达式作为坐标,甚至可以将若干个点的横坐标依次填在x处而纵坐标对应填在y处(json中写作多行两列的二维数组),从而同时显隐多个点。 - - 楼层ID省略则取当前楼层,“动画时间”用于同层显隐,从而表现出淡入淡出的效果。 - - “不等待执行完毕”的含义如前,您可以淡入一些点同时淡出另一些点。 - - 值得注意的是,“隐藏事件”还提供了一个“同时删除”勾选框,勾选后无法再用“显示事件”指令显示出来。 - - 删除后该点本身依然是启用状态,您可以把该点安全地直接转变为别的图块或让别的图块移动/跳跃到此点,比如把箱子/阻击怪推过来。 - - 其他两个图层的图块也支持显隐,对游戏性的影响主要体现在显隐背景层的滑冰图块以及两个图层的单向通行箭头。 - - 坐标和楼层ID的填法同上,只不过这两个就没有淡入淡出效果了。 - - 因为其他两个图层的图块不支持什么初始隐藏,如有需要,可以在“开场剧情”中统一提前隐藏。 - - 显隐事件对应core.showBlock(x, y, floorId)和core.hideBlock(x, y, floorId) - - 同时删除对应core.removeBlock(x, y, floorId)函数, - - 显隐图层块对应`core.maps._triggerFloorImage(type, loc, floorId, callback)` - -4. 转变图块和图层块、事件转向:这组指令可以修改三层地图矩阵的阵元。 - - 先说图层块吧(前景、背景),坐标和楼层的填法同上,不支持淡入淡出。 - - 转变图层块后,块的显隐状态不变,原来是隐藏还是隐藏。 - - 接着说事件层,坐标和楼层的填法同上。有几个注意事项: - 1. 新图块为0时“动画时间”全部用来淡出,用于没有普通事件和“楼梯、传送门”的点会视为删除。 - 2. 转变图块也不影响显隐状态,该点原来是隐藏还是隐藏。 - 3. 同层把一种非0图块转变为另一种非0图块,“动画时间”的前一半用来淡出原图块,后一半用来淡入新图块。 - 4. 同层把0图块转变为非0图块,“动画时间”全部用来淡入。 - - 这对指令可以填写新图块的ID也可以填写数字(如17是空气墙,201起是怪物)。 - - 如需让绑定了“行走图朝向”的npc48转向,也可以直接使用“事件转向”指令(和勇士一样支持7种转法),从而避免一个个手写行走图ID的麻烦。 - - 转变图块和图层块对应core.setBlock(number, x, y, floorId)和 - - `core.maps._triggerBgFgMap(type, name, loc, floorId, callback)` - -5. 显隐贴图:这个指令可以用来显隐之前在“楼层属性”中介绍的楼层贴图。 - - 显隐贴图不支持淡入淡出,坐标为贴图左上角的【像素坐标】,楼层ID不填则取当前层。实际执行`core.maps._triggerFloorImage(type, loc, floorId, callback)` - -6. 移动和跳跃事件:这两个指令可以将地图一点的图块转移到另一点。 - - 首先明确一点,这两个指令转移的【仅仅是图块】。起点的七彩事件不会被一同转移,终点的七彩事件也不会被覆盖。 - - 从游戏性上讲,最终的效果是起点被“隐藏事件+同时删除”,勾选“不消失”时终点被“转变图块+显示事件”(终点原来的图块被覆盖)。 - - 比如,阻击怪是“移动后不消失”,捕捉怪是“移动后消失”,支援怪是“跳跃后消失”。 - - 这两个指令一次只能转移一个图块,双击从地图选点选择的是移动的起点和跳跃的终点(跳跃的起点请右击选取)。 - - 任何一个坐标不填都视为当前点,比如“跳跃事件”什么坐标都不填就会让当前点图块原地跳跃。 - - 和无视地形移动勇士一样,“移动事件”也没有碰撞效果,移动过程中会穿过勇士和一切地形。 - - “动画时间”为每步移动的时间和跳跃的用时,以及不勾选“不消失”时淡出的时间。 - - 和“跳跃勇士”一样,“跳跃事件”默认也没有音效,可以自己搭配。 - - 移动和跳跃实际对应core.moveBlock(x, y, steps, time, keep, callback)和core.jumpBlock(sx, sy, ex, ey, time, keep, callback)函数。 - - “移动事件”的步伐口诀只支持“上下左右”四个方向,不支持“前后”,即使是绑定了行走图朝向的NPC48也一样。 - - “不等待执行完毕”的用法如前,但几个图块再加上勇士以各异的速度和总步数移动时安排起来很麻烦,需要用到下述的“等待三姐妹”。 - -### 等待三姐妹、注释和原生js/json +## 等待三姐妹、注释和原生js/json 在讲解“事件控制”(流程控制)类指令之前,这里插播几个比较杂牌的指令。 -1. 等待固定时间:如题,可以用来实现复杂的集体移动效果。 - 比如说51层魔塔一区结尾的骷髅埋伏圈,就是九只骷髅和四扇机关门组成的复杂演出。 +1. **等待固定时间:**如题,可以用来实现复杂的集体移动效果。 + * 比如说51层魔塔一区结尾的骷髅埋伏圈,就是九只骷髅和四扇机关门组成的复杂演出。 + * 每只骷髅开始移动时都不等待执行完毕,但又需要等待一小段时间再让下一只骷髅开始移动。 + * 本指令还提供了一个勾选项“不可被Ctrl跳过”,如果不勾选此项且当前【没有】正在执行的异步事件(动画不算),则Ctrl可以跳过等待。 +2. **等待所有异步事件执行完毕:**让我们来想象这样一个情景。 + * 您使用了“移动事件”来移动一只怪物到勇士面前,并且“不等待执行完毕”。而下一条指令是“勇士前进一格或撞击”,以期触发战斗。然而因为怪物移动需要时间,两个指令同时执行,所以战斗没法触发。 + * 类似地,如果您在一个异步事件执行完毕之前就结束了整个事件流,让勇士恢复行动,那么可能这些异步事件还没来得及在游戏性方面生效,导致接下来会发生的事取决于玩家操作的时机和勇士的移速。 + * 考虑到录像系统,在录像回放时很多耗时的东西和所有需要用户响应的东西会被跳过,勇士的移速又可以很快(倍速播放),导致回放结果和原游戏不一致。 + * 总之,当您希望确保一些异步事件完全生效后再开始执行新的指令或结束事件流,“等待所有异步事件执行完毕”就是您的不二之选了,事件编辑器也会在发现缺少本指令时弹窗警告。 +3. **等待用户操作并获得键鼠信息:**前面提到三种QTE指令,这是最后一种。 + * 此指令的下一条指令为“清除所有动图”的话,会先清除再开始等待。 + * 之前提到的“确认框”和“选择项”可以复现RPG Maker的回合制战斗,但没法做出更复杂的交互界面,比如技能/天赋树,以及样板的道具商店。 + * 本指令会阻塞事件的执行,直到玩家按下键盘上的某个键(滚轮视为PageUp/PageDown键)、或点击【视野】中的某个点、或经过了超时毫秒数(不设置则不限时)。 + * 解除阻塞后,下列值块可能发生变化: + 1. `变量:type`(`flag:type`),解除的原因,0表示按键,1表示点击,-1表示超时。 + 2. `变量:keycode`(`flag:keycode`),按键情况下的键值,48—57为大键盘0—9,65—90为字母键A—Z,其他键自己搜一下。 + 3. `变量:x`和`变量:y`(`flag:x`,`flag:y`),点击情况下所点格子的相对坐标,一定在0—12或0—14范围。 + 4. `变量:px`和`变量:py`(`flag:px`,`flag:py`),点击情况下所点像素的相对坐标,一定在0—415或0—479范围。 + * 您可以根据这些值块去做流程控制,较为简单的场合(如几个键执行同一段指令,或横平竖直的单个矩形点击区)也可直接使用图中的场合块。 + * 其中点击的场合块还支持双击预览判定区,用半透明的红色标出。 +4. **添加注释:**在上述的场合块里您还可以看到两个注释块。 + * 注释块在游戏中会被忽略,一般用来帮您记住写的指令是用来做什么的。 +5. **自定义事件:**自带的指令毕竟有限,但事件可以与脚本任意联动。 + * 原生脚本分为两种,原生js和原生json.其中后者会实际执行您通过`core.registerEvent`注册的事件处理函数,请注意这类函数在执行结束前务必调用`core.doAction()`函数去继续执行下一条指令。 + * 如果学有余力,还可根据[修改编辑器](editor)来代替原生json,就可以使用调色器、地图选点、选文件等功能啦。 +6. **原生JS脚本执行**:允许你执行任意JS脚本。 - 每只骷髅开始移动时都不等待执行完毕,但又需要等待一小段时间再让下一只骷髅开始移动。 +原生js的用法就更广了,首先它可以做一些事件做不到的事,比如: - 本指令还提供了一个勾选项“不可被Ctrl跳过”,如果不勾选此项且当前【没有】正在执行的异步事件(动画不算),则Ctrl可以跳过等待。 +如果用事件增加道具的话就会有提示和音效,而这有时不是我们需要的,尤其是在设计新道具时将“能否使用”填“true”并在使用效果事件中使用失败的场合返还道具时;因此我们可以直接调用脚本: +```js +core.addItem(itemId, n); // 静默增加n个道具,n可为负数,不填视为1 +``` -2. 等待所有异步事件执行完毕:让我们来想象这样一个情景。 +其次,受制于Antlr—blockly的数据类型,很多指令的参数只能写常数,比如楼层ID。这时我们就需要在原生js中使用万能的core.insertAction()大法,来突破这些限制。 - 您使用了“移动事件”来移动一只怪物到勇士面前,并且“不等待执行完毕”。而下一条指令是“勇士前进一格或撞击”,以期触发战斗。 +比如说我们有一座20层高的塔,楼层ID为MT0—MT19,某个事件中我们想让勇士随机传送到某个楼层,坐标不变。那么就可以使用下列原生js: +```js +core.insertAction({"type": "changeFloor", "floorId": "MT" + core.rand2(20)}) +``` - 然而因为怪物移动需要时间,两个指令同时执行,所以战斗没法触发。 +连续使用多条json指令时,请先声明一个空的指令数组(`var todo = [];`)然后将需要的指令逐条追加到其末尾(`todo.push({"type": "xxx", ...});`),最后再一次性`core.insertAction(todo)` - 类似地,如果您在一个异步事件执行完毕之前就结束了整个事件流,让勇士恢复行动,那么可能这些异步事件还没来得及在游戏性方面生效,导致接下来会发生的事取决于玩家操作的时机和勇士的移速。 +上述`core.rand2(20)`表示随机获取一个小于20的自然数。 - 尽管这在RPG Maker中很正常(怪物在地图上走来走去,主角要躲着走),但在我们的作品中是致命的。因为我们有录像系统,在录像回放时很多耗时的东西和所有需要用户响应的东西会被跳过。 +另外您可能会问:既然都用js了,为什么不直接用之前提到的core.changeFloor()函数呢? - 勇士的移速又可以很快(倍速播放),导致回放结果和原游戏不一致。 +这是因为,原生js在不勾选`不自动执行下一个事件`的情况下,**只能使用瞬间完成的函数(或者drawTip、动画和音效这种虽然耗时但不影响游戏性的),不能使用任何异步函数(包括阻塞直到玩家操作的)**! - 总之,当您希望确保一些异步事件完全生效后再开始执行新的指令或结束事件流,“等待所有异步事件执行完毕”就是您的不二之选了,事件编辑器也会在发现缺少本指令时弹窗警告。 -3. 等待用户操作并获得键鼠信息:前面提到三种QTE指令,这是最后一种。 +系统常见可能会被造塔用到的API都在[API列表](api)中给出,一般而言异步API的最后一个自变量都叫callback(回调)。在勾选`不自动执行下一个事件`的情况下,原生js可以使用一个异步API,只需将其`callback`参数填`core.doAction`,请谨慎使用。 - 此指令的下一条指令为“清除所有动图”的话,会先清除再开始等待。 +比如说,我们知道天降强制战斗没有坐标所以不受光环等影响也无法触发战后事件,那捕捉怪的战斗是怎么实现的呢?答案是在原生js中使用了异步的`core.battle(id, x, y, force, callback)`函数,这里`force`填`true`表示强制战斗,`callback`填`core.doAction`表示战斗结束后继续处理事件。 - 之前提到的“确认框”和“选择项”可以复现RPG Maker的回合制战斗, +熟练运用后,还可以使用多个异步API,每个以下一个作为回调。 - 但没法做出更复杂的交互界面,比如技能/天赋树,以及样板的道具商店。 - - 本指令会阻塞事件的执行,直到玩家按下键盘上的某个键(滚轮视为PageUp/PageDown键)、或点击【视野】中的某个点、或经过了超时毫秒数(不设置则不限时)。 - - 解除阻塞后,下列值块可能发生变化: - 1. “变量:type”,解除的原因,0表示按键,1表示点击,-1表示超时。 - 2. “变量:keycode”,按键情况下的键值,48—57为大键盘0—9,65—90为字母键A—Z,其他键自己搜一下。 - 3. “变量:x”和“变量:y”,点击情况下所点格子的相对坐标,一定在0—12或0—14范围。 - 4. “变量:px”和“变量:py”,点击情况下所点像素的相对坐标,一定在0—415或0—479范围。 - - 您可以根据这些值块去做流程控制,较为简单的场合(如几个键执行同一段指令,或横平竖直的单个矩形点击区)也可直接使用图中的场合块。 - - 其中点击的场合块还支持双击预览判定区,用半透明的红色标出。 -4. 添加注释:在上述的场合块里您还可以看到两个注释块。 - - 注释块在游戏中会被忽略,一般用来帮您记住写的指令是用来做什么的。 - 请注意,右击块加注释的功能有问题用不了,请忽略那个功能。 - -5. 原生js/json脚本:自带的指令毕竟有限,但事件可以与脚本任意联动。 - - 原生脚本分为两种,原生js和原生json.其中后者会实际执行您自定义的`core.events._action_xxx(data, x, y, callback)`函数,请注意这类函数在执行结束前务必调用core.doAction()函数去继续执行下一条指令。 - - 如果学有余力,还可根据@zhaouv撰写的另一篇文档自定义新的blockly指令块来代替原生json,就可以使用调色器、地图选点、选文件等功能啦。 - - 原生js的用法就更广了,首先它可以做一些事件做不到的事,比如: - - core.addItem(itemId, n); // 静默增加n个道具,n可为负数,不填视为1 - - 如果用事件增加道具的话就会有提示和音效,而这有时不是我们需要的, - - 尤其是在设计新道具时将“能否使用”填“true”并在使用效果事件中使用失败的场合返还道具时。 - - 其次,受制于Antlr—blockly的数据类型,很多指令的参数只能写常数,比如楼层ID. - - 这时我们就需要在原生js中使用万能的core.insertAction()大法,来突破这些限制。 - - 比如说我们有一座20层高的塔,楼层ID为MT0—MT19, - - 某个事件中我们想让勇士随机传送到某个楼层,坐标不变。 - - 那么就可以使用下列原生js: - - `core.insertAction({"type": "changeFloor", "floorId": "MT" + core.rand2(20)})` - - 连续使用多条json指令时,请先声明一个空的指令数组(`let todo = [];`)然后将需要的指令逐条追加到其末尾(`todo.push({"type": "xxx", ...});`),最后再一次性core.insertAction(todo) - - 上述core.rand2(20)表示随机获取一个小于20的自然数,另外您可能会问: - - 既然都用js了,为什么不直接用之前提到的core.changeFloor()函数呢? - - 这是因为,原生js在不勾选“不自动执行下一个事件”的情况下, - - 只能使用瞬间完成的函数(或者drawTip、动画和音效这种虽然耗时但不影响游戏性的),不能使用任何异步函数(包括阻塞直到玩家操作的)! - - 系统常见可能会被造塔用到的API都在runtime.d.ts中给出, - - 一般而言异步API的最后一个自变量都叫callback(回调)。 - - 在勾选“不自动执行下一个事件”的情况下,原生js可以使用一个异步API,只需将其callback参数填core.doAction,请谨慎使用。 - - 比如说,我们知道天降强制战斗没有坐标所以不受光环等影响也无法触发战后事件,那捕捉怪的战斗是怎么实现的呢?答案是在原生js中使用了异步的core.battle(id, x, y, force, callback)函数,这里force填true表示强制战斗,callback填core.doAction表示战斗结束后继续处理事件。 - - 熟练运用后,还可以使用多个异步API,每个以下一个作为回调。 ## 事件控制类(深蓝) -![image](img/v2.7/flowCtrl.png) -在三个QTE指令中,我们已经初见了流程控制的端倪。 +![image](img/flowCtrl.jpg) -只不过,它们的流程走向是由玩家的选择直接左右的。 +在三个QTE指令中,我们已经初见了流程控制的端倪。只不过,它们的流程走向是由玩家的选择直接左右的。能否通过对值块的比较等操作自动走向不同的流程分支呢?答案是肯定的。 -能否通过对值块的比较等操作自动走向不同的流程分支呢?答案是肯定的。 -1. 条件分歧:和“显示确认框”很相似,只不过这个是自动的。 - - 和js的`if (...) {...;} else {...;}`完全等价,本指令需要内嵌一个值块(可以填逻辑表达式,常常是两个值块的比较,比如某道具是否足够)。 - - 当此值块的值不为“false、0、null、undefined、NaN和空字符串”时, - - 执行“如果:”和“否则:”之间的指令。 - - 当此值块的值为这六个值之一时,执行“否则:”后面的指令。 -2. 多重分歧:本指令和js的switch语句有一定差别,即使您有js基础也请仔细阅读接下来的说明。 - - 事件执行到多重分歧指令时,会先计算一次“判别值”,结果记作key. - - 然后准备一个空的指令数组,记作list.接下来从上到下扫描每个场合块, - - 如果一个场合块的“值”为default或计算结果和key相等, - - 就把这个场合的指令组追加到list的末尾,`core.push(list, [...])`, - - 每次成功追加后,如果被追加的此场合块未勾选“不跳出”, - - 则无视下面的所有场合块直接结束扫描,否则继续扫描下一个场合块。 - - 扫描完全结束后,调用core.insertAction(list)付诸执行。 - - 所以各场合块的顺序一定要安排好,比如default(可以没有此场合)如果不勾选“不跳出”则一定要放在最后。 - - 多重分歧常见的用法是,判别值填常量,各场合块填未知量且都勾选“不跳出”。把所有相等的场合筛选出来依次执行,类似js的filter语法。 - - 或者,判别值填未知量,所有场合块都不勾选“不跳出”且“值”填写为两两不同的常量(如果有相同的则只有第一个有效)。从而执行唯一的相等场合,没有的话还可以补一个default场合,类似js的else +1. **条件分歧:**和“显示确认框”很相似,只不过这个是自动的。 + * 和js的`if (...) {...;} else {...;}`完全等价,本指令需要内嵌一个值块(可以填逻辑表达式,常常是两个值块的比较,比如某道具是否足够)。 + * 当此值块的值不为`false、0、null、undefined、NaN和空字符串`时,执行“如果:”和“否则:”之间的指令,当此值块的值为这六个值之一时,执行“否则:”后面的指令。 +2. **多重分歧:**本指令和js的switch语句有一定差别,即使您有js基础也请仔细阅读接下来的说明。 + * 事件执行到多重分歧指令时,会先计算一次“判别值”,结果记作key.然后准备一个空的指令数组,记作list; + * 接下来从上到下扫描每个场合块,如果一个场合块的“值”为default或计算结果和key相等,就把这个场合的指令组追加到list的末尾,`core.push(list, [...])` + * 每次成功追加后,如果被追加的此场合块未勾选“不跳出”,则无视下面的所有场合块直接结束扫描,否则继续扫描下一个场合块。 + * 扫描完全结束后,调用core.insertAction(list)付诸执行。 + * 所以各场合块的顺序一定要安排好,比如default(可以没有此场合)如果不勾选“不跳出”则一定要放在最后。 + * 多重分歧常见的用法是,判别值填常量,各场合块填未知量且都勾选“不跳出”。把所有相等的场合筛选出来依次执行,类似js的filter语法。 + * 或者,判别值填未知量,所有场合块都不勾选“不跳出”且“值”填写为两两不同的常量(如果有相同的则只有第一个有效)。从而执行唯一的相等场合,没有的话还可以补一个default场合,类似js的else if语法。 -3. 循环遍历(计数):使用临时变量A—Z(事件流结束时会和arg+纯数字的变量一起被清空)可以进行循环遍历,它们都属于前置条件循环。 - - 循环遍历有两种,第一种是计数型。“从”和“到”之间的框填写临时变量的初始值,“到”和“步增”之间的框填写临时变量允许的边界值。 - - 每轮循环开始前会【重新计算】边界值和步增,如果临时变量位于界外(减去边界值后和步增同号)则跳出循环。 - - 每轮循环结束时,临时变量会加上步增值(可以为负数,请注意变号问题)。 -4. 循环遍历(迭代):这是另一种循环遍历,可以迭代一个列表。 - - 每轮循环前,会检查列表是否已空。已空则跳出循环,否则将列表的第一项【移除并代入】临时变量。 - - 使用此项时请注意,列表中的字符串不会被自动解释为冒号缩写量。 - - 显示文章等处如有需求,请使用`${core.calValue(temp:A-Z)}`来计算。 - - 分歧和循环都可以嵌套,嵌套循环遍历请给内外层使用不同的临时变量。 - - 此指令对应的js语法为`for (let term of list) {...;}` -5. 前/后置条件循环:在《仙剑奇侠传1》中,有一个非常经典的场景。 - - 男主角李逍遥在扬州封城期间抓小偷不成反被失主诬告,县太爷命令衙役刑讯逼供。在游戏中就表现为玩家需要对一个确认框选择“NO”,如果选择“YES”就会再次弹出同一个确认框,如此往复。 - - 当然,这一节的流程控制都是自动的,不会这样欺负玩家。 - - 客观上,前置条件循环和一个没有“否则”分支的条件分歧很相似,区别仅仅在于每次执行完分支内容后都会【跳转】回到条件检测之前,从而再次检测条件,还满足就再执行,如此往复。 - - 而后置条件循环比起前置,区别在于第一轮循环是无视条件强制执行的。 - - 它们对应的js语法分别为`while (...) {...;}和do {...;} while(...);` -6. 跳出当前循环:如题,遇到此指令时,将检测当前是否在某个循环中(还包括自动事件、公共事件、全局商店),并跳出所在的【最内层】循环。如果不在任何循环中,则什么也不做。大致相当于js的break; -7. 提前结束本轮循环:生效范围同上,不过是结束最内层的【本轮】循环。 - - 换言之,对一般的前/后置条件循环会立刻跳转到下次检测条件前, - - 对循环遍历(计数)会立刻跳转到下次计算边界和步增并累加前, - - 对循环遍历(迭代)会立刻跳转到下次检查列表是否为空前。 - - 还可用来“重启新版商店或道具商店”。若不在任何循环中,则什么也不做。 - - 完全等价于js的continue; -8. 立刻结束当前事件:此指令将清空临时变量(以@temp开头)和参数变量(arg+纯数字),清空事件列表,中断一切事件处理,恢复勇士行动。 -9. 触发系统事件:模拟勇士撞击/踩踏本楼层的某个点,把触发的事件(包括图块属性的script,不包括阻激夹域捕和血网)插队到当前事件列表中。 - - 譬如该点是道具则会捡起来,是怪物则会强制战斗,是门则会尝试开门, - - 还会连带触发对应的afterXxx事件。实际执行core.trigger(x, y, callback) - - 而如果该点是楼梯则会直接触发传送(目标点是“保持不变”或三种对称点也以勇士位置而不是楼梯位置计算),是路障则会触发对应的毒衰咒(血网除外,它的原理是把伤害加到了阻激夹域里所以只有真实的行走才能触发)。是踩灯则会把勇士脚下变成踩过的灯,是普通事件(红)则会触发。滑冰在背景层,所以无法触发。至于推箱子...请自行探索。 -10. 插入公共事件:如题,“参数列表”为一数组,其各项会被依次代入值块“变量:arg1”、“变量:arg2”...而“变量:arg0”会记录公共事件的名称。 - - 实际执行core.insertCommonEvent(name, args, x, y, callback, addToLast) -11. 插入事件:此指令可以无视目标点启用与否,跨楼层插入任何点的普通事件或afterXxx事件执行。 - - 这本是两年前公共事件尚未问世的权宜之计,楼层ID不填视为当前楼层。参数列表意义同上,只不过“变量:arg0”这次是坐标。 - -其中“触发系统事件”和“插入事件”支持双击从地图选点。 +3. **循环遍历(计数):**使用临时变量A—Z(事件流结束时会和arg+纯数字的变量一起被清空)可以进行循环遍历,它们都属于前置条件循环。 + * 循环遍历有两种,第一种是计数型。`从`和`到`之间的框填写临时变量的初始值,`到`和`步增`之间的框填写临时变量允许的边界值。 + * 每轮循环开始前会【重新计算】边界值和步增,如果临时变量位于界外(减去边界值后和步增同号)则跳出循环。 + * 每轮循环结束时,临时变量会加上步增值(可以为负数,请注意变号问题)。 +4. **循环遍历(迭代):**这是另一种循环遍历,可以迭代一个列表。 + * 每轮循环前,会检查列表是否已空。已空则跳出循环,否则将列表的第一项【移除并代入】临时变量。 + * 使用此项时请注意,列表中的字符串不会被自动解释为冒号缩写量。显示文章等处如有需求,请使用`${core.calValue(temp:A)}`来计算。 + * 分歧和循环都可以嵌套,嵌套循环遍历请给内外层使用不同的临时变量。 +5. **前/后置条件循环:** + * 客观上,前置条件循环和一个没有“否则”分支的条件分歧很相似,区别仅仅在于每次执行完分支内容后都会【跳转】回到条件检测之前,从而再次检测条件,还满足就再执行,如此往复。 + * 而后置条件循环比起前置,区别在于第一轮循环是无视条件强制执行的。 + * 它们对应的js语法分别为`while (...) {...;}和do {...;} while(...);` +6. **跳出当前循环:**如题,遇到此指令时,将检测当前是否在某个循环中(还包括自动事件、公共事件、全局商店),并跳出所在的【最内层】循环。如果不在任何循环中,则什么也不做。大致相当于js的`break;` +7. **提前结束本轮循环:**生效范围同上,不过是结束最内层的【本轮】循环。换言之,对一般的前/后置条件循环会立刻跳转到下次检测条件前, + * 对循环遍历(计数)会立刻跳转到下次计算边界和步增并累加前, + * 对循环遍历(迭代)会立刻跳转到下次检查列表是否为空前。 + * 还可用来“重启新版商店或道具商店”。若不在任何循环中,则什么也不做。 + * 大致等价于js的`continue;` +8. **立刻结束当前事件:**此指令将清空临时变量(以`@temp@`开头)和参数变量(`arg+纯数字`),清空事件列表,中断一切事件处理,恢复勇士行动。 +9. **触发系统事件:**模拟勇士撞击/踩踏本楼层的某个点,把触发的事件(包括图块属性的`script`,不包括阻激夹域捕和血网)插队到当前事件列表中。支持双击地图选点。 + * 譬如该点是道具则会捡起来,是怪物则会强制战斗,是门则会尝试开门, + * 还会连带触发对应的`afterXxx`事件。实际执行`core.trigger(x, y, callback)` + * 如果该点是楼梯则会直接触发传送(目标点是“保持不变”或三种对称点也以勇士位置而不是楼梯位置计算),是路障则会触发对应的毒衰咒(血网除外)。是踩灯则会把勇士脚下变成踩过的灯,是普通事件(红)则会触发。滑冰在背景层,所以无法触发。至于推箱子...请自行探索。 +10. **插入公共事件:**如题,“参数列表”为一数组,其各项会被依次代入值块`变量:arg1`、`变量:arg2`...而`变量:arg0`会记录公共事件的名称。 + * 实际执行`core.insertCommonEvent(name, args, x, y, callback, addToLast)` +11. **插入事件:**此指令可以无视目标点启用与否,跨楼层插入任何点的普通事件或afterXxx事件执行。支持双击地图选点。 ## 特效声音类(褐色) -![image](img/v2.7/blockly.png) + +![image](img/blockly.jpg) 这个类别的指令会负责动画、视角、色调、天气、音频等其他一些细节。 -1. 画面震动:会让画面左右震动,时间必须为500毫秒的倍数且至少1秒。 - 实际执行core.vibrate(time, callback)函数。 -2. 显示动画:如题,可以双击选文件并预览(预览的坐标锁定为视野中心)和试听/修改音效。 +1. **画面震动:**会让画面左右震动,时间必须为500毫秒的倍数且至少1秒。 + * 实际执行`core.vibrate(time, callback)`函数。 +2. **显示动画:**如题,可以双击选文件并预览(预览的坐标锁定为视野中心)和试听/修改音效。 + * 如需从地图选点请右击指令块,坐标也可写hero令动画跟随勇士移动。 + * 坐标不写则取当前点,如果勾选“相对窗口坐标”则坐标应填写为0—12或0—14表示视野中的相对坐标(如13×13样板填两个6表示视野中心)。 + * 另外,即使勾选了“不等待执行完毕”,此指令也不会被视为通常意义上的异步事件,换言之没有其他异步事件的风险。 + * 如果不勾选“不等待执行完毕”,则等待的实际时长只取决于动画,和音效无关(同时开播)。 + * 实际调用`core.drawAnimate(name, x, y, alignWindow, callback)`和`core.drawHeroAnimate(name, callback)` +3. **设置和移动视角:**设置视角支持双击从地图选点,不填坐标则重置视角。 + * 移动视角的动画时间为每动一格的时间,步伐数组只支持“上下左右”。 + * 请注意,勇士重绘时(`core.drawHero()`函数)视角也会随之重置。所以视角变化后勇士的坐标、朝向、显隐、行走图(事件和API都提供了不重绘参数)和跟随者情况暂时都不要动。 + * 实际调用`core.setViewport(x, y)`和`core.moveViewport(steps, time, callback)`,其中前者的自变量为【像素坐标】且不必为32的倍数,必要时可作为原生js使用来实现特殊的演出。 +4. **显隐状态栏:**如题,如果隐藏状态栏期间勇士需要恢复行动,则建议不隐藏竖屏工具栏以方便手机玩家。 + * 实际调用`core.showStatusBar()`和`core.hideStatusBar(showToolbox)` +5. **显隐勇士:**如题,动画时间为淡入淡出时间,异步勾选框用法如前。 + * 实际调用`core.triggerHero(type, time, callback)` +6. **更改画面色调:**色调可以用调色器调配,“动画时间”为渐变的总时间。 + * 请注意渐变是在RGBA颜色空间中匀速直线运动,因此效果可能不好,画面闪烁同理。 +7. **恢复画面色调:**指将更改后的色调恢复到楼层的默认色调。 +8. **画面闪烁:**“单次时间”必须为3的倍数,前1/3时间用于将画面色调转变为目标色调,后2/3时间用于恢复当前色调,执行次数如题。 + * 实际调用`screenFlash(color, time, times, callback)` +9. **更改天气:**如题,可以选择“无、雨、雪、雾”之一,强度需填小于等于10的正整数。 +10. **播放背景音乐:**如题,可以双击选文件并试听,并指定开始播放的秒数。 + * 如前所述,当在游戏中触发楼层切换时(包括读档),如果`flag:__color__、flag:__weather__、flag:__bgm__`这三个值块没有值,游戏当时的画面色调、天气、背景音乐就会变为楼层属性中的这三个设置项。 + * 以上几个指令都提供了“持续到下个本事件”勾选框,勾选后,本次设置的值将会计入这三个值块。它们的拦截行为在“脚本编辑——切换楼层中”。 + * 若不勾选,或恢复画面色调、设置天气为无(晴),就会清除对应的值块。您也可以随时对这三个值块进行手动干预。 +11. **暂停和恢复背景音乐:**如题,暂停时会记录暂停在了第几秒,恢复时可以选择从这个秒数继续或从头重播。 +12. **预加载背景音乐和释放其缓存:**在线游戏使用,前者的原理是静音播放。 + * 最多同时缓存四首背景音乐(由`libs/core.js`控制),会自动释放最久未使用的,但您也可以手动释放。 +13. **播放音效和停止所有音效:**如题,开播一个音效的同时可以停止其他的。 +14. **设置音量:**只对背景音乐有效,音量为小于等于100的自然数(玩家设置值其实被开了平方),渐变时间如题。 +15. **呼出怪物手册和SL界面:** + * 呼出手册只在勇士持有手册时生效,关闭手册后事件继续。 + * 呼出存档界面最多只能存一个档然后事件继续(读档后事件现场会恢复) + * 呼出读档界面如果不读档则事件继续,录像回放中这组指令被忽略。 +16. **自动存档:**读档后也会恢复事件现场,录像回放中会照常存档。 + * 如不勾选“不提示”则会core.drawTip(“已自动存档”),此指令一般用于选择项/确认框之前。 - 如需从地图选点请右击指令块,坐标也可写hero令动画跟随勇士移动。 - - 坐标不写则取当前点,如果勾选“相对窗口坐标”则坐标应填写为0—12或0—14表示视野中的相对坐标(如13×13样板填两个6表示视野中心)。 - - 另外,即使勾选了“不等待执行完毕”,此指令也不会被视为通常意义上的异步事件,换言之没有其他异步事件的风险。 - - 如果不勾选“不等待执行完毕”,则等待的实际时长只取决于动画,和音效无关(同时开播)。实际调用core.drawAnimate(name, x, y, alignWindow, callback)和core.drawHeroAnimate(name, callback) -3. 设置和移动视角:设置视角支持双击从地图选点,不填坐标则重置视角。 - - 移动视角的动画时间为每动一格的时间,步伐数组只支持“上下左右”。 - - 请注意,勇士重绘时(core.drawHero()函数)视角也会随之重置。所以视角变化后勇士的坐标、朝向、显隐、行走图(事件和API都提供了不重绘参数)和跟随者情况暂时都不要动。 - - 实际调用core.setViewport(x, y)和`core.moveViewport(steps, time, callback)`, - 其中前者的自变量为【像素坐标】且不必为32的倍数,必要时可作为原生js使用来实现特殊的演出。 -4. 显隐状态栏:如题,如果隐藏状态栏期间勇士需要恢复行动,则建议不隐藏竖屏工具栏以方便手机玩家。 - - 实际调用core.showStatusBar()和core.hideStatusBar(showToolbox) -5. 显隐勇士:如题,动画时间为淡入淡出时间,异步勾选框用法如前。 - - 实际调用core.triggerHero(type, time, callback) -6. 更改画面色调:色调可以用调色器调配,“动画时间”为渐变的总时间。 - - 请注意渐变是在RGBA颜色空间中匀速直线运动,因此效果可能不好,画面闪烁同理。 -7. 恢复画面色调:指将更改后的色调恢复到楼层的默认色调。 -8. 画面闪烁:“单次时间”必须为3的倍数,前1/3时间用于将画面色调转变为目标色调,后2/3时间用于恢复当前色调,执行次数如题。 - - 实际调用screenFlash(color, time, times, callback) -9. 更改天气:如题,可以选择“无、雨、雪、雾”之一,强度需填小于等于10的正整数。 -10. 播放背景音乐:如题,可以双击选文件并试听,并指定开始播放的秒数。 - - 如前所述,当在游戏中触发楼层切换时(包括读档),如果 `flag:__color__、flag:__weather__、flag:__bgm__`这三个值块没有值,游戏当时的画面色调、天气、背景音乐就会变为楼层属性中的这三个设置项。 - - 以上几个指令都提供了“持续到下个本事件”勾选框,勾选后,本次设置的值将会计入这三个值块。它们的拦截行为在“脚本编辑——切换楼层中”。 - - 若不勾选,或恢复画面色调、设置天气为无(晴),就会清除对应的值块。您也可以随时对这三个值块进行手动干预。 -11. 暂停和恢复背景音乐:如题,暂停时会记录暂停在了第几秒,恢复时可以选择从这个秒数继续或从头重播。 -12. 预加载背景音乐和释放其缓存:在线游戏使用,前者的原理是静音播放。 - - 最多同时缓存四首背景音乐(由libs\core.js控制),会自动释放最久未使用的,但您也可以手动释放。 -13. 播放音效和停止所有音效:如题,开播一个音效的同时可以停止其他的。 -14. 设置音量:只对背景音乐有效,音量为小于等于100的自然数(玩家设置值其实被开了平方),渐变时间如题。 -15. 呼出怪物手册和SL界面:呼出手册只在勇士持有手册时生效,关闭手册后事件继续。 - - 呼出存档界面最多只能存一个档然后事件继续(读档后事件现场会恢复) - - 呼出读档界面如果不读档则事件继续,录像回放中这组指令被忽略。 -16. 自动存档:读档后也会恢复事件现场,录像回放中会照常存档。 - - 如不勾选“不提示”则会core.drawTip(“已自动存档”),此指令一般用于选择项/确认框之前。 ## UI绘制类(瞬间) -![image](img/v2.7/uievent.png) + +![image](img/uievent.jpg) 这个类别的指令全部是瞬间完成的,有一一对应的API,请放心使用,除“绘制多行文本”外都可以逐个双击预览。游戏中,这些指令都是画在uievent层的。 -1. UI绘制并预览:您可以把一堆UI绘制类指令塞进去然后双击黄框整体预览 - 请注意,“绘制多行文本”双击是多行编辑,必须塞到这里才能预览。 -2. 清除画布:擦除uievent层的一部分,x和y为左上角坐标。 - - 四个参数都支持使用表达式,任何一个参数不填都会删除整个uievent层。 - 实际调用core.clearMap(“uievent”,x,y,width,height)和core.deleteCanvas(“uievent”),熟练后对其他画布使用也是可以的。 -3. 设置画布属性: +1. **UI绘制并预览:**您可以把一堆UI绘制类指令塞进去然后双击黄框整体预览 + * 请注意,“绘制多行文本”双击是多行编辑,必须塞到这里才能预览。 +2. **清除画布:**擦除uievent层的一部分,x和y为左上角坐标。 + * 四个参数都支持使用表达式,任何一个参数不填都会删除整个uievent层。 + * 实际调用`core.clearMap("uievent",x,y,width,height)`和`core.deleteCanvas("uievent")`,熟练后对其他画布使用也是可以的。 +3. **设置画布属性:** 1. 字体:`italic和bold`表示斜体和加粗,可省略,字号和字体用于绘制文本。 2. 填充样式:绘制实心图形时的默认填色,可用调色器调配。 3. 边框样式:绘制空心图形时的默认边框颜色,可用调色器调配。 4. 线宽度:绘制线段、箭头和空心图形时的默认线宽,单位为像素。 - 5. 不透明度:不大于1的非负数,此项为“画笔”的不透明度。 - - 只影响接下来画的内容,已经画上去的不受影响。 + 5. 不透明度:不大于1的非负数,此项为“画笔”的不透明度。只影响接下来画的内容,已经画上去的不受影响。 6. 对齐:绘制单行文本的对齐方式,左对齐、左右居中、右对齐。 - 7. 基准线:绘制单行文本的基准线,有六种写法。 + 7. 基准线:绘制单行文本的基准线,有六种写法。绘制单行文本的坐标其实是文本的基准点, + 8. z值:初始为135,z值较大的画布将覆盖较小的,详见“个性化”。闪烁光标的z值总是比上述的值大1,即默认为136. +4. **绘制文本:** + * 这里仅绘制单行文化单行,坐标为基准点的像素坐标,需配合上述“对齐”和“基准线”使用。 + * 如果设置了最大宽度,那么在超出此宽度时就会保持比例压缩到这个宽度。 + * 正文只支持`${js表达式求值}`,不支持其他一切转义序列,更不能手动换行。 + * 实际执行`core.fillText("uievent", text, x, y, style, font, maxWidth)` +5. **绘制描边文本:**同上,但不支持限宽,描边效果同状态栏数字的黑边。 + * 实际原理是向四个方向各偏移1px以描边色绘制了四份一样的文本,中央再以文本色覆盖一份。 + * 本指令对应的`js函数为core.ui.fillBoldText('uievent', text, x, y, style, font)` +6. **绘制多行文本:**双击进入多行编辑,预览请塞进黄框。 + * 起点像素为左上角,只有设置了最大行宽才会对齐、居中和自动换行。 + * 如果不设置颜色和字号,就会采用“设置剧情文本的属性”中的正文设置。 + * 不设置行距就会采用字体大小的1.3倍,建议采用偶数字号和1.5倍行距。 + * 多行文本不支持字体样式的设置,使用的是全塔属性中的全局字体`Verdana`, + * 如有需要,请使用“设置全局属性”指令来设置字体样式。 +7. **绘制几何图形:**对应的`js函数为core.ui.fillXxx()和core.ui.strokeXxx()` +8. **绘制图片:**同“显示图片”指令但功能有出入,比如这个支持旋转。实际执行`core.drawImage('uievent',img,x,y,w,h,x1,y1,w1,h1)` +9. **绘制图标:**支持图块id和系统图标,支持伸缩和选择哪一帧。支持32×32和32×48两种尺寸,实际执行`core.drawIcon(name, id, x, y, w, h, frame)` +10. **绘制背景图:**背景色支持颜色数组,也支持类似`winskin.png`的图片名。使用图片时不透明度,纯色背景时的边框颜色,由“设置画布属性”指定。本指令对应的`js函数为core.ui.drawBackground(left, top, right, bottom, posInfo)` +11. **绘制和清除闪烁光标:**如题,光标的z值总是比`uievent`层大1. + +========================================================================================== - 绘制单行文本的坐标其实是文本的基准点, - - 而对齐方式和基准线决定了基准点在单行文本矩形区的相对位置, - - 就像Windows“画图”的画布周围的八个拖动点一样: - - ----------------- ------------------- ----------------- - 左对齐+顶部 左右居中+顶部 右对齐+顶部 - ----------------- ------------------- ----------------- - 左对齐+上下居中 左右居中+上下居中 右对齐+上下居中 - ----------------- ------------------- ----------------- - 左对齐+底部 左右居中+底部 右对齐+底部 - ----------------- ------------------- ----------------- - - 基准线的“标准值”(alphabet,默认值)比“底部”略高,另外两种为“悬挂”和“表意文字”,具体效果请自行双击预览。 - 8. $z$值:初始为135,$z$值较大的画布将覆盖较小的,详见“个性化”。 - - 闪烁光标的$z$值总是比上述的值大1,即默认为136. -4. 绘制文本: - - 单行,坐标为基准点的像素坐标,需配合上述“对齐”和“基准线”使用。 - - 如果设置了最大宽度,那么在超出此宽度时就会保持比例压缩到这个宽度。 - - 正文只支持`${js表达式求值}`,不支持其他一切转义序列,更不能手动换行。 - - 实际执行core.fillText(’uievent’, text, x, y, style, font, maxWidth) -5. 绘制描边文本:同上,但不支持限宽,描边效果同状态栏数字的黑边。 - - 实际原理是向四个方向各偏移1px以描边色绘制了四份一样的文本,中央再以文本色覆盖一份。 - - 本指令对应的`js函数为core.ui.fillBoldText('uievent', text, x, y, style, font)` - -6. 绘制多行文本:双击进入多行编辑,预览请塞进黄框。 - - 起点像素为左上角,只有设置了最大行宽才会对齐、居中和自动换行。 - - 如果不设置颜色和字号,就会采用“设置剧情文本的属性”中的正文设置。 - - 不设置行距就会采用字体大小的1.3倍,建议采用偶数字号和1.5倍行距。 - - 多行文本不支持字体样式的设置,使用的是全塔属性中的全局字体`Verdana`, - - 如有需要,请使用“设置全局属性”指令来设置字体样式。 - -![image](img/v2.7/parabola.png) -7. 绘制几何图形:对应的`js函数为core.ui.fillXxx()和core.ui.strokeXxx()` - - 更复杂的曲线要用很多折线来拟合,譬如我想画抛物线$y=x^2/400$: - - `for(x=0;x<400;++x)core.ui.drawLine('uievent',x,x*x/400,x+1,(x+1)*(x+1)/400)` - 图中绘制在了UI层,`uievent`层也是一样的道理。 -8. 绘制图片:同“显示图片”指令但功能有出入,比如这个支持旋转。 - - 实际执行`core.drawImage('uievent',img,x,y,w,h,x1,y1,w1,h1)` -9. 绘制图标:支持图块id和系统图标,支持伸缩和选择哪一帧 - - 支持32×32和32×48两种尺寸,实际执行`core.drawIcon(name, id, x, y, w, h, frame)` - -10. 绘制背景图:背景色支持颜色数组,也支持类似winskin.png的图片名。 - - 使用图片时不透明度,纯色背景时的边框颜色,由“设置画布属性”指定。 - - 本指令对应的`js函数为core.ui.drawBackground(left, top, right, bottom, posInfo)` -11. 绘制和清除闪烁光标:如题,光标的$z$值总是比`uievent`层大1. \ No newline at end of file +[继续阅读下一章:个性化](personalization) diff --git a/_docs/personalization.md b/_docs/personalization.md index e29776e1..c950a2ee 100644 --- a/_docs/personalization.md +++ b/_docs/personalization.md @@ -1,5 +1,6 @@ # 个性化 -?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} * + +?> 在这一节中,让我们来了解更多对样板个性化的修改 有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。 @@ -58,31 +59,19 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana'); 带有独立开关的商人算是一个最为简单的单点多事件的例子了,单点多事件最常用的指令就是“转变图块”(或关门)和“条件分歧”。下面以几个具体例子来进行详细说明: 1. 打怪变成门或道具、开门变成怪或道具:怪物、门、道具都是系统触发器,直接利用afterXxx事件。如: - - 战后事件:关门`yellowDoor`(原地关上了一扇黄门) - - 战后事件:转变图块为`yellowKey`(怪物掉落了黄钥匙) - - 开门后事件:转变图块为`greenSlime或yellowKey`(开门变成了史莱姆或黄钥匙) - - 打怪变成别的怪、开门关上别的门、门和怪来回变的,用独立开关计数。 - - 如有批量需求,请使用“脚本编辑——afterXxx”函数。 + * 战后事件:关门`yellowDoor`(原地关上了一扇黄门) + * 战后事件:转变图块为`yellowKey`(怪物掉落了黄钥匙) + * 开门后事件:转变图块为`greenSlime`或`yellowKey`(开门变成了史莱姆或黄钥匙) + * 打怪变成别的怪、开门关上别的门、门和怪来回变的,用独立开关计数。 + * 如有批量需求,请使用“脚本编辑 - `afterXxx`函数。 2. 打怪/开门/捡道具后变成传送点或npc: - - 这时的传送点就不能用“楼梯、传送门”事件了,而应该用只有一条“场景切换”指令的普通事件。 - - 此事件不勾选“覆盖触发器”,这样怪物、门和道具的系统触发器会触发。 - - 在对应的afterXxx事件中“转变图块为”传送点或npc,淡入效果更佳哦。 - - 请注意,因为道具是可通行的,如果勇士走到道具上,就会和npc重合。 - -3. (懒人的选择)利用“图块类别:x,y”和“图块ID:x,y”等值块集中处理: - - 如果您实在搞不清楚“覆盖触发器”和“通行状态”这两项,那就干脆勾选前者并把后者设为不可通行,本希望可以通行的场合就得用“无视地形移动勇士”指令前进一步。 - - 用自动事件去转变图块,然后利用上述两个值块判定当前图块的状态等,再用“强制战斗”、“开门(需要钥匙)”和`core.getItem(id)`分别处理吧。 + * 这时的传送点就不能用“楼梯、传送门”事件了,而应该用只有一条“场景切换”指令的普通事件。 + * 此事件不勾选“覆盖触发器”,这样怪物、门和道具的系统触发器会触发。 + * 在对应的afterXxx事件中“转变图块为”传送点或npc,淡入效果更佳哦。 + * 请注意,因为道具是可通行的,如果勇士走到道具上,就会和npc重合。 +3. (懒人的选择)利用`图块类别:x,y`和`图块ID:x,y`等值块集中处理: + * 如果您实在搞不清楚“覆盖触发器”和“通行状态”这两项,那就干脆勾选前者并把后者设为不可通行,本希望可以通行的场合就得用“无视地形移动勇士”指令前进一步。 + * 用自动事件去转变图块,然后利用上述两个值块判定当前图块的状态等,再用`强制战斗`、`开门(需要钥匙)`和`增加道具`分别处理吧。 ## 并行脚本:即时制的希望? @@ -94,37 +83,37 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana'); js语言其实是没有多线程的,但我们可以写一些浏览器帧刷新时执行的脚本,也就是“并行脚本”。 -并行脚本分为两种,全塔并行和楼层并行。前者在“脚本编辑—并行脚本”,后者在楼层属性。 - -一般来说,当您有多个楼层需要执行相同的并行脚本时,建议写在前者并通过对core.status.floorId的范围进行判定来决定具体执行的内容。 +并行脚本分为两种,全塔并行和楼层并行。前者在“脚本编辑—并行脚本”,后者在楼层属性。一般来说,当您有多个楼层需要执行相同的并行脚本时,建议写在前者并通过对core.status.floorId的范围进行判定来决定具体执行的内容。 并行脚本将被系统反复执行,执行的时机是“浏览器帧刷新”,换言之相邻两次执行的间隔取决于浏览器或设备的性能,上限为60fps即每秒60次。 -如果有一个bgs是1秒长的心跳声,我们把它注册到了全塔属性的音效中。 +如果有一个bgs是1秒长的心跳声,我们把它注册到了全塔属性的音效中。假设这个bgs要被用于MT0层,那么我们在MT0层的“楼层属性——并行脚本”中写这样的代码: -假设这个bgs要被用于MT0层,那么我们在MT0层的“楼层属性——并行脚本”中写这样的代码: ``` js - if (core.hasFlag('frame')) { +if (core.hasFlag('frame')) { // 剧情事件中将“变量:frame”设为正整数来开启bgs,设为0来关闭 - core.status.hero.flags.frame %= 60000; // 防止挂机太久导致溢出 - if (core.getFlag('frame', 0) % 60 === 0) - core.playSound('heartBeat.wav'); // 每60帧即1秒播放一次 - ++core.status.hero.flags.frame; // 帧数加1 - + core.status.hero.flags.frame %= 60000; // 防止挂机太久导致溢出 + if (core.getFlag('frame', 0) % 60 === 0) + core.playSound('heartBeat.wav'); // 每60帧即1秒播放一次 + core.status.hero.flags.frame++; // 帧数加1 } // 其他特效也是一样的用法。 ``` + +在并行脚本(全塔或楼层)里可以使用`timestamp`作为参数,表示从游戏开始到当前总共过了多少毫秒。 + ## 覆盖楼传事件 对于特殊的塔,我们可以考虑修改楼传事件来完成一些特殊的要求,比如镜子可以按楼传来切换表里。 要修改楼传事件,需要进行如下两步: -1. 重写楼传的点击事件。在插件中对`core.control.useFly进行重写`。详细代码参见[重写点击楼传事件](script#重写点击楼传事件)。 -2. 修改楼传的使用事件。和其他永久道具一样,在地图编辑器的图块属性中修改楼传的useItemEffect和canUseItemEffect两个内容。例如: +1. 重写楼传的点击事件。在插件中对`core.control.useFly`进行重写。详细代码参见[重写点击楼传事件](script#重写点击楼传事件)。 +2. 修改楼传的使用事件。和其他永久道具一样,在地图编辑器的图块属性中修改楼传的`useItemEvent`(或`useItemEffect`)和`canUseItemEffect`两个内容。例如: ``` js -"useItemEffect": "core.insertAction([...])" // 执行某段自定义事件,或者其他脚本 +"useItemEvent": "[...]" // 执行某段自定义事件 "canUseItemEffect": "true" // 任何时候可用 ``` +3. 将全塔属性里的`楼梯边楼传`的勾去掉。 除了覆盖楼传事件外,对于快捷商店、虚拟键盘等等也可以进行覆盖,只不过是仿照上述代码重写对应的函数(`openQuickShop`,`openKeyBoard`)即可。 @@ -134,7 +123,7 @@ js语言其实是没有多线程的,但我们可以写一些浏览器帧刷新 要修改按键,我们可以在脚本编辑的`onKeyUp`进行处理: -我们设置一个快捷键进行绑定,比如 `Y`,其 `keycode` 是 `89` 。
+我们设置一个快捷键进行绑定,比如 `Y`,其 `keycode` 是 `89` 。 (大键盘数字键 `0-9` 的 `keycode` 为 `48-57, A-Z` 键的 `keycode` 为 `65-90` ,其他键的 `keycode` 搜一下就能得到) 然后在脚本编辑的`onKeyUp`函数的`switch`中进行处理。 @@ -216,6 +205,7 @@ this.myfunc = function(x) { 具体可详见脚本编辑的`drawStatusBar`函数。 自绘状态栏开启后,金币图标将失去打开快捷商店的功能,您可以修改脚本编辑的 `onStatusBarCLick` 函数来适配。 + ## 自定义状态栏的显示项 在V2.2以后,我们可以自定义状态栏背景图(全塔属性 - statusLeftBackground)等等。 @@ -275,8 +265,11 @@ core.statusBar.speed.innerHTML = core.getStatus('speed'); core.statusBar.speed.innerHTML = core.getFlag('speed', 0); ``` 总的来说不建议这样做,因为 `main.js` 和 `html` 文件不在 `project` 文件夹,会导致随样板更新迁移接档变得困难。 + ## 技能塔的支持 + 从V2.5开始,内置了"二倍斩"技能,可以仿照其制作自己的技能。要支持技能塔,可能需要如下几个方面: + - 魔力(和上限)的添加;技能的定义 - 状态栏的显示 - 技能的触发(按键与录像问题) @@ -315,6 +308,7 @@ core.statusBar.skill.innerHTML = core.getFlag('skillName', '无'); ### 技能的触发 #### 使用道具作为技能 + 由于手机端按字母键不方便,虚拟键盘不好用,因此强烈推荐**给每个字母键技能设置一个道具,在道具栏点击使用!** 下面是个很简单的例子,要制作一个技能"二倍斩"。 diff --git a/_docs/script.md b/_docs/script.md index 76903d02..521fcf9c 100644 --- a/_docs/script.md +++ b/_docs/script.md @@ -1,6 +1,6 @@ # 脚本 -?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} * +?> 在这一节中,让我们来了解如何使用控制台和复写函数! 在V2.6版本中,基本对整个项目代码进行了重写,更加方便造塔者的使用和复写函数。 @@ -349,6 +349,6 @@ core.registerAnimationFrame("globalAnimate", true, "myGlobalAnimate"); ========================================================================================== -[继续阅读下一章:API列表](api) +[继续阅读下一章:修改编辑器](editor) diff --git a/_docs/start.md b/_docs/start.md index b06a2ba0..8e5e8761 100644 --- a/_docs/start.md +++ b/_docs/start.md @@ -1,6 +1,6 @@ # 快速上手 -?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} *
-在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔! + +?> 在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔! ## 前置需求 你需要满足如下条件才能进行制作:[样板下载地址](https://github.com/ckcz123/mota-js/releases)。 @@ -14,44 +14,50 @@ 3. (强烈推荐)[VScode](http://code.visualstudio.com/download):最适合HTML5项目的文本编辑器,能进行跨文件的正则搜索和替换,也能完整发挥根目录的runtime.d.ts文件的作用。 只要满足了上述条件,你就可以开始做自己的塔啦! + ## 启动HTTP服务 -与编辑器闭源的RPG Maker -MV不同,本样板对文件的绝大部分修改是通过网页编辑器经由本地HTTP服务完成的,这样做也有助于编辑器跨平台并最大限度地复用运行时代码,还可以让玩家在在线游戏时查看游戏工程。 + +与编辑器闭源的RPG Maker MV不同,本样板对文件的绝大部分修改是通过网页编辑器经由本地HTTP服务完成的,这样做也有助于编辑器跨平台并最大限度地复用运行时代码,还可以让玩家在在线游戏时查看游戏工程。 在根目录下有一个“启动服务.exe”,运行之。(非Windows电脑则需使用命令行运行server.py,安卓手机则使用造塔器) -![image](img/v2.7/server.png) -1. 启动游戏:打开127.0.0.1:1055/index.html,同时开启多个启动服务则1056、1057顺延(下同)。你能在里面看到现在游戏的效果。 -2. 地图编辑器:打开127.0.0.1:1055/editor.html(竖屏则为editor-mobile.html),这是您整个制作流程的核心页面。\ - 以下为Windows专用的一些辅助工具(位于“辅助工具”文件夹),由C#编写: -3. 便捷PS工具:能方便地替换和新增素材。 -4. 地图生成器:识别RPG Maker魔塔的地图截图,生成HTML5魔塔的地图数据。 -5. 怪物数据导出:从RPG Maker XP - 1.03游戏导出怪物数据,用于HTML5魔塔或使用excel查看。 -6. RM动画导出:从RPG Maker XP 1.03游戏导出动画,用于HTML5魔塔。 -7. JS代码压缩:对js代码和音像素材(背景音乐除外)进行压缩,从而减小文件体积,加快在线游戏的加载。 -8. 额外素材合并:将`project\tilesets`文件夹中的图片中用到的图块重新拼成更少的图片,并更新对应的地图矩阵。 -9. 动画编辑器:编辑`project\animates`文件夹中的动画文件,或利用图片制作全新的动画。 -10. 伤害和临界值计算器、帮助文档:如题,后者会打开本文档。 +![image](img/server.jpg) + +* 启动游戏:打开[http://127.0.0.1:1055/index.html](http://127.0.0.1:1055/index.html),同时开启多个启动服务则1056、1057顺延(下同)。你能在里面看到现在游戏的效果。 +* 地图编辑器:打开[http://127.0.0.1:1055/editor.html](http://127.0.0.1:1055/editor.html)(竖屏则为editor-mobile.html),这是您整个制作流程的核心页面 + +以下为Windows专用的一些辅助工具(位于“辅助工具”文件夹),由C#编写: + +* 便捷PS工具:能方便地替换和新增素材。 +* 地图生成器:识别RPG Maker魔塔的地图截图,生成HTML5魔塔的地图数据。 +* 怪物数据导出:从RPG Maker XP 1.03游戏导出怪物数据,用于HTML5魔塔或使用excel查看。 +* RM动画导出:从RPG Maker XP 1.03游戏导出动画,用于HTML5魔塔。 +* JS代码压缩:对js代码和音像素材(背景音乐除外)进行压缩,从而减小文件体积,加快在线游戏的加载。 +* 额外素材合并:将`project\tilesets`文件夹中的图片中用到的图块重新拼成更少的图片,并更新对应的地图矩阵。 +* 动画编辑器:编辑`project\animates`文件夹中的动画文件,或利用图片制作全新的动画。 +* 伤害和临界值计算器、帮助文档:如题,后者会打开本文档。 !> **整个造塔过程中,启动服务必须全程处于开启状态!切不可手滑关闭,否则做的都是无用功!** + ## 编辑器页面的结构 -![image](img/v2.7/editor.png) -------------------------------- -如上图,编辑器页面的结构分为三大部分。左边叫数据区,中央叫地图区,右侧叫素材区,竖屏状态下同时只能显示其中一个,需要经常来回切换。 + +![image](img/editor.jpg) + +如上图,编辑器页面的结构分为三大部分。左边叫**数据区**,中央叫**地图区**,右侧叫**素材区**,竖屏状态下同时只能显示其中一个,需要经常来回切换。 请尤其注意中央下方的下拉框,您可以随时按下Z、X、…、句号键(字母键第三行)让数据区在这些模式之间切换。更多键鼠快捷操作请按下H键查看,这里列出一部分: -1. Alt+0—9、0—9:给素材区的图块绑定数字快捷键,并使用。(您也可以用中央下方的“最近/最常使用图块”和置顶来代替) -2. WASD、或单击/长按四个箭头按钮:滚动大地图,还可以单击“大地图”按钮观看全景。 -3. Ctrl+W/A/S/Z/X/C/V/Y:关闭、全选、保存、撤销、剪切、复制、粘贴、重做绘图等操作。 -4. PageUp/PageDown或滚轮:切换楼层。 -5. ESC、Delete:取消选中并保存、删除选中点的图块和事件。(需要保存时“保存地图”按钮也会变色提示) -6. 地图上单击、双击、右击:地图选点、选中该点的素材并自动定位到素材区、弹出菜单(您可以进行出生点、机关门、上下楼的快速绑定等操作) -7. 地图上左键或右键拖动:交换两个点的图块和事件、框选一些点供Ctrl+X/C/V剪切复制。 -8. 素材区最右侧的tileset区域左键拖动:框选一批素材,供在地图区单击批量绘制或左键拖动平铺。 -9. 事件编辑器中Ctrl+S/Z/X/C/V/Y、右击、双击等:执行相应操作,如双击可以进入多行编辑或UI绘制预览。 +1. **Alt+0~9、0~9:**给素材区的图块绑定数字快捷键,并使用。(您也可以用中央下方的“最近/最常使用图块”和置顶来代替) +2. **WASD、或单击/长按四个箭头按钮:**滚动大地图,还可以单击“大地图”按钮观看全景。 +3. **Ctrl+W/A/S/Z/X/C/V/Y:**关闭、全选、保存、撤销、剪切、复制、粘贴、重做绘图等操作。 +4. **PageUp/PageDown或滚轮:**切换楼层。 +5. **ESC、Delete:**取消选中并保存、删除选中点的图块和事件。(需要保存时“保存地图”按钮也会变色提示) +6. **地图上单击、双击、右击:**地图选点、选中该点的素材并自动定位到素材区、弹出菜单(您可以进行出生点、机关门、上下楼的快速绑定等操作) +7. **地图上左键或右键拖动:**交换两个点的图块和事件、框选一些点供Ctrl+X/C/V剪切复制。 +8. **素材区最右侧的tileset区域左键拖动:**框选一批素材,供在地图区单击批量绘制或左键拖动平铺。 +9. **事件编辑器中Ctrl+S/Z/X/C/V/Y、右击、双击等:**执行相应操作,如双击可以进入多行编辑或UI绘制预览。 ## 快速上手 + 针对红海塔作者,这里给出一个极简版的造塔流程,您可以据此造出一座没有任何事件(包括但不限于难度分歧、老人、木牌、商人和商店等)的塔: 1. 编辑勇士的出生点和初始属性: 1. 滚轮切换到主塔0层,右击地图任意位置,绑定出生点为此点(会有一个大大的白色S字母显示出来)。 @@ -61,28 +67,32 @@ MV不同,本样板对文件的绝大部分修改是通过网页编辑器经由 3. 如果您需要制作多个楼层,只需按下Z键将数据区切换到“地图编辑”模式,然后“新建空白地图”即可,不同楼层之间简单地通过楼梯来往返,您可以将楼梯画在地图上再右击快速绑定即可。(看到楼梯左下角出现绿色小方块即说明绑定成功)各个楼层的属性可以通过按下V键将数据区切换到“楼层属性”模式来填写,如能否使用楼传、是否为地下层、画面色调、宝石血瓶倍率等。 4. 从素材区选择您所使用的各种怪物,在数据区填写它们的各项属性,其中“特殊属性”是通过多选框来编辑的。 5. 游戏胜利的触发:滚轮切换到样板1层,单击地图上的公主,按下Ctrl+C复制。滚轮切换回您的boss层,(记得给boss设置不可被炸哦)单击boss身后的任何一个空格子,按下Ctrl+V粘贴即可。这样玩家触碰到公主游戏就会胜利。 + ## 控制台调试 -![image](img/v2.7/console.png) ---------------------------------- + +![image](img/console2.jpg) + HTML5项目都是可以进行控制台调试的,下面以edge浏览器为例介绍其部分操作: 首先按下F12键(部分键盘没有此键或需与Fn键一起按)或Ctrl+Shift+I,打开开发人员界面。 可以看到它分为“元素”、“控制台”、“调试程序”、“性能”等多个部分: -1. 元素:您可以在这里对游戏和编辑器的各HTML和css元素进行查看和临时的修改,譬如您想观察游戏在竖屏的表现,只需将窗口拉到瘦高。 -2. 性能:您可以在这里对游戏的任何一段脚本进行性能分析,观察其中各行的执行频率和耗时,从而确定优化的方向。 -3. 调试程序:您可以在这里查看游戏的源码,包括project文件夹的functions.js和plugin.js(脚本编辑和插件编写)以及整个libs文件夹,并进行断点调试。 -4. 控制台:最常使用的部分,当编辑器或游戏打不开、卡死、或者不按您的预想运作时您就需要查看这里的报错信息。这里也是各种API输入的地方,譬如上图中您可以看到全部的插件函数。这里介绍几个最基本的命令,更多通用命令请前往[菜鸟教程](http://www.runoob.com/js)或[w3school](http://w3school.com.cn/js/index.asp)学习,更多样板API请查阅runtime.d.ts(这是个文本文件,不是音频。手机打不开的话请将后缀名改为txt)。 +1. **元素:**您可以在这里对游戏和编辑器的各HTML和css元素进行查看和临时的修改,譬如您想观察游戏在竖屏的表现,只需将窗口拉到瘦高。 +2. **性能:**您可以在这里对游戏的任何一段脚本进行性能分析,观察其中各行的执行频率和耗时,从而确定优化的方向。 +3. **调试程序:**您可以在这里查看游戏的源码,包括project文件夹的functions.js和plugin.js(脚本编辑和插件编写)以及整个libs文件夹,并进行断点调试。 +4. **控制台:**最常使用的部分,当编辑器或游戏打不开、卡死、或者不按您的预想运作时您就需要查看这里的报错信息。这里也是各种API输入的地方,譬如上图中您可以看到全部的插件函数。这里介绍几个最基本的命令,更多通用命令请前往[菜鸟教程](http://www.runoob.com/js)或[w3school](http://w3school.com.cn/js/index.asp)学习,更多样板API请查阅runtime.d.ts(这是个文本文件,不是音频。手机打不开的话请将后缀名改为txt)。 ``` js alert('Hello world!'); // 弹窗警告,请勿放在正常游戏流程中可以触发的地方 console.log('Hello world'); // 在控制台打印一条信息,可用于游戏流程的任何部分 - Math.xxx(); // 执行一个数学函数计算,如Math.random()会得到一个小于1的随机正数 - // 以上是所有网页通用的命令,下面介绍HTML5魔塔样板特有的两个API. - // 样板API都是以core.xxx开头的,比如: + Math.floor(3.2); // 执行一个数学函数计算,计算不大于某数的最大整数 + // 以上是所有网页通用的命令,下面介绍HTML5魔塔样板特有的API. 样板API都是以core.xxx开头的,比如: core.material; // 查看游戏的所有元件(只读),如动画、音频、图片、道具和怪物等 core.status; // 查看游戏的所有状态,其中又以core.status.hero为核心 - core.getItem('yellowKey', n); // 获得n个某道具(支持即捡即用类,n不写视为1),提示并播放音效 + core.getItem('yellowKey', 3); // 获得3把黄钥匙,有获得提示并播放音效 ``` + +更多关于控制台调试和脚本的信息可参见[脚本](script)和[API列表](api)。 + ========================================================================================== [继续阅读下一章:元件说明](element) diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js index 17adb7a4..435fab3e 100644 --- a/_server/CodeMirror/defs.js +++ b/_server/CodeMirror/defs.js @@ -1334,17 +1334,14 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "__visited__": { "!doc": "当前访问过的楼层" }, + "__leaveLoc__": { + "!doc": "每个楼层的离开位置,用于楼传平面塔模式" + }, "cannotMoveDirectly": { "!type": "bool", "!doc": "当前是否全局不可瞬移" }, }, - "loc": { - "!doc": "勇士坐标", - "x": "number", - "y": "number", - "direction": "string" - }, "hero": { "!doc": "勇士当前属性", "image": { @@ -1432,12 +1429,17 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ }, }, "equips": { - "!doc": "未装备上的装备" + "!doc": "在背包中未装备上的装备" }, }, "loc": { "!doc": "勇士当前坐标和朝向", - "!type": "loc", + "x": "number", + "y": "number", + "direction": { + "!doc": "朝向,只能为 up,down,left,right 之一", + "!type": "string" + }, }, "flags": { "!type": "flag", @@ -2070,6 +2072,14 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!doc": "当前地图信息" } }, + "init": { + "!doc": "初始化core", + "!type": "fn(coreData: ?, callback: fn())" + }, + "doFunc": { + "!doc": "执行一个函数;如果函数名是字符串则转发到插件中", + "!type": "fn(func: name|fn(), _this?: ?)" + }, "control": { "!doc": "游戏控制", "showStatusBar": { @@ -2170,7 +2180,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ }, "setAutomaticRoute": { "!doc": "半自动寻路,用于鼠标或手指拖动
例如:core.setAutomaticRoute(0, 0, [{direction: \"right\", x: 4, y: 9}, {direction: \"right\", x: 5, y: 9}]);
destX: 鼠标或手指的起拖点横坐标
destY: 鼠标或手指的起拖点纵坐标
stepPostfix: 拖动轨迹的数组表示,每项为一步的方向和目标点。", - "!type": "fn(destX: number, destY: number, stepPostfix: [loc])" + "!type": "fn(destX: number, destY: number, stepPostfix: [{x: number, y: number, direction: string}])" }, "triggerHero": { "!doc": "改变勇士的显隐状态", @@ -2265,7 +2275,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!type": "fn()" }, "setAutoHeroMove": { - "!doc": "连续行走
例如:core.setAutoHeroMove([{direction: \"up\", step: 1}, {direction: \"left\", step: 3}, {direction: \"right\", step: 3}, {direction: \"up\", step: 9}]); // 上左左左右右右上9
steps: 压缩的步伐数组,每项表示朝某方向走多少步", + "!doc": "连续行走
例如:core.setAutoHeroMove([{direction: \"up\", step: 1}, {direction: \"left\", step: 3}]); // 上左左左
steps: 压缩的步伐数组,每项表示朝某方向走多少步", "!type": "fn(steps: [?])" }, "fillPosWithPoint": { @@ -2646,7 +2656,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "right": { "x": "number", "y": "number" - }, + } }, "clamp": { "!doc": "将x限定在[a,b]区间内,注意a和b可交换
例如:core.clamp(1200, 1, 1000); // 1000
x: 原始值,!x为true时x一律视为0
a: 下限值,大于b将导致与b交换
b: 上限值,小于a将导致与a交换", @@ -2757,7 +2767,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!type": "fn(turn: string, direction?: string) -> string" }, "myconfirm": { - "!doc": "显示确认框,类似core.drawConfirmBox()
例如:core.myconfirm('重启游戏?', core.restart); // 弹窗询问玩家是否重启游戏
hint: 弹窗的内容
yesCallback: 确定后的回调函数
noCallback: 取消后的回调函数,可选", + "!doc": "显示确认框,类似core.drawConfirmBox(),但不打断事件流
例如:core.myconfirm('重启游戏?', core.restart); // 弹窗询问玩家是否重启游戏
hint: 弹窗的内容,支持 ${} 语法
yesCallback: 确定后的回调函数
noCallback: 取消后的回调函数,可选", "!type": "fn(hint: string, yesCallback?: fn(), noCallback?: fn())" }, "calValue": { @@ -2961,6 +2971,14 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!doc": "播放动画,注意即使指定了主角的坐标也不会跟随主角移动,如有需要请使用core.drawHeroAnimate(name, callback)函数
例如:core.drawAnimate('attack', core.nextX(), core.nextY(), false, core.vibrate); // 在主角面前一格播放普攻动画,动画停止后视野左右抖动1秒
name: 动画文件名,不含后缀
x: 横坐标
y: 纵坐标
alignWindow: 是否是相对窗口的坐标
callback: 动画停止后的回调函数,可选
返回值:一个数字,可作为core.stopAnimate()的参数来立即停止播放(届时还可选择是否执行此次播放的回调函数)", "!type": "fn(name: string, x: number, y: number, alignWindow: bool, callback?: fn()) -> number" }, + "drawHeroAnimate": { + "!doc": "播放跟随勇士的动画
name: 动画名
callback: 动画停止后的回调函数,可选
返回值:一个数字,可作为core.stopAnimate()的参数来立即停止播放(届时还可选择是否执行此次播放的回调函数)", + "!type": "fn(name: string, callback?: fn()) -> number" + }, + "stopAnimate": { + "!doc": "立刻停止一个动画播放
id: 播放动画的编号,即drawAnimate或drawHeroAnimate的返回值
doCallback: 是否执行该动画的回调函数", + "!type": "fn(id: number, doCallback?: bool)" + }, "getBlockCls": { "!doc": "判定某个点的图块类型
例如:if(core.getBlockCls(x1, y1) != 'enemys' && core.getBlockCls(x2, y2) != 'enemy48') core.openDoor(x3, y3); // 另一个简单的机关门事件,打败或炸掉这一对不同身高的敌人就开门
x: 横坐标
y: 纵坐标
floorId: 地图id,不填视为当前地图
showDisable: 隐藏点是否不返回null,true表示不返回null
返回值:图块类型,即“地形、四帧动画、矮敌人、高敌人、道具、矮npc、高npc、自动元件、额外地形”之一", "!type": "fn(x: number, y: number, floorId?: string, showDisable?: bool) -> string" @@ -3043,7 +3061,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ }, "automaticRoute": { "!doc": "自动寻路
例如:core.automaticRoute(0, 0); // 自动寻路到地图左上角
destX: 目标点的横坐标
destY: 目标点的纵坐标
返回值:每步走完后主角的loc属性组成的一维数组", - "!type": "fn(destX: number, destY: number) -> [loc]" + "!type": "fn(destX: number, destY: number) -> [{x: number, y: number, direction: string}]" }, "resizeMap": { "!doc": "更改地图画布的尺寸", @@ -3067,7 +3085,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ }, "searchBlock": { "!doc": "搜索图块, 支持通配符和正则表达式
例如:core.searchBlock('*Door'); // 搜索当前地图的所有门
id: 图块id,支持星号表示任意多个(0个起)字符
floorId: 地图id,不填视为当前地图
showDisable: 隐藏点是否计入,true表示计入
返回值:一个详尽的数组,一般只用到其长度", - "!type": "fn(id: string, floorId?: string, showDisable?: bool) -> Array<{ floorId -> string, index -> number, x -> number, y -> number, block -> Block }>" + "!type": "fn(id: string, floorId?: string, showDisable?: bool) -> [{floorId: string, index: number, x: number, y: number, block: block}]" }, "hideBgFgMap": { "!doc": "隐藏前景/背景地图", @@ -3151,7 +3169,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ }, "getBlock": { "!doc": "获得某个点的block", - "!type": "fn(x: number, y: number, floorId?: string, showDisable?: bool) -> block" + "!type": "fn(x: number, y: number, floorId?: string, showDisable?: bool) -> {index: number, block: block}" }, "initBlock": { "!doc": "初始化一个图块", @@ -3327,6 +3345,10 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!doc": "地图中间绘制一段文字", "!type": "fn(contents: string, callback?: fn())" }, + "drawConfirmBox":{ + "!doc": "绘制一个确认框
此项会打断事件流,如需不打断版本的请使用core.myconfirm()
text: 要绘制的内容,支持 ${} 语法
yesCallback: 点击确认后的回调
noCallback: 点击取消后的回调", + "!type": "fn(text: string, yesCallback?: fn(), noCallback?: fn())" + }, "fillPolygon": { "!doc": "在某个canvas上绘制一个多边形", "!type": "fn(name: string|CanvasRenderingContext2D, nodes?: [[number]], style?: string)" @@ -3448,7 +3470,7 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!type": "fn(name: string|CanvasRenderingContext2D, text: string, maxWidth: number, font?: ?) -> string" }, "clearMap": { - "!doc": "清空某个画布图层
name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名;还可以直接传画布的context本身。(下同)
如果name也可以是'all',若为all则为清空所有系统画布。", + "!doc": "清空某个画布图层
name为画布名,可以是系统画布之一,也可以是任意自定义动态创建的画布名;还可以直接传画布的context本身。
如果name也可以是'all',若为all则为清空所有系统画布。", "!url": "https://www.w3school.com.cn/tags/canvas_clearrect.asp", "!type": "fn(name: string|CanvasRenderingContext2D, x?: number, y?: number, width?: number, height?: number)" }, @@ -3549,6 +3571,22 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ }, "enemys": { "!doc": "怪物处理的相关函数", + "getEnemys": { + "!doc": "获得所有怪物原始数据的一个副本。
请使用core.material.enemys获得当前各项怪物属性。", + "!type": "fn()" + }, + "getSpecials": { + "!doc": "获得所有特殊属性的定义", + "!type": "fn() -> [[?]]" + }, + "getSpecialColor": { + "!doc": "获得某个怪物所有特殊属性的颜色", + "!type": "fn(enemy: string|enemy) -> [string]" + }, + "getSpecialFlag": { + "!doc": "获得某个怪物所有特殊属性的额外标记。

例如,1为全图性技能,需要进行遍历全图(光环/支援等)", + "!type": "fn(enemy: string|enemy) -> number" + }, "getSpecialHint": { "!doc": "获得某种敌人的某种特殊属性的介绍
例如:core.getSpecialHint('bat', 1) // '先攻:怪物首先攻击'
enemy: 敌人id或敌人对象,用于确定属性的具体数值,否则可选
special: 属性编号,可以是该敌人没有的属性
返回值:属性的介绍,以属性名加中文冒号开头", "!type": "fn(enemy: string|enemy, special: number) -> string" @@ -3561,10 +3599,26 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!doc": "判定某种特殊属性的有无
例如:core.hasSpecial('greenSlime', 1) // 判定绿头怪有无先攻属性
special: 敌人id或敌人对象或正整数数组或自然数
test: 待检查的属性编号
", "!type": "fn(special: number|[number]|string|number, test: number) -> bool" }, + "nextCriticals": { + "!doc": "获得某只敌人接下来的若干个临界及其减伤,算法基于useLoop开关选择回合法或二分法
例如:core.nextCriticals('greenSlime', 9, 0, 0, 'MT0') // 绿头怪接下来的9个临界
enemy: 敌人id或敌人对象
number: 要计算的临界数量,可选,默认为1
x: 敌人的横坐标,可选
y: 敌人的纵坐标,可选
floorId: 敌人所在的地图,可选
返回:两列的二维数组,每行表示一个临界及其减伤", + "!type": "fn(enemy: string|enemy, number?: number, x?: number, y?: number, floorId?: string) -> [[number]]" + }, + "getDefDamage": { + "!doc": "计算再加若干点防御能使某只敌人对主角的总伤害降低多少
例如:core.getDefDamage('greenSlime', 10, 0, 0, 'MT0') // 再加10点防御能使绿头怪的伤害降低多少
enemy: 敌人id或敌人对象
k: 假设主角增加的防御力,可选,默认为1
x: 敌人的横坐标,可选
y: 敌人的纵坐标,可选
floorId: 敌人所在的地图,可选", + "!type": "fn(enemy: string|enemy, k?: number, x?: number, y?: number, floorId?: string) -> number" + }, "canBattle": { "!doc": "判定主角当前能否打败某只敌人
例如:core.canBattle('greenSlime',0,0,'MT0') // 能否打败主塔0层左上角的绿头怪(假设有)
enemy: 敌人id或敌人对象
x: 敌人的横坐标,可选
y: 敌人的纵坐标,可选
floorId: 敌人所在的地图,可选
返回值:true表示可以打败,false表示无法打败", "!type": "fn(enemy: string|enemy, x?: number, y?: number, floorId?: string) -> bool" }, + "getEnemyInfo": { + "!doc": "获得怪物真实属性
hero: 可选,此时的勇士属性
此函数将会计算包括坚固、模仿、光环等若干效果,将同时被怪物手册和伤害计算调用", + "!type": "fn(enemy: string|enemy, hero?: ?, x?: number, y?: number, floorId?: string) -> {hp: number, atk: number, def: number, money: number, exp: number, special: [number], point: number, guards: [?]}" + }, + "getDamageInfo": { + "!doc": "获得战斗伤害信息
例如:core.getDamage('greenSlime',0,0,'MT0') // 绿头怪的总伤害
enemy: 敌人id或敌人对象
hero: 可选,此时的勇士属性
x: 敌人的横坐标,可选
y: 敌人的纵坐标,可选
floorId: 敌人所在的地图,可选
返回值:伤害计算信息,如果因为没有破防或无敌怪等其他原因无法战斗,则返回null", + "!type": "fn(enemy: string|enemy, hero?: ?, x?: number, y?: number, floorId?: string) -> {damage: number, per_damage: number, hero_per_damage: number, init_damage: number, mon_hp: number, mon_atk: number, mon_def: number, turn: number}" + }, "getDamage": { "!doc": "获得某只敌人对主角的总伤害
例如:core.getDamage('greenSlime',0,0,'MT0') // 绿头怪的总伤害
enemy: 敌人id或敌人对象
x: 敌人的横坐标,可选
y: 敌人的纵坐标,可选
floorId: 敌人所在的地图,可选
返回值:总伤害,如果因为没有破防或无敌怪等其他原因无法战斗,则返回null", "!type": "fn(enemy: string|enemy, x?: number, y?: number, floorId?: string) -> number" @@ -3572,6 +3626,14 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "getDamageString": { "!doc": "获得某只敌人的地图显伤,包括颜色
例如:core.getDamageString('greenSlime', 0, 0, 'MT0') // 绿头怪的地图显伤
enemy: 敌人id或敌人对象
x: 敌人的横坐标,可选
y: 敌人的纵坐标,可选
floorId: 敌人所在的地图,可选
返回值:damage: 表示伤害值或为'???',color: 形如'#RrGgBb'", "!type": "fn(enemy: string|enemy, x?: number, y?: number, floorId?: string) -> {color: string, damage: string}" + }, + "getCurrentEnemys": { + "!doc": "获得某张地图的敌人集合,用于手册绘制
例如:core.getCurrentEnemys('MT0') // 主塔0层的敌人集合
floorId: 地图id,可选
返回值:敌人集合,按伤害升序排列,支持多朝向怪合并", + "!type": "fn(floorId?: string) -> [enemy]" + }, + "hasEnemyLeft": { + "!doc": "检查某些楼层是否还有漏打的(某种)敌人
例如:core.hasEnemyLeft('greenSlime', ['sample0', 'sample1']) // 样板0层和1层是否有漏打的绿头怪
enemyId: 敌人id,可选,null表示任意敌人
floorId: 地图id或其数组,可选,不填为当前地图
返回值:地图中是否还存在该种敌人", + "!type": "fn(enemyId?: string, floorId?: string|[string]) -> bool" } }, "events": { @@ -3668,6 +3730,14 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!doc": "点击怪物手册时的打开操作", "!type": "fn(fromUserAction?: bool)" }, + "save": { + "!doc": "点击存档按钮时的打开操作", + "!type": "fn(fromUserAction?: bool)" + }, + "load": { + "!doc": "点击读档按钮时的打开操作", + "!type": "fn(fromUserAction?: bool)" + }, "getNextItem": { "!doc": "轻按获得面前的物品或周围唯一物品
noRoute: 若为true则不计入录像", "!type": "fn(noRoute?: bool)" @@ -3860,56 +3930,68 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!doc": "尝试使用一个道具
例如:core.tryUseItem('pickaxe'); // 尝试使用破墙镐
itemId: 道具id,其中敌人手册、传送器和飞行器会被特殊处理", "!type": "fn(itemId: string)" } + }, + "plugin": { + "!doc": "插件编写", + "drawLight": { + "!doc": "绘制一段灯光效果
name:必填,要绘制到的画布名;可以是一个系统画布,或者是个自定义画布;如果不存在则创建
color:可选,只能是一个0~1之间的数,为不透明度的值。不填则默认为0.9。
lights:可选,一个数组,定义了每个独立的灯光。其中每一项是三元组 [x,y,r] x和y分别为该灯光的横纵坐标,r为该灯光的半径。
lightDec:可选,0到1之间,光从多少百分比才开始衰减(在此范围内保持全亮),不设置默认为0。比如lightDec为0.5代表,每个灯光部分内圈50%的范围全亮,50%以后才开始快速衰减。
例如:core.plugin.drawLight('test', 0.2, [[25,11,46,0.1]]); // 创建一个test图层,不透明度0.2,其中在(25,11)点存在一个半径为46的灯光效果,灯光中心不透明度0.1。
core.plugin.drawLight('test2', 0.9, [[25,11,46],[105,121,88],[301,221,106]]); // 创建test2图层,且存在三个灯光效果,分别是中心(25,11)半径46,中心(105,121)半径88,中心(301,221)半径106。", + "!type": "fn(name: string|CanvasRenderingContext2D, color?: number, lights?: [[number]], lightDec?: number)" + }, + "openShop": { + "!doc": "打开一个全局商店
shopId: 要开启的商店ID
noRoute: 打开行为是否不计入录像", + "!type": "fn(shopId: string, noRoute?: bool)" + }, + "isShopVisited": { + "!doc": "某个全局商店是否被访问过", + "!type": "fn(id: string) -> bool" + }, + "listShopIds": { + "!doc": "列出所有应当显示的快捷商店列表", + "!type": "fn() -> [string]" + }, + "canOpenShop": { + "!doc": "当前能否打开某个商店", + "!type": "fn(id: string) -> bool" + }, + "setShopVisited": { + "!doc": "设置某个商店的访问状态", + "!type": "fn(id: string, visited?: bool)" + }, + "canUseQuickShop": { + "!doc": "当前能否使用某个快捷商店
如果返回一个字符串,则代表不能,返回的字符串作为不能的提示;返回null表示可以使用", + "!type": "fn(id: string) -> string" + }, + "removeMaps": { + "!doc": "删除某一些楼层;删除后不会存入存档,不可浏览地图也不可飞到。
fromId: 开始删除的楼层ID
toId: 删除到的楼层编号;可选,不填则视为fromId
例如:core.removeMaps(\"MT1\", \"MT300\") 删除MT1~MT300之间的全部层
core.removeMaps(\"MT10\") 只删除MT10层", + "!type": "fn(fromId: string, toId?: string)" + }, + "resumeMaps": { + "!doc": "恢复某一些被删除楼层。
fromId: 开始恢复的楼层ID
toId: 恢复到的楼层编号;可选,不填则视为fromId
例如:core.resumeMaps(\"MT1\", \"MT300\") 恢复MT1~MT300之间的全部层
core.resumeMaps(\"MT10\") 只删恢复MT10层", + "!type": "fn(fromId: string, toId?: string)" + }, + "openItemShop": { + "!doc": "打开一个道具商店", + "!type": "fn(itemShopId: string)" + } } }, + "lzw_encode": { + "!doc": "LZW压缩算法", + "!url": "https://gist.github.com/revolunet/843889", + "!type": "fn(s: string) -> string" + }, + "lzw_decode": { + "!doc": "LZW解压缩算法", + "!url": "https://gist.github.com/revolunet/843889", + "!type": "fn(s: string) -> string" + }, "hero": { "!type": "heroStatus", "!doc": "勇士信息,为 core.status.hero 的简写", }, "flags": { + "!type": "flag", "!doc": "游戏中用到的变量,为 core.status.hero.flags 的简写", - "hatred":{ - "!type": "number", - "!doc": "当前仇恨值" - }, - "poison":{ - "!type": "bool", - "!doc": "是否处于中毒状态" - }, - "weak":{ - "!type": "number", - "!doc": "是否处于衰弱状态" - }, - "curse":{ - "!type": "number", - "!doc": "是否处于诅咒状态" - }, - "no_zone": { - "!type": "bool", - "!doc": "无视领域伤害" - }, - "no_repulse": { - "!type": "bool", - "!doc": "无视阻击伤害" - }, - "no_lasel": { - "!type": "bool", - "!doc": "无视激光伤害" - }, - "no_ambush": { - "!type": "bool", - "!doc": "无视捕捉" - }, - "__bgm__": { - "!type": "string", - "!doc": "背景音乐" - }, - "__weather__": { - "!doc": "天气" - }, - "__color__": { - "!doc": "色调" - }, } } ]; \ No newline at end of file diff --git a/_server/editor_multi.js b/_server/editor_multi.js index f9fe4389..c50d789d 100644 --- a/_server/editor_multi.js +++ b/_server/editor_multi.js @@ -8,6 +8,7 @@ editor_multi = function () { "Ctrl-/": function (cm) { cm.toggleComment(); }, "Ctrl-B": function (cm) { ternServer.jumpToDef(cm); }, "Ctrl-Q": function(cm) { ternServer.rename(cm); }, + "Cmd-F": CodeMirror.commands.findPersistent, "Ctrl-F": CodeMirror.commands.findPersistent, "Ctrl-R": CodeMirror.commands.replaceAll, "Ctrl-D": function(cm){ cm.foldCode(cm.getCursor()); }, @@ -271,8 +272,11 @@ editor_multi = function () { editor_multi.isString = false; editor_multi.lintAutocomplete = false; if (args.lint === true) editor_multi.lintAutocomplete = true; + if ((!input.value || input.value == 'null') && args.template) + input.value = '"' + args.template + '"'; if ((!input.value || input.value == 'null') && editor_mode.mode == 'plugins') input.value = '"function () {\\n\\t// 在此增加新插件\\n\\t\\n}"'; + // if ((!input.value || input.value == 'null') && args) if (input.value.slice(0, 1) === '"' || args.string) { editor_multi.isString = true; _setValue(JSON.parse(input.value) || ''); diff --git a/_server/editor_table.js b/_server/editor_table.js index a4d63bff..f448f1cb 100644 --- a/_server/editor_table.js +++ b/_server/editor_table.js @@ -419,7 +419,7 @@ editor_table_wrapper = function (editor) { var cobj = JSON.parse(tr.children[1].getAttribute('cobj')); var input = tr.children[2].children[0].children[0]; if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event }); - if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string }); + if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string, template: cobj._template }); if (cobj._type === 'material') editor.table.selectMaterial(input, cobj); if (cobj._type === 'color') editor.table.selectColor(input); if (cobj._type === 'point') editor.table.selectPoint(input); @@ -451,7 +451,7 @@ editor_table_wrapper = function (editor) { editor_table.prototype.dblclickfunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) { if (editor_mode.doubleClickMode === 'change') { if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event }); - if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string }); + if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string, template: cobj._template }); if (cobj._type === 'material') editor.table.selectMaterial(input, cobj); if (cobj._type === 'color') editor.table.selectColor(input); if (cobj._type === 'point') editor.table.selectPoint(input); diff --git a/_server/table/comment.js b/_server/table/comment.js index c79ee185..1e56adfe 100644 --- a/_server/table/comment.js +++ b/_server/table/comment.js @@ -449,6 +449,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_string": true, "_lint": true, + "_template": "(function (timestamp) {\\n\\t// 在这里写楼层并行脚本,大约每16.6ms执行一次\\n\\t// timestamp: 从游戏开始到当前所经过的毫秒数。\\n\\t\\n})(timestamp);", "_docs": "并行处理脚本", "_data": "在该层楼时执行的并行脚本处理。\n可以在这里写上任意需要自动执行的脚本,比如打怪自动开门等。\n详见文档-事件-并行事件处理。" }, diff --git a/_server/table/plugins.comment.js b/_server/table/plugins.comment.js index b822dbc3..aadc3213 100644 --- a/_server/table/plugins.comment.js +++ b/_server/table/plugins.comment.js @@ -57,6 +57,7 @@ var plugins_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_leaf": true, "_type": "textarea", "_range": "typeof(thiseval)=='string' || thiseval==null", + "_template": "function () {\\n\\t// 在此增加新插件\\n\\t\\n}", "_data": "自定义插件" } } diff --git a/libs/events.js b/libs/events.js index a9093243..2a5d873f 100644 --- a/libs/events.js +++ b/libs/events.js @@ -2626,11 +2626,6 @@ events.prototype._setValue_setGlobal = function (name, value) { core.setGlobal(name.substring(7), value); } -////// 数值增减 ////// -events.prototype.addValue = function (name, value, prefix) { - this.setValue(name, '+=', value, prefix); -} - ////// 设置一个怪物属性 ////// events.prototype.setEnemy = function (id, name, value, prefix) { if (!core.hasFlag('enemyInfo')) { diff --git a/project/plugins.js b/project/plugins.js index 91596be0..b12e864e 100644 --- a/project/plugins.js +++ b/project/plugins.js @@ -565,7 +565,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = var bigFont = core.ui._buildFont(20, false), middleFont = core.ui._buildFont(18, false); - this.drawItemShop = function () { + this._drawItemShop = function () { // 绘制道具商店 // Step 1: 背景和固定的几个文字 @@ -820,7 +820,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = } } - this.performItemShopAction = function () { + this._performItemShopAction = function () { if (flags.type == 0) return this._performItemShopKeyBoard(flags.keycode); else return this._performItemShopClick(flags.px, flags.py); } @@ -839,9 +839,9 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = "type": "while", "condition": "true", "data": [ - { "type": "function", "function": "function () { core.drawItemShop(); }" }, + { "type": "function", "function": "function () { core.plugin._drawItemShop(); }" }, { "type": "wait" }, - { "type": "function", "function": "function() { core.performItemShopAction(); }" } + { "type": "function", "function": "function() { core.plugin._performItemShopAction(); }" } ] }, { diff --git a/runtime.d.ts b/runtime.d.ts index 0fb404a2..c8366901 100644 --- a/runtime.d.ts +++ b/runtime.d.ts @@ -1145,6 +1145,12 @@ declare class events { /** 飞往某一层 */ flyTo(toId?: string, callback?: () => boolean): void + /** 点击存档按钮时的打开操作 */ + save(fromUserAction?: boolean): void + + /** 点击读档按钮时的打开操作 */ + load(fromUserAction?: boolean): void + /** 点击装备栏时的打开操作 */ openEquipbox(fromUserAction?: boolean): void @@ -1352,7 +1358,7 @@ declare class enemys { */ hasEnemyLeft(enemyId?: string, floorId?: string | string[]): boolean - /** 获得所有怪物 */ + /** 获得所有怪物原始数据的一个副本 */ getEnemys(): any /** 获得所有特殊属性定义 */ @@ -1669,6 +1675,21 @@ declare class maps { */ drawAnimate(name: string, x: number, y: number, alignWindow: boolean, callback?: () => void): number + /** + * 播放跟随勇士的动画 + * @param name 动画名 + * @param callback 动画停止后的回调函数,可选 + * @returns 一个数字,可作为core.stopAnimate()的参数来立即停止播放(届时还可选择是否执行此次播放的回调函数) + */ + drawHeroAnimate(name: string, callback?: () => void): number + + /** + * 立刻停止一个动画播放 + * @param id 播放动画的编号,即drawAnimate或drawHeroAnimate返回值 + * @param doCallback 是否执行该动画的回调函数 + */ + stopAnimate(id: number, doCallback?: boolean): void + /** 加载某个楼层(从剧本或存档中) */ loadFloor(floorId?: string, map?: any): any @@ -2110,6 +2131,9 @@ declare class ui { /** 地图中间绘制一段文字 */ drawText(contents: string, callback?: () => any): void + /** 绘制一个确认框 */ + drawConfirmBox(text: string, yesCallback?: () => void, noCallback?: () => void): void + /** 绘制选择光标 */ drawWindowSelector(background: any, x: number, y: number, w: number, h: number): void