diff --git a/_docs/_sidebar.md b/_docs/_sidebar.md index a27b1f84..912b6100 100644 --- a/_docs/_sidebar.md +++ b/_docs/_sidebar.md @@ -1,7 +1,8 @@ - [快速上手](start) - [元件说明](element) -- [事件](event) +- [事件编辑](event) +- [事件指令](instruction) - [个性化](personalization) - [脚本](script) - [修改编辑器](editor) diff --git a/_docs/element.md b/_docs/element.md index a4eac405..4438b897 100644 --- a/_docs/element.md +++ b/_docs/element.md @@ -1,350 +1,383 @@ # 元件说明 ?> 目前版本**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部分。 +4. `project\materials\enemy48.png`:32×48px的怪物,自带只有四只。您可以随意修改它们的任何属性。 +5. `project\materials\npcs.png`:32×32px的NPC,如老人、商人、小偷、公主、仙子、木牌、魔龙和章鱼的其他8块,您可以随意修改它们的任何属性。 +6. `project\materials\npc48.png`:32×48的NPC,自带只有样板0层的小姐姐,但您也可以用它来制作32×48px的门。 +7. `project\autotiles`:自动元件,会随着在地图上的连续摆放而自动采取适当的绘制方式。 +8. `project\tilesets`:额外素材,用来突破其他素材合计不得超过1000个的限制。您可以在这个区域拖动来批量框选,再在地图区单击成片绘制或拖动平铺。 -请打开样板0层 `sample0.js` 进行参照对比。 +您可以随时使用`core.getBlockCls(x, y, floorId, showDisable)`这一API来获取游戏中某个位置的图块类别,其中自动元件和额外素材会分别返回“autotile”和“tileset”,其他的则会返回所在的图片文件名(不含后缀)。 +## 地图编辑(快捷键Z) +![image](img/v2.7/editor.png)如图所示,您可以在此对地图进行清空或删除操作,也可以新建或批量新建任意宽高的空白地图。其中“导出并复制地图”是指显示出左侧的矩阵并复制(一般用来跨塔复制地图),您也可以直接改动其中的数字,再点击“从框中导入地图”就能将改动的结果同步到地图上。下面的“楼层ID、中文名、状态栏名”分别对应楼层属性(快捷键V)的floorId、title和name,其中floorId也作为文件名(不能使用中文),title会显示在楼传界面和楼层切换黑屏,name也允许使用中文。 +## 图块属性(快捷键C) +![image](img/v2.7/mapsC.png) +如上图,除怪物和道具外,所有素材的图块属性都定义在`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. 图块名称:怪物在手册中、道具在道具栏中、其他图块在剧情对话中的默认名称,可以随意修改。但原则上不推荐不同的怪物和道具有重复的名称,否则会影响事件编辑器的中文替换功能。 -![生成地图](./img/sample0.png) +在讲解其他属性之前,这里简单介绍一下素材的注册机制。 -## 道具 -样板自带的所有道具在样板0层中已全部给出。当你在样板0层中拿到某个宝物时会有提示,这里不再赘述,详见拿到该道具的说明。 +除自动元件和额外素材外,其余图块只有在注册后才拥有上面所说的ID和数字。 -大多数宝物都有默认的效果,屠龙匕首暂未定义,如有自己的需求可参见[自定义道具效果](personalization#自定义道具效果)。 +未注册的图块则只有“索引”,索引为n表示该图块在图片的第(n+1)行, -拿到道具后将触发`afterGetItem`事件(从V2.7起,`afterGetItem` 脚本提供了一个参数表示该道具是否是通过轻按捡到的,对应的事件也允许在轻按时不予触发),有关事件的详细介绍请参见[事件](event)。 +ID和索引的对应关系定义在project\icons.js中。 -如需修改某个道具的效果,在不同区域宝石数据发生变化等问题,请参见[自定义道具效果](personalization#自定义道具效果)的说明。 -
**有关轻按,在全塔属性的系统开关中有定义。如果勾选了 `enableGentleClick` ,则鼠标(触摸屏)通过双击勇士,键盘通过空格,手机通过虚拟数字键 7 可达到轻按效果,即不移动而获得周围物品。** -## 装备 -如果需要让剑盾等变成装备,可以直接在它们的图块属性中把 `cls` 一项改为 `equips` 。
-从V2.4.1开始,HTML5魔塔样板终于拥有了属于自己的装备页面。 +尝试用未注册的图块(如道具一列中的某些魔杖和飞羽,或者利用便捷PS工具新追加的图块)在地图上绘制,就会出现红色的问号方框。 -### 装备栏的设置,装备类型 +此时请在数据区手动注册此图块,只需填写一个新ID和数字(1000以内)即可。 -在全塔属性中,有一个`equipName`项,其定义了本塔的所有可装备的装备栏。 -
其需要是一个长度为正数且不大于 6 ( 15×15 样板为不大于 8 )的一维数组,其中每一项为装备栏的名称,**建议是两个汉字**。
-例如下面这种写法就是定义了四个装备孔,名称分别为武器、防御、首饰和魔杖。 +也可以点击“自动注册”按钮批量注册该图片的所有未注册素材,自动注册出的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层使用的小姐姐。 + +### 道具属性 +样板自带的道具都在样板0层摆好了,您可以直接进入游戏捡起它们,就会看到该道具的注意事项,这里不再赘述。 +1. 道具类别:虽然和图块类别的英文缩写都是cls,但有本质区别,请注意区分。道具的图块类别都是items,而道具类别分为以下几种: + 1. items:是的你没看错,又是items这个词,请注意和图块类别的items相区分。它表示即捡即用类不进背包的道具,如四种血瓶、三种宝石等。这类道具需要用到的其他属性有“即捡即用效果”、“即捡即用提示”、“碰触或使用事件”。 + 2. tools:进背包的消耗类道具,如钥匙和解药瓶、便携式血瓶蓝瓶(生命魔杖)、破震炸飞和跳鞋等。这类道具需要用到的其他属性有“道具描述”、“不显示在道具栏”、“回放不绘制道具栏”、“碰触或使用事件”、“使用效果”、“能否使用”。 + 3. constants:进背包的永久道具(每件在背包的数量要么为1要么为0),如手册、楼传、幸运金币、十字架、护符、二倍斩等,这类道具需要用到的其他属性和tools一致。 + 4. 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为此道具的基础效果(如四种血瓶和三种宝石的基础效果定义在了全塔属性中),而最后的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. 手册中属性值的修正:(按照结算顺序)模仿、坚固、光环,修正后的属性也将被用于战斗,详见“脚本编辑——怪物真实属性”。 + 2. 战损的修正:这类最多,先攻、魔攻、连击(次数为n)、破甲(比例为defValue)、反击(比例为atkValue,回合数为勇士的攻击回合数)、净化(倍数为n,1表示单纯无视护盾)、吸血(比例为value,是否加到自身为add)、仇恨(每场战斗的仇恨增值由全塔属性指定)、无敌、固伤(数值为damage)、支援。其中又以仇恨和固伤不能被护盾直接抵消而和无敌较为特殊,详见“脚本编辑——战斗伤害信息”。 + 3. 战后的影响:中毒、衰弱、诅咒、仇恨(的累加和减半)、自爆、退化(扣减值分别为atkValue和defValue)、重生,详见“脚本编辑——战后脚本”和“公共事件——毒衰咒处理”。 + 4. 阻激夹域捕:即对主角行走的妨害,详见“脚本编辑——阻激夹域伤害”,该函数也负责了血网(图块ID为lavaNet,请勿修改)的伤害。 + +阻激域的伤害都为value且在夹击之前结算,领域的形状和半径与光环一致。 + +如果需要更复杂的形状(如米字形激光),请自行研究该函数。 + +请勿给同一种怪物设置阻击和捕捉,否则其阻击只会变得类似固伤。 + +可以看到,怪物属性中有很多值是彼此互相冲突的。请自行注意,比如分散给各项而不要都吊死在三个value上。最后介绍一些和怪物相关的API: ``` js -"equipName": ["武器","防具","首饰","魔杖"] + core.status.hero.flags.no_repulse = true; // 禁用阻击,包括伤害和后退效果 + core.status.hero.flags.no_laser = true; // 禁用激光 + core.status.hero.flags.no_betweenAttack = true; // 禁用夹击 + core.status.hero.flags.no_zone = true; // 禁用领域 + core.status.hero.flags.no_ambush = true; // 禁用捕捉 + core.getItem('amulet'); // 禁用血网等路障 + core.setEnemy('greenSlime', 'name', '绿史莱姆'); // 设置怪物属性,并计入存档 + core.getDamageString(enemy, x, y, floorId); // 获取某只怪的地图显伤字符串和颜色 + core.getCurrentEnemys(floorId); // 获取某层楼的(映射后)怪物列表,按战损递增排列 + core.hasEnemyLeft(enemyId, floorId); // 漏怪检测,两个参数都允许使用一维数组 + core.hasSpecial(src, n); // 检测src是否含有编号为n的特殊属性,src分为以下几种情况: ``` +如果src为一个数组,检查n是否在其中。为一个数字,检查是否和n全等; -这么定义好后,装备类型即为每个装备孔的索引(从0开始)。 +为字符串,视为怪物ID去检查。为对象,将其special域作为src递归检查。 -即,武器的装备类型是0,防御的装备类型是1,首饰的装备类型是2,魔杖的装备类型是3。 +如果您想在数据区的表格中追加新的属性项,或修改已有项的格式、范围和长短注释,请点击数据区顶部的“配置表格”按钮,并参照已有的项去追加和修改,具体可查阅@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层)。值得一提的是,很多事件也以颜色作为参数,这些都是可以使用取色器调色的。 -如果要将一个道具设置为装备,首先需要将其`cls`设为`equips`。 + 与RPG Maker不同,HTML5 canvas的色调合成公式是“此值×不透明度 + + 原值×(1$-$不透明度)”,所以即使给此项的红绿蓝填写相等的值也无法实现完美的灰色。如有需求,请使用[插件库](http://h5mota.com/plugins)的“仿RM光照”。 +12. 天气:一行两列的数组,第一项为字符串“rain”、“snow”或“fog”,第二项为不大于10的正整数,分别表示1—10级的雨天(见样板的主塔40层)、雪天(由大小不一的白色实心圆组成,详见样板1层)和雾天(由project\\materials\\fog.png放大后随时间加入不规则扰动得到)。 -然后在图块属性的`equip`一项中设置装备的具体属性。从V2.7起,该项通过事件编辑器编辑。分为以下几项: -1. 类型:自然数或字符串常量,和前面的 `equipName` 对应,填字符串一般是因为 `equipName` 中有重复项(比如可以装备两件饰品什么的)。 -2. 普攻动画:一个已注册的 `.animate` 文件名(这里不再写后缀),只对第一个装备位才有效。具体可参见[动画和天气系统](#动画和天气系统)。 -3. 数值提升项:若干个键值对,表示该装备增加属性的常数值(支持负数,会影响 `core.getStatus()` 的结果,可以用 `core.getEquippedStatus()` 来获取),7个常用属性可以通过下拉框选取,自定义的新属性也可以手动输入。 -4. 百分比提升项:若干个键值对,表示该装备增加属性的百分比(支持负数,会影响 `core.getRealStatus()` 的结果,可以用 `core.getBuff()` 来获取。最终的状态栏属性向下取整,百分比之间用加法叠加,且晚于常数结算),修改方法同上,精确到千分之一。 -### 检测是否存在装备 + 色调层在天气层上方、UI层下方(如不透明色调会遮盖天气,浏览地图看不到色调),关于图层的详细说明,参见“个性化” +13. 背景音乐:如题,当在游戏中触发楼层切换时(包括读档),如果 + `core.status.hero.flags.__color__、__weather__、__bgm__`没有值,游戏当时的画面色调、天气、背景音乐就会变为楼层属性中的这三个设置项,详见“脚本编辑——切换楼层中”。 +14. 宝石血瓶效果:如题,必须填写且必须为非负数。此项的用法为core.status.thisMap.ratio,请参考四种血瓶和三种宝石的捡拾效果。 -可以使用`core.hasEquip(itemId)`来检测是否装上某个装备。 + 您还可以将其用于其他各种场合作为系数,如血网的伤害、中毒后每步的损血等。 +15. 楼层贴图:至此我们会发现,图块只有32×32px和32×48px两种尺寸,且后者只能画在事件层,每个图块最多只能有4帧。 -使用`core.hasItem(itemId)`来检测是否存在一个未装上的装备。 +所以您可以在npcs.png中看到魔龙和章鱼被大卸八块,使用起来非常不方便。 -使用`core.getEquip(equipType)`来获得某个装备类型的当前装备。 +所幸样板提供了“楼层贴图”,该项允许您使用任何尺寸、任何帧数的素材, -更多相关API详见[附录:API列表](api)。 +唯一的缺点是不支持伸缩、移动跳跃和淡入淡出效果。 -### 多重装备 +点击“编辑”按钮进入事件编辑器,每张图片的写法为(可从入口方块拖出,然后双击预览第一帧的效果): +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的整数,就会把上述裁剪得到的结果再从左到右等分为若干份,并在实际绘制时从左到右逐帧(可能还带有翻转)循环绘制,每帧的持续时间和其他图块一致。 -从V2.5.4开始,允许支持多重装备,即有若干的装备可共用若干的格子(例如永不复还那样)。 +总之,每张贴图是按照“裁剪”—“左右等分”—“逐帧翻转”的顺序得到的。 -要实现这一点,上面的写法有所改变。 -
在全塔属性中的`equipName`项写法不变,不过可以写重复的装备孔名称。(但仍然最多只能写 6 或 8 个) +贴图本身只具有观赏性,您仍然需要使用空气墙等手段去控制其绘制区域各个点的通行性。在使用贴图来表现魔龙和章鱼这类大型怪物时,可以预先注册两种一样属性的怪物。一种透明,另一种为缩小到32×32px且只有两到四帧的版本。将前者画在地图上,怪物属性的“手册映射ID”填后者,最后在该点的战后事件中隐藏贴图即可。最后附上贴图和图块绘制顺序的修改方法:(libs\maps.js) ``` js -"equipName": ["武器", "武器", "武器", "防具", "防具", "首饰"] + ////// 绘制背景层 ////// + maps.prototype.drawBg = function (floorId, ctx) { + var onMap = ctx == null; + if (onMap) { + ctx = core.canvas.bg; + core.clearMap(ctx); + } + this._drawBg_drawBackground(floorId, ctx); + // ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块 + this._drawFloorImages(floorId, ctx, 'bg'); + this._drawBgFgMap(floorId, ctx, 'bg', onMap); +} // 后绘制的覆盖先绘制的。 ``` +## 全塔属性(快捷键B) +全塔属性共分为四部分:文件注册、初始勇士、全局数值、系统开关,您可以随时折叠其中任何一个部分。 +![image](img/v2.7/firstDataB.png) +### 文件注册 +这部分基本上都是经由多选框半自动完成的,下面逐一讲解: +1. 楼层列表:project\floors文件夹中的文件名(不含后缀),此数组的顺序决定了楼传和上下楼器(fly、upFly、downFly)的顺序。 -然后对于某个装备,将其`type`(装备类型)写对应的装备孔名称即可。 + 如果您不慎将勇士的出生楼层注销了或不慎删除了某些楼层的js文件,导致编辑器页面打开后一片白屏,请手动打开project\data.js去小心地修改floorIds以和实际的文件名相匹配,并将出生楼层改为一个存在的楼层。 -这样写的话,则所有该名称的装备孔均可装上此装备。 + 其他更复杂的白屏请在控制台根据报错信息(安卓手机则使用ES文件浏览器查看日志)去小心地修改文件(如某个楼层文件有问题则可以注销它),如果难以独立解决,欢迎加QQ群959329661寻求帮助。 +2. 使用图片:project\images文件夹中的文件名(需要后缀,必须全英数),单击“编辑”按钮,编辑器会自动扫描文件系统中格式合适的图片(如jpg、png和gif)。 -当尝试装上此装备时,会取最小的一个空的装备孔进行装备。如果没有空闲的装备孔,则会提示“请先卸下装备”。 + 您可以预览并将需要的图片勾选。请注意,勇士的初始行走图必须在这里注册。另外,winskin.png只许替换为相同规格的图片而不要注销,否则道具商店插件无法正常绘制。 +3. 额外素材:project\tilesets中的文件名(需要后缀,只支持png)。 + 注册方法同上,最大的区别在于这个数组的顺序必须保持好。如果随意调换其中的顺序,或注销不在数组末尾的图片,就会导致地图上最终呈现的素材发生错位。因此,新勾选的图片总会被自动追加到数组的末尾。 -装备动画仍然会取第一个(装备类型为0)的装备的`animate`项,即使装备了多个有动画的武器。 + 比起常规素材,额外素材最大的好处有几点: + 1. 图片没有数量限制。常规素材的总数量最多只允许不到一千个,而额外素材每张图片上的图块数量最多允许一千个。 + 2. 查看和绘制更为方便。常规素材每个图块独占一行,每列为一帧,导致不方便观察,且用多个图块拼图必须逐图块绘制。额外素材都是静止的,所以每个图块只占一格,多个图块可以在准备素材时就直接以相邻的样子绘制在同一张图片上,绘制地图时直接从素材区拖动来批量框选,再在地图区单击成片绘制或拖动平铺。 + 3. 批量替换也更为方便。譬如您如果想制作形如“一场大战/天灾过后/多年以后,村庄/城镇化为了一片废墟”的效果,可以预先准备两张甚至更多张相同规格的额外素材图片,然后在适当的时候遍历某个/某些楼层的图块ID,将以“X1”开头的图块统一替换为“X2”开头等。发布单机版游戏时,您也可以提供多张相同规格的额外素材图片供玩家直接替换。当然,使用这类做法的话就没法再使用“额外素材合并”了。 -## 门 -样板自带6种门,黄蓝红绿铁花。前四种门需要有对应的钥匙打开,花门只能通过调用 `openDoor` 事件进行打开。铁门是否需要钥匙,由全塔属性的 `steelDoorWithoutKey` 开关控制,详见“万能铁门钥匙”道具的拾取效果。
-开门后可触发该点的 `afterOpenDoor` 事件,有关事件的详细介绍请参见[事件](event)。
-如果要新增自己的门(支持32×48尺寸),请参见[新增门和对应的钥匙](personalization#新增门和对应的钥匙)。 + 当您即将发布您的游戏时,可以使用“额外素材合并”工具将用到的额外素材图块重新拼成更少的图片,以减少游戏体积和加快在线游戏的加载。执行此操作后,额外素材的图块ID和数字(包括第一位)都将被打乱,因此请勿在制作中以任何方式直接引用其ID和数字。如确有此需求,请间接引用、等量代换,如“将$(x_1,y_1)$处的图块设置为和$(x_2,y_2)$处一样”、“判断$(x_3,y_3)$和$(x_4,y_4)$处的图块是否相同”。 +4. 使用动画:project\\animates文件夹中的文件名(不含后缀,请注意与`animates.png`相区分)。 -## 暗墙 -样板支持暗墙。要制作一个暗墙非常简单:在该点直接放一个普通墙壁,然后事件写“开门”,坐标为该点就行。 -``` json -// 该点画一个普通的墙壁,比如`yellowWall` + 要使用动画,您可以使用“RM动画导出”工具从RPG Maker XP + 1.03及其制作的游戏中导出动画,也可以用动画编辑器修改已有的动画或用图片新建。但这些办法都只适用于Windows系统,非Windows系统建议直接从我们的官网下载他人的作品取用其中的动画。 -// 在该点的事件events中: -[{"type": "openDoor"}] // 直接使用开门事件,坐标可忽略表示当前点 -``` -系统会自动调用animates中的开暗墙动画。样板自带如下ID支持以这种方式开门: -``` text -yellowDoor, blueDoor, redDoor, greenDoor, specialDoor, steelDoor, -yellowWall, blueWall, whiteWall + 动画不支持在编辑器中预览,Windows系统可以使用“动画编辑器”预览但没有音效。 + + RPG Maker的动画存储方式是将用到的图片独立存放,而所有动画的帧信息(包括第几帧该用什么音效,会闪烁整个画面或当前图块)会集结在同一个文件中。 + + 而我们的存储方式则不同,是对每个动画将其用到的各张图片直接以base64硬编码进同一个animate文件,每个动画为一个animate文件。 + + 这样做的缺点是如果多个动画使用了相同的图片那么图片会被重复存储,优点则是跨作品迁移动画更加方便。 + + animate文件为文本文件,文件末尾记录了动画的帧信息,文件开头则记录了动画的伸缩比和唯一音效(会和动画同时开播)。 + + 在导出动画时,会出现一个输入框并提示动画的唯一音效名。不管该文件名是什么语种,请直接点击下一步。音效文件会被尝试自动复制,随后您只需手动注册该动画和音效并将音效文件名改为全英数。如果复制失败,则需要您手动去该RPG + Maker XP 1.03项目的SE文件夹中将这个文件复制出来(所以刚才最好记一下这个名字),放在您的H5魔塔项目的project\sounds文件夹中并改名为全英数,然后手动注册该动画和音效。 + + 如果要查看或修改一个动画和音效的对应关系(比如从官网上别的作品扒来的动画),请直接在注册时预览并修改。 + + 动画的播放速度为20FPS,即每帧50毫秒。这里给出几个相关API: +``` js + core.drawAnimate(name, x, y, alignWindow, callback); + // 播放一个动画,name为不带后缀的动画文件名,x和y为播放的格子坐标。 + // alignWindow表示该坐标在大地图中是绝对坐标还是相对坐标,填true表示相对坐标。 + // 相对坐标模式下,坐标应填写为小于13或15的自然数,譬如对13×13样板来说, + // 填两个6就会强制播放在视野中心。 + // callback为动画播放完毕后(和音效无关)的回调函数,因为动画播放本身是异步的。 + core.drawHeroAnimate(name, callback); // 和上面类似,但该动画会跟随勇士移动。 + // 每场战斗后,都会根据怪物坐标尝试用前者播放普攻动画。若坐标不存在 + // (天降强制战斗),则会尝试用后者播放。看上去就像勇士在打自己,请自行注意。 ``` + 详见“脚本编辑——战后脚本”。上述两个函数都会返回一个每次不同的正整数id,您可以使用`core.stopAnimate(id, doCallback)`函数来立即停止一个正在播放的动画,其中doCallback为true表示停止时执行原动画的回调。 +1. 使用音乐:project\bgms文件夹中的文件名(需要后缀,默认只支持wav、mp3和ogg)。 -## 怪物 -样板自带的怪物列表参见 `project\enemys.js` 。其与 `images\enemys.png` 素材按顺序一一对应。
-如有自己的怪物素材需求请参见[自定义素材](personalization#自定义素材)的内容。 + 如果玩家使用的是手机且没有连接WiFi(iOS和部分浏览器无法获知网络状态,将始终视为流量党),那么背景音乐默认不会开启,可以在标题画面点击右下角的圆形按钮来开启。 -怪物可以有特殊属性,每个怪物可以有多个自定义属性。 + 发布到官网的作品还可以从远程加载背景音乐,您可以点击此链接试听和下载其他作品的背景音乐。是否启用远程加载、以及启用时远程加载的根目录,由main.js指定。因此从官网下载其他作品的离线版本后请先关闭远程加载功能,才能正常加载本地注册的音乐。 -怪物的特殊属性所对应的数字(special)在脚本编辑中的`getSpecials`中定义,请勿对已有的属性进行修改。 -
多属性可直接从图块属性勾选。怪物可以负伤,由全塔属性的系统开关 `enableNegativeDamage` 指定。
-打败怪物后可以进行加点操作。有关加点塔的制作可参见[加点事件](event#加点事件)。 -
如果全塔属性中的“显示经验值”未勾选,即不启用经验的话,怪物手册里将不显示怪物的经验值,打败怪物也不获得任何经验。
-拿到幸运金币后,打怪获得的金币将翻倍。如果怪物勾选了 `notBomb` ,则这个种类的怪物均不可被炸。
-N连击怪物的special是6,且我们可以为它定义n代表实际连击数。参见样板中剑王的写法。 -
吸血怪需要给怪物设置value,代表吸血的比例。可以给吸血怪勾选 `add` 来将吸血的数值加到自身上。
但这样做以后,红色的预估伤害往往带有误导性,这点还务请注意!
-中毒怪让勇士中毒后,每步扣减的生命值由全塔属性中的 `poisonDamage` 定义。
-衰弱怪让勇士衰弱后,攻防会下降一定比例或固定数值(直到衰弱状态解除恢复);由全塔属性中的 `weakValue` 定义。
-诅咒怪将让勇士陷入诅咒状态,诅咒状态下杀怪不获得金币和经验值。 -
领域怪需要需要给怪物设置 `value` ,代表领域伤害的数值。如果勇士生命值扣减到0,则直接死亡触发 `lose` 事件。
-领域是锯齿形状还是正方形由 `zoneSquare` 设定,如勾选则为正方形,不勾选则为锯齿形状。
-领域怪还可以设置`range`选项代表该领域怪的范围,不写则默认为1。 -
**将 `flags.no_zone` 设置为 `true` 可以免疫领域效果。**
-阻击怪同样需要设置value,代表阻击伤害的数值。如果勇士生命值扣减到0,则直接死亡触发lose事件。 -
**将`flags.no_repulse`设置为true可以免疫阻击效果(包括伤害和移动!)。**
-!> 阻击怪后退的地点不能有任何事件层图块,否则不会后退。另外它会无视可通行方向,请自行注意悬崖效果的影响!
-激光怪同样需要设置value,代表激光伤害的数值。 -
请注意如果吸血、领域、阻击、激光、生命光环中任何两个同时存在,则 `value` 会冲突。**因此请勿将吸血、领域、阻击、激光或生命光环放置在同一个怪物身上。退化和攻防光环、吸血加到自身和光环叠加同理!
** -**将 `flags.no_laser` 设置为 `true` 可以免疫激光效果。将 `flags.no_ambush` 设置为 `true` 可以免疫捕捉效果。**
-退化怪和光环怪需要设置'atkValue'和'defValue'表示退化或增幅的数值;也可以不设置默认为0。 -
**将`flags.no_betweenAttack`设置为true可以免疫夹击效果,在全塔属性中还有一个系统开关 `betweenAttackMax` 可以控制夹击伤害是否封顶至夹击怪的战斗伤害。**
-固伤怪则需要设置`damage`选项,代表战前扣血数值。 + 使用core.material.bgms可以查看所有的背景音乐,如果需要同时播放多个背景音乐并独立控制时刻和音量,请直接对它们使用play()方法并修改其currentTime(可读)和volume属性。 +2. 使用音效:project\sounds文件夹中的文件名(写法同上)。和动画不同, -如有额外需求,可参见[自定义怪物属性](personalization#自定义自定义怪物属性),里面讲了如何设置一个新的怪物属性。 + 音效的播放不支持回调,只支持提前停止,而且一停就会停止所有的。 -## 怪物和NPC的朝向问题 + 音效的音量是固定的,无法调节。此外,样板没有背景音效(bgs、bgv)的默认实现。如有需求,请使用并行脚本处理。 -从V2.5.2开始,对于人形怪物和NPC的朝向问题已经有着比较好的解决方式。 + 音乐和音效在使用多选框注册时都支持试听,您可以看到它们的总时长和已播时长(精确到秒),从而指定音乐的开播秒数或配合使用“等待n毫秒”事件或并行脚本处理。 +3. 使用字体:project\fonts文件夹中的文件名(只支持ttf格式,不写后缀)。 -首先明确一点的是,和RM不同,H5中即使是对同一个怪物/NPC的不同朝向,也需要分别将其各个朝向素材追加对应的图片上,并进行注册。 + 不建议给在线游戏版本添加中文字体,因为文件真的很大…… +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) -为了避免这种情况的发生,在怪物的属性中存在一个`displayIdInBook`项,**我们可以指定该项来控制每个怪物在怪物手册中中显示成的怪物。** +### 初始勇士 +1. 初始楼层、朝向和坐标:如题,请注意初始楼层必须在上述的“楼层列表”中。初始坐标一般通过右击地图上的空地快速绑定,但您也可以手动在这里填写负数或超出初始楼层宽高的值。然后使用“无视地形移动勇士”或“跳跃勇士”等改变勇士位置的事件指令,做出“勇士从地图外进入”的演出效果。 -举个例子,假设我现在有个怪物,其向下的行走图ID是`E300`,其向左的行走图ID是`E301`,向右的行走图ID是`E302`。分别对这几个怪物填写完全相同的怪物属性。 + 如需根据难度分歧或用户选项来改变它们,请在“开场剧情”中修改core.firstData.floorId和core.firstData.hero.loc +2. 行走图:如题,必须在“使用图片”中注册过。宽高必须为4的倍数,宽度至少为128px(即每帧32px)。高度不限,剧情对话中和状态栏中会尝试保持比例压缩到每帧32px宽。 -如果我在地图上同时绘制向下、向左和向右的该怪物,则确实能在地图上显示出来不同的朝向,但是在怪物手册中会同时显示这三种类型的怪物,观感较差。 + 在游戏中,勇士当前的行走图文件名用core.status.hero.flags.heroIcon表示(只读)。 +3. 帧动画:勾选此项后,勇士在剧情对话中(朝上视为朝下)和原地不动时会循环播放四帧踏步动画,一般用于长翅膀的勇士。 +4. 勇士名:如题,也会作为剧情对话中`\t[hero]`的默认标题。 +5. 初始等级:如果开启了自动进阶功能,请不要修改此项。 +6. 生命上限、魔力上限、初始生命/魔力/攻防/护盾/金经:如题。 -我们可以给`E301`和`E302`怪物属性中的`displayIdInBook`项填写为`"E300"`。 + 注意生命上限和金经需要在系统开关中勾选后才会启用,魔力上限填负数代表没有上限。 +7. 初始装备、游戏变量:建议留空(事件中的变量初始时都会视为0,脚本中也有办法做到)。 +8. 永久道具、消耗道具、初始拥有装备个数:点击“注释”按钮,按照提示进行修改。 +9. 标题事件:需要配合系统开关中勾选“标题开启事件化”来使用,可以在“开始游戏”、“读取存档”之余添加一些额外的功能。如成就系统、音像和回想鉴赏,但这并不是唯一的方法,请自行研究。 +10. 开场剧情:会在难度分歧事件之后执行,可以在这里设置各种变量的初始值、穿上初始拥有的装备、隐藏勇士和一些初始不希望显示的图层块、追加跟随者等。 +11. 全局商店:详见“QTE与全局商店”。 +12. 等级提升:需要配合系统开关中勾选“等级”、“经验”和“升级”来使用,每个等级分为以下几项: + 1. 需求:刷新状态栏时,如果勇士当前等级是此等级的前一级,且经验值大于等于此需求,就会触发升级。 -这样的话,在怪物手册中,所有的E301和E302均会被视为E300并进行合并。即使只有一只朝向左的怪物(E301),怪物手册仍然会按E300进行显示。 -
从而完美解决了同种怪物不同朝向在怪物手册的显示问题。此做法不兼容夹击属性,漏怪检测也以映射后的怪物为准。 -### NPC的朝向问题 + 因此如果您想设计“低难度初始等级较高”,请直接增加经验。 -和怪物不同的是,NPC朝向问题更复杂一点。 + 触发升级后会再次检查下一个等级,直到经验不足或等级已满。 -在NPC的图块属性中,存在一个`faceIds`的项目,可以用其来绑定一个图块所对应的其他朝向的图块ID。 + 所以您不必担心一次获得太多经验连续触发升级会出bug. -举个例子,假设我存在一个NPC,其向上的图块ID是N333,向下的图块ID是N334,向左的图块ID是N335,不存在向右的图块ID。 + 2. 称号:状态栏显示的等级默认是个正整数,会尝试替换为这里的称号(调用core.getLvName()函数),请注意控制字数。 + 3. 是否扣除经验:如果勾选了此项,则触发升级时经验值会扣除需求值。 + 4. 事件:触发升级时执行的事件,如全面提升属性。 -则可以在这几个图块属性中的`faceIds`中写:`{"up": "N333", "down": "N334", "left": "N335"}`。 -
当勇士从左边撞上此NPC后,将从该图块的图块属性中的 `faceIds` 中寻求 `left` 所对应的ID。 -如果存在定义(如N335),则会在触发对话事件前改变当前图块为N335,看起来就是在对话前进行了转向,面向勇士。
-对话中,`\t[this]` 效果的图像也会尝试选用该NPC的当前朝向(朝上不好看,会自动改为用朝下的)
-!> 请注意,在对话结束后朝向不会切换回来,因此如果有必要切换朝向请在事件结束前调用转变图块事件。 -
从v2.7起,也提供了“事件转向”指令来执行这种转变图块,从而省去了手动填写ID的不便。
-同理,使用移动事件让NPC在行走时,不同朝向的行走会自动调用`faceIds`中不同朝向的ID所对应的行走图,看起来就是在行走时也可以不断转向了。 +### 全局数值 +![image](img/v2.7/values&flagsB.png) +这个类型的数值会保存在core.values中,可以直接在游戏中修改。 +1. 血网伤害和中毒伤害:如题,如果不想用常数,请修改“脚本编辑”的“阻激夹域伤害”和“每步后操作”。 +2. 衰弱效果:填小于1的正数代表扣减的比例,否则为扣减的常数。 -从而,完美解决了NPC的朝向问题(碰触时面向勇士、行走时改变朝向)。 + 扣减和恢复的原理和装备相同,详见“公共事件——毒衰咒处理”、解衰药水和万能药水的使用效果。 +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个以内,否则竖屏可能塞不下。 -血网的伤害数值、中毒后每步伤害数值、衰弱时暂时攻防下降的数值,都在全塔属性的values内定义。 -
如果有个性化需求,可以自行修改路障的图块属性 `script`、脚本编辑“阻激夹域伤害、每步后操作”和公共事件“毒衰咒处理”。
-路障同样会尽量被自动寻路绕过(目前,后三种路障在已主角附加对应debuff的情况下依然会绕过)。 -
有关楼梯和传送门,必须在该点的 `changeFloor` 事件里指定传送点的目标。![生成地图](./img/changeFloorBlockly.png)
-楼层ID指定的是目标楼层的唯一标识符(ID),也可以在第一个下拉框中选择“前一楼”和“后一楼”。
-第二个下拉框可以选择传送到哪个楼梯,或选择三种对称位置,或显式指定坐标(比如目标楼层有多个楼梯时)。
-“朝向”为勇士上下楼后面对的方向(从V2.7起,支持三种相对转向),不填则不改变。“动画时间”为上下楼的黑屏时间,不填则使用玩家设定值。
“穿透性”表示鼠标或触屏寻路时勇士能否穿过此传送点,在转不开身的狭窄区域建议设为可穿透。
-**从v2.1.1开始,楼层属性中提供了 `upFloor` 和 `downFloor` 两项。如果设置此项(比如`"upFloor": [2,3]`,从V2.7起支持地图选点法设置),则写传送到哪个楼梯或者楼传器的落点将用此点来替换楼梯位置(即类似于RMXP中的上箭头)。** -## 剧情文本控制与对话框效果 + 多说一句,这些项的图标都在`project\materials\icons.png`中。 -在写剧情文本时,可以: + 该文件夹下也提供了一个`icons_old.png`可供替换。 -- 使用`\t[...]`来给文字加上标题和图标。如`\t[老人,man]`。 -- 使用`\b[...]`来制作对话框效果,如`\b[up,3,2]`。 -- 使用`\r[...]`来动态修改局部文本的颜色,如`\r[red]`。 -- 使用`${}`来计算一个表达式的值,如`${status:atk+status:def}`。 -- 使用`\f[...]`来同时插入一张立绘图,如`\f[1.png,100,200]`。 -- 使用`\\i[...]`来在对话框中绘制一个图标,如`\\i[fly]`。 -- 使用`\\c[...]`来修改字体大小,如`\\c[16]`。 -- 使用`\\d`来加粗或者取消粗体。 -- 使用`\\e`来加斜体或取消斜体。 -- 使用`\\z[...]`来添加打字中的暂停效果。 + “血限”、“金币”和“经验”必须勾选才会启用(指会处理生命溢出、金经会显示在手册、打怪也会掉落), -从V2.5.2开始,也允许绘制一张头像图在对话框中,只要通过`\t[1.png]`或`\t[标题,1.png]`的写法。 + 必须勾选“升级”才会启用自动进阶,“升级扣除模式”如果不勾选就会同时显示下一级的需求(NEXT)和当前经验(EXP,如果勾选了的话),否则会只显示两者的差(依然用NEXT图标)。 -**使用`\\i,\\c,\\d,\\e,\\z`时请注意:在事件块中,允许只写一个反斜杠`\`,系统会自动转义成`\\`;但是在脚本中必须两个反斜杠都写上!** + 如果同时勾选了“钥匙”和“绿钥”,则每种钥匙的数量都会被缩小尺寸显示,因此如非必要请不要勾选“绿钥”。 +2. 楼传需在楼梯边:如果勾选了此项,则只有勇士在楼梯旁边(如果开启了下述的平面模式则还包括四种三帧箭头旁边)时才允许使用楼传。 -详细信息请参见[剧情文本控制](event#text:显示一段文字(剧情))中的说明。 + 请注意,此项是在楼传道具使用条件之外额外进行的判定,目的是给出不同的提示信息。因此如果您要修改楼传的使用条件(指总的使用条件,具体能否飞到某层的条件则在“脚本编辑——楼层飞行”),则可能需要一并取消此勾选。 +3. 楼传开平面模式:如果勾选了此项,则勇士在使用楼传飞往某层时会落在上次离开该层的位置。此外,上述“在楼梯边”也会包括“在四种三帧箭头旁边”。 +4. 铁门不消耗钥匙:如果勾选了此项,则铁门无需钥匙也能撞开。 -从V2.5.2开始,可以用一张WindowSkin图片作为对话框的背景皮肤。 -
使用时,需要将图片放在images目录下,并在全塔属性中予以注册。已有的 `winskin.png` 请勿删除,否则会影响道具商店插件的使用。
-可以使用[设置剧情文本的属性](setText:设置剧情文本的属性)事件将对话框背景设置为需要的皮肤。 + 勾选后,您可以将铁门的开门动画ps为墙壁状,来批量制作暗道。 -!> 关于对话框效果请注意,现在是采用WindowSkin的右下角两个32x32的图片作为对话框尖角进行绘制。因此请尽量使用群文件或网盘的常用素材中给出的WindowSkin素材(均已进行对话框适配)。如需使用来自第三方的WindowSkin素材,请自行注意对话框的尖角问题,或弃用`\b`效果。 + 直接把三色墙等的图块的“触发器”改为openDoor也是可以的。 +5. 首次道具进行提示:勾选后,首次捡到非即捡即用类道具都会弹窗提示(晚于afterGetItem事件被执行)。 +6. 状态栏装备按钮:勾选后,状态栏的楼传按钮会变为装备栏按钮,但玩家仍然可以双击道具栏来呼出装备栏。 +7. 加点和负伤:前者勾选后怪物的加点值会在“脚本编辑——战后脚本”中作为参数core.status.hero.flags.arg1被传递给“公共事件——加点事件”。 -另外一点是,V2.5.2以后,对话框`\b`可以根据文字长度来自动控制文本框宽度,其基本控制原理如下: + 后者勾选后,战斗结束时如果勇士的护盾没有完全被打破,则剩余的护盾值会加到其生命上。所以勾选此项后,护盾可以这样“间接”抵消掉仇恨伤害和固伤。 -- 如果用户存在手动换行`\n`,则选取**最长的一段话**作为文本框宽度。 -- 如果用户不存在手动换行,则会将文本框宽度调整为X行半的最佳宽度。 -- 文本框宽度存在上下界,最终宽度一定会控制在该范围内。 -- 从V2.7开始,自动换行增加了标点禁则,成对标点的左部不会出现在行尾,右部和不成对标点不会出现在行首。 +8. 夹击不超伤害值:勾选此项后,夹击伤害将封顶至夹击怪的战损。 -该自动调整仅对`\b`的对话框效果有效。非对话框仍然会绘制整个界面的宽度。 + 同时被四只怪夹击时,取两个战损中较小的。 +9. 二分临界:我们知道,打败怪物所需的回合数,取决于勇士的攻击减去怪物的防御。这个值并非每增大1都能使回合数减少,因而有了“临界”的说法,即“再至少增加多少攻击力,才能减少回合数”。然而,当您修改“脚本编辑——战斗伤害信息”函数后,攻击力的增加可能反而导致回合数也增加,于是临界值计算出错。您可以勾选此开关来修复,代价是游戏可能较卡,请自行权衡。 +10. 标题开启事件化:勾选此项后,标题画面将改为执行前述的“标题事件”,请自行研究。 +11. 开启自绘状态栏:勾选此项后,状态栏将改用“脚本编辑——自绘状态栏”来绘制,同时“脚本编辑——点击状态栏”也将启用,请自行研究。 +12. 三个显伤:略,玩家依然可以在设置菜单中开关之。 +13. 允许轻按:勾选此项后,玩家可以按下空格/大键盘数字7/双击勇士来拾取相邻的唯一道具,或面前的道具。 +14. 允许穿透楼梯:在狭窄的区域拦路放置一个可通行的“楼层转换”事件时(图块左下角出现绿色标记),玩家可能希望勇士能直接走过去。您可以逐个去设置其能否被这样走过,或者让其依据本勾选项。 -## 大地图 + 值得注意的是,当玩家从允许穿透的楼梯向一个不可走的方向(如旁边是墙,或不勾选下一个开关时的致命领域)手动寻路时,可以停在楼梯上(进而再轻按拾取周围物品等)。不建议您利用这类极端情况去迫使玩家进行非常规操作,毕竟穿透楼梯和不能踏入致命领域的本意是方便玩家,不是么? +15. 允许将死领域:“脚本编辑——阻激夹域伤害”会将地图中每个点的阻激夹域和血网伤害加总,如果不勾选此开关,则当勇士生命小于等于相邻空格子的总伤害(没有则视为0)时,勇士无法走向该格子。 -从V2.4开始,H5魔塔开始支持大地图。 + 值得注意的是,这种判定方式并没有考虑“走这一步后、结算该点伤害前”可能的加血或该点伤害变化,因此您可能需要根据“脚本编辑——每步后操作”去修改core.canMoveHero()函数。 +16. 允许瞬移:若不勾选此开关,将全程禁用瞬移功能。一般只建议在需要的楼层逐层勾选禁止瞬移(主要为了用自动事件去监听勇士的坐标),详见`core.maps._canMoveDirectly_checkGlobal()`函数。 +17. 伤害禁用商店:勾选此项后,每当勇士踩到阻激夹域和血网并受到伤害时,所有全局商店都将被禁用,需要重新去启用(譬如勇士去撞击该商店的实体NPC)。详见`core.control._checkBlock_disableQuickShop()`函数。 +18. 虚化前景层:前景层会遮挡事件层,这对魔塔来说有时可能不太友好。 -大地图在创建时可以指定宽高,要求**宽和高都不得小于13(15x15版本则是不小于15),且宽高之积不超过1000**。 -
您也可以在楼层属性的最下面修改宽高,还可以指定偏移量。 -## 动画和天气系统 - -现在我们的H5魔塔支持播放动画,也支持天气系统了。 -
要播放动画,你可以先使用“RM动画导出器”将 `RPG Maker XP 1.03` 的动画导出,放在animates目录下,然后在全塔属性的animates中定义。 -``` json -// 在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名 -// 动画必须放在animates目录下;文件名不能使用中文,不能带空格或特殊字符 -"animates": ["hand", "sword", "zone", "yongchang", "thunder"] -``` -目前不支持用浏览器预览动画,Windows系统请使用“动画编辑器”预览,然而预览不会播放音效。
-!> 动画必须是animate格式,名称不能使用中文,不能带空格或特殊字符。 - -导出动画时可能会进行一些压缩(譬如把本来是128×128尺寸的动画压缩为64×64,播放时再临时放大)以节省流量,因此清晰度可能不如原版。 - -从2.3.2开始,动画可以同时导出所用的音效。**如果导出音效,请确保将所用到的音效复制到了`sounds`目录下,并且在全塔属性中注册过。** -
确切地说,动画文件中记录着第几帧该用什么音效的文件名,您可以用记事本等文本编辑器打开动画文件并手动修改用到的音效文件名(原本可能是中文甚至日文),以和实际的文件名相匹配 - -动画播放时,是按照每秒20帧的速度(即50ms/帧)。 - -定义完毕后,我们可以调用`animate`事件来播放该动画,有关事件的详细介绍请参见[事件](event)。 - -!> 播放录像时,将默认忽略所有动画。 -
目前天气系统支持雨、雪和雾三种天气。在每层楼的楼层属性中存在一个weather选项,表示该层楼的默认天气。 -``` json -// 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain","snow"或"fog"代表雨雪雾,第二项为1-10之间的数代表强度。 -"weather": ["snow",5] -``` - -我们也可以使用`setWeather`事件来设置当前天气,有关事件的详细介绍请参见[事件](event)。 - -## 背景音乐 -样板支持BGM和SE的播放。要播放音乐和音效,你需要将对应的文件放在sounds目录下,然后在全塔属性中进行定义 -``` json -// 在此存放所有的bgm,和文件名一致。 -// 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 -"bgms": ["bgm.mp3"] - -// 在此存放所有的SE,和文件名一致 -"sounds": ["floor.mp3", "attack.mp3", "door.mp3", "item.mp3", "zone.mp3"] -``` - -!> 音频名不能使用中文,不能带空格或特殊字符。 -
目前BGM支持主流的音乐格式,有 `wav, mp3, ogg`,不支持 `mid` 格式的播放。
`iOS` 系统对 `ogg` 的支持性较差,但 `ogg` 比 `mp3` 体积小,请注意权衡。
-定义完毕后,我们可以调用`playBgm`/`playSound`事件来播放对应的音乐/音效,有关事件的详细介绍请参见[事件](event)。 - -**另外,考虑到用户的流量问题,将遵循如下规则:** - -- **如果用户当前使用的电脑,则默认开启音乐效果,并播放默认BGM** -- **如果用户当前使用的手机,且处于Wifi状态,则默认开启音乐效果,并播放默认BGM** -- **其他情况,将默认关闭音乐效果,只有在用户在菜单栏中点击“音乐开关”后才会播放音乐** - -!> iOS平台以及部分浏览器不支持获得当前网络状态,此时即使在使用Wifi也必须要用户点击“音乐开关”才能播放音乐。 - -从V2.5.3开始,可以使用`loadBgm`事件来预加载一个bgm,这样到播放时无需等待,直接播放。 - -同时BGM将使用LRU算法增加缓存机制。默认最多缓存4个BGM(在core.js的musicStatus.cachedBgmCount控制)。 -
系统会自动释放最久未使用的BGM。也可以使用 `freeBgm` 事件来手动释放一个无需再用的bgm -## 录像 - -HTML5魔塔一大亮点就是存在录像系统,可以很方便进行录像回放。 - -当你在游戏的过程中,随着你的操作,录像也会被依次记录。游戏结束后将提示是否下载录像,上传成绩时也会上传你的录像信息。 - -在菜单栏-同步存档中,可以直接对当前录像进行下载。 - -!> 录像记录的是你当前的路线(本质上是模拟键盘操作),是一个纯文本文件,占用空间很小! - -录像的回放主要有两种方式: - -1. 保存成的录像文件(.h5route文件):在标题界面点录像回放,再选择文件即可。 -2. 游戏过程中时的当前录像:随时按R可以进行回放;手机端则可调出虚拟键盘,再按R。 - -录像播放过程中,可以进行如下操作: - -- **步进:** 暂停状态下,按 `N` 键可以单步执行录像,常用于调试。 -- **暂停/播放:** 按空格可以随时暂停或播放录像。 -- **加速:** 按X可以加速录像播放,最高可达6倍速。 -- **减速:** 按Z可以减速录像播放,最低可达0.3倍速。 -- **停止:** 按ESC可以立刻停止录像播放,并返回正常游戏。 -- **回退:** 按A可以回退到上一个录像节点(录像播放过程中每50步存一个录像节点)。 -- **存档:** 按S可以在录像播放过程中进行存档。 -- **查看手册:** 按C可以在录像播放过程中查看怪物手册。 -- **浏览地图:** 按PgUp/PgDn可以在录像播放过程中浏览地图。 - -如果录像出现问题,请加 QQ 群 [959329661](https://jq.qq.com/?_wv=1027&k=5C87qeQ) 找小艾反馈Bug。 -## 操作说明 - -![](img/keyboard.png) - - - -  - -  + 勾选此项后,事件层有东西(如道具)时将虚化该格子的前景层,使得该东西以半透明状态可见。 上面就是整个样板中的各个元件说明。通过这种方式,你就已经可以做出一部没有任何事件的塔了。 diff --git a/_docs/event.md b/_docs/event.md index f14a9265..ccd86d5f 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -1,2377 +1,254 @@ # 事件 ?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} *
-本章内将对样板所支持的事件进行介绍。 +## 事件编辑(地图选点,快捷键X) +![image](img/v2.7/eventsX.png) +样板所有的事件都是依靠“触发器”完成的。例如,勇士碰到(绑定好的)楼梯可以触发changeFloor,碰到门可以触发openDoor,碰到怪物可以触发battle,碰到道具可以触发getItem,碰到箱子可以触发pushBox,走上冰面(背景层)可以触发ski. -## 事件的机制 -本塔所有的事件都是依靠触发器 `trigger` 完成的。例如,勇士碰到一个门可以触发一个事件 `openDoor` ,勇士碰到怪物可以触发一个事件 `battle` ,勇士碰到一个(上面定义的)楼层传送点可以触发一个事件 `changeFloor` ,等等。上面说的这些事件都是系统本身自带的,即类似于RMXP中的公共事件。
-上述这些默认的事件已经存在处理机制,不需要我们操心。我们真正所需要关心的,其实只是一个自定义的事件。 -
所有事件都存在两种状态:启用和禁用。 -- 启用状态下,该事件才处于可见状态,可被触发、交互与处理。 -- 禁用状态下该事件相当于不存在,不可见、不可被触发、不可交互。 +这些触发器都是系统自带的,已经存在处理机制,不需要我们操心。我们真正所需要关心的,其实只是自定义的事件(如NPC)。 -所有事件默认情况下初始都是启用的,除非取消了“启用”的勾选(适用于普通事件)。
-在事件列表中使用“显示事件”和“隐藏事件”可以将一个禁用事件给启用,或将一个启用事件给禁用(后者也提供了一个勾选项,勾选后不禁用而是直接永久从地图中删除)。
-因此,非常不推荐仅仅为了初始隐藏一个图块,就去给它绑定一个本身没有任何指令的普通事件。
-如有需求,请使用“转变图块”或“关门”事件 -## 关于V2.0的重要说明 +地图选点(快捷键X)一共有七项,在地图中以图块左下角用七色小方块标记。 -在V2.0以后版本中,所有事件均可以使用blockly来进行块的可视化编辑。 +红色为普通事件,橙色为自动事件,黄色为战后事件,绿色为楼层转换,青色为(拾获)道具后事件,靛色(不是事件)为勇士站在该点不能朝哪些方向走,紫(粉)色为开门后事件。此外还有一些事件不在地图上,如“首次到达”、“每次到达”(这两个的触发原理,详见“脚本编辑——切换楼层后”)、“道具效果”、“公共事件”和全塔属性中那五个事件。 -它能通过拖动、复制粘贴等方式帮助你快速生成事件列表,而不用手动打大量字符。 +### 事件的机制 +地图上的所有事件都存在两种状态:启用和禁用。 +- 启用状态下,该事件才处于可见状态,可被触发、交互与处理。 +- 禁用状态下,该事件几乎相当于不存在,不可见、不可被触发、不可交互,只能通过“插入事件”指令远程调用。 -下述所说的都是在事件编辑器右边所展示的,该事件的代码化写法;部分增加了可视化事件编辑器的截图示意(感谢秋橙的制作)。 -
强烈建议要对每个事件的写法进行了解,因为在脚本编辑,`insertAction` 等地方需要插入临时事件组时,还是很有必要的。 -## 普通事件 -打开样板1层(`sample1.js`)有着一些介绍。下面是更为详细的说明。 -
所有普通事件都是如下的开头:
-覆盖触发器(Y/N)启用(Y/N)通行状态(不改变/不可通行/可以通行)显伤(Y/N) -1. 覆盖触发器:如果该点原本是道具或怪物等有着系统触发器的图块,那么必须勾选此项,表示用此普通事件中的指令覆盖原本的行为(拾获和战斗等,但炸弹、光环和阻激夹域捕不受影响),如果是在原本的系统行为结束后执行其他行为,请使用三个 `afterXxx` 事件。 -2. 启用:如果不勾选此项,就表示此普通事件初始时是隐藏的。 -3. 通行状态:可以使用此设定来覆盖该点图块的通行性,如果不指定则以图块为准(道具可通行,怪物不可通行,其他图块由图块属性的 `canPass` 项指定) -4. 显伤:如果不勾选此项,则该点为怪物时将取消显伤。 -``` json -{ - "trigger": "action", // 触发的trigger, action代表覆盖触发器 - "enable": true, // 该事件初始状态下是否处于启用状态 - "noPass": true, // 该点是否不可通行。true代表不可通行,false代表可通行。 - "data": [ // 实际执行的事件列表 - {"type": "xxx", ...}, // 事件1 - {"type": "xxx", ...}, // 事件2 - // ... - // 按顺序写事件,直到结束 -] -``` +所有事件默认情况下初始都是启用的,只有普通事件可以通过不勾选“启用”来初始隐藏。 -`"type"`为该自定义事件的类型;而后面的`...`则为具体的一些事件参数。 -
每次,系统都将取出数组中的下一个事件,并进行处理(执行 `core.events_action_xxx()` 函数);直到数组中再无任何事件,或遇到“立刻结束当前事件”,才会完全结束本次普通事件,恢复游戏状态。
-从V2.7起,事件流结束时会清空所有临时变量和参数变量(以 `@temp` 开头、或 `arg` 加纯数字的 `flag`)。
-下面将依次对所有自定义事件类型进行介绍。 +在事件列表中使用“显示事件”和“隐藏事件”可以将一个禁用事件给启用,或将一个启用事件给禁用,甚至直接从地图中删除。 -### text:显示一段文字(剧情) +如想让一个普通事件(红)或楼层转换事件(绿)隐形但不禁用,请将其“转变图块为”0(空地)或17(空气墙)。 -使用`{"type": "text"}`可以显示一段文字。后面`"text"`可以指定文字内容。 +【重要警告】: +1. 打怪开门捡道具后,如果有对应的坐标,则该点的事件会被从地图中删除(重生怪除外,它只会被暂时隐藏)。然后会尝试执行该点的战后事件、开门后事件或(拾获)道具后事件(您可以勾选“轻按时不触发”)。如果执行,则“当前点坐标”(core.status.event.data的坐标)也会变为该点。 -``` json -[ - {"type": "text", "text": "在界面上的一段文字"}, // 显示文字事件,按空格或单击屏幕继续 - "这是第二段文字", // 显示第二个文字事件,可以简写为字符串 - // 请注意insertAction函数接收单个字符串作为参数时会优先识别为公共事件,建议改用drawText - // 按顺序写事件,直到结束 -] -``` + 所以,这三个XX后事件,其实是有可能被多次触发或意外触发的(如打死或炸掉某个有战后事件的怪,推了个阻击怪过去打死),请自行注意。 +2. “移动事件”(如阻击和捕捉)和“跳跃事件”(如支援)会将起点处的事件从地图中删除,如果不勾选“不消失”(如阻击),则会在终点处“转变图块”并“显示事件”。但事件的内容不会被跟着移动到终点,推箱子同理,但在终点只转变图块而不予显示。 +### 楼梯、传送门事件 +![image](img/v2.7/changeFloor.png) -![](img/events/1.jpg) +当您在地图上绘制楼梯、或绘制四种三帧箭头并右击绑定后,就创建了一个“楼层转换”事件,您可以在事件编辑器右侧看到一行代码(json),请注意对照。 -值得注意的是,系统会自动对文字进行换行;不过我们也可以手动加入`\n`来换行。 +此事件与core.changeFloor(floorId, stair, heroLoc, time, +callback)函数相对应,只是多了一项“穿透性”。 -``` json -[ - "这一段文字特别特别长,但是系统可以对它进行自动换行,因此我们无需手动换行", - "这是第一行\n这是第二行\n这是第三行", - // ... - // 按顺序写事件,直到结束 -] -``` +每个这样的事件都是上图的写法,下面逐一讲解其各项的含义和用法: +1. 目标楼层(floorId):如题,如果选择了“楼层ID”就需要在第二个框中输入目标楼层的ID(会自动提示补全,也可以双击整个紫色块从地图选点)。如果选择了其他三种,则json代码中“:before”、“:next”、“:now”分别表示“前一楼”、“后一楼”(顺序由“全塔属性——楼层列表”指定,上下楼器同理)和“当前楼”,函数中也是一样的写法。 +2. 目标位置(stair):如果选择了“坐标”则需要在后面两个框里输入(同样可以地图选点,在函数中则将stair填null并填写heroLoc),也可以选择下拉框中的其他几项(在函数中则将heroLoc填null),如保持不变(:now)、中心对称(:symmetry)、左右对称(`:symmetry_x`)、上下对称(`:symmetry_y`)或任何一个图块ID. -我们可以给文字加上标题或图标,只要以`\t[...]`开头就可以。 -
其一般写法是 `\t[名字,ID]` ,其中名字为你要显示的标题,ID为图块ID,也可以填 `hero` 或`this`。
如果不需要可以不写ID,则只会显示标题。对于非道具,也可以不写名字代表使用默认值。
-从V2.5.2以后,新增了绘制大头像的功能。绘制大头像图的基本写法是`\t[1.png]`或者`\t[标题,1.png]`。 -
从V2.6开始,所有图块都允许只写ID,对于非怪物也非道具则仅当图块属性中设置了 `name` 才有标题(否则不显示标题)。另外注意的是,名字可以用null从而只显示动画而不显示标题。 -``` json -[ - "一段普通文字", - "\t[勇士,hero]这是一段勇士说的话", - "\t[hero]如果使用勇士默认名称也可以直接简写hero", - "\t[黑暗大法师,magicMaster]我是黑暗大法师", - "\t[黑暗大法师,this]如果使用当前点的图块作为图标也可以简写this", - "\t[magicMaster]如果使用怪物的默认名称也可以简写怪物id", - "\t[小妖精,fairy]这是一段小妖精说的话,使用仙子(fairy)的图标", - "\t[你赢了]直接显示标题为【你赢了】", - "\t[1.png]绘制1.png这个头像图", - "\t[标题,1.png]同时绘制标题和1.png这个头像图", - "\t[sword1]获得铁剑,没有标题", - "\t[man]没有标题的npc动画", - "\t[null,greenSlime]只绘制怪物动画而不显示标题" -] -``` + 填写三种对称位置时请注意,坐标计算以当前楼层而不是目标楼层为准,尤其要注意防止勇士出界。 -![](img/events/2.jpg) + 填写图块ID时请注意,“上下楼梯”提供在了下拉框中,实际传送时会优先尝试取用目标层的“楼层属性——上下楼点”。其次尝试像其他ID一样从目标楼层搜索,因此请确保该图块在目标楼层中存在且唯一。 +3. 朝向:有八种写法,可以直接填写改变后的朝向(up、down、left、right),也可以填写转身的角度(:left、:right、:back)或不变。 -!> 大头像的头像图需要在全塔属性中注册,且必须是png格式,不可以用jpg或者其他格式,请自行另存为。
-除此以外,我们还能实现“对话框效果”,只要有`\b[...]`就可以。 -- `\b[up]` 直接显示在当前点上方。`up` 换成 `down` 则为下方,换成 `null` 则根据当前点在视野中的位置自动选择上下 - - 如果不存在当前点(如在`firstArrive`或`eachArrive`中调用),则显示在屏幕最上方(最下方) - - `\b[up,null]`和`\b[center]`可以无视当前点存在与否,强制显示在屏幕最上方(最下方)或中央 -- `\b[up,hero]` 显示在勇士上方。同样把这里的 `up` 换成 `down` 则为下方。 - - 从V2.6开始,也允许写`\b[hero]`来根据勇士在视野中的位置自动决定上方还是下方 -- `\b[up,x,y]` 显示在(x,y)点的上方(下方);x和y都为整数,表示该点的绝对坐标 - - 从V2.6开始,也允许写`\b[null,x,y]`来根据(x,y)位置自动决定上方还是下方 -- `\b[up,x]` 显示在勇士的第x个跟随的行走图的上方(下方);也允许把 `up` 换成 `down`,或用 `hero` 来自动适配 -``` json -[ - "\b[up]这段文字显示在当前点上方", - "\b[down]这段文字显示在当前点下方", - "\b[this]这段文字显示在当前点,根据位置自动适配上下", - "\b[up,null]这段文字显示在视野最上方", - "\b[down,null]这段文字显示在视野最下方", - "\b[center]这段文字显示在视野中央", - "\t[hero]\b[up,hero]这是一段勇士说的话,会显示在勇士上方", - "\t[hero]\b[hero]这是一段勇士说的话,根据勇士位置自动适配上下", - "\t[小妖精,fairy]\b[down,2,2]这是一段小妖精说的话,会显示在(2,2)点下方", - "\b[this,1,3]根据坐标位置自动适配上下", - "\b[up,1]显示在勇士第一个跟随的行走图上方", - "\b[hero,2]显示在勇士第二个跟随的行走图,自动适配上下", -] -``` +4. 动画时间:指黑屏的毫秒数,可以填0或不小于100的整数,不填则使用玩家设定值。 -![](img/events/3.jpg) +5. 穿透性:见[系统开关]允许穿透楼梯。 -!> `\t[...]`必须在`\b[...]`前面!不然两者都无法正常显示。 -
还可以使用`\r[...]`来调整剧情文本的颜色,颜色的英文名详见[w3school](https://www.w3school.com.cn/cssref/css_colornames.asp)。样板也会帮你自动补全最标准的这17个:aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, orange, purple, red, silver, teal, white, yellow -``` json -[ - "这句话是默认颜色,\r[red]将颜色变成红色,\r[blue]将颜色变成蓝色", - "\r[#FF00FF]还可以使用RGB值来控制颜色,\r如果不加中括号则回到默认颜色", - "\t[hero]\b[up,hero]啊啊啊,别过来,\r[red]别过来!!!\n\r你到底是什么东西!" -] -``` +值得注意的是,绑定了楼层转换事件的门、怪物、道具、箱子,其系统行为(开门、战斗、拾取、推行)将不再发生(阻激夹域等地图属性不受影响),而是被覆盖为上下楼。 +## 普通事件(红) +普通事件在启用后可以被勇士碰触而触发,它们都有着这样的开头: -![](img/events/4.jpg) +覆盖触发器(Y/N)启用(Y/N)通行状态(Y/N?)显伤(Y/N) +1. 覆盖触发器:如前所述,门、怪物、道具、箱子都已经被绑定了系统触发器。如果您需要让地图上的个别这类图块在被勇士碰触时不发生系统行为(开门、战斗、拾取、推行),而是执行您在下面自定义的事件(比如触碰boss先进行一段对话再强制战斗),请勾选此项。(阻激夹域等地图属性不受影响) +2. 启用:如果不勾选此项,则此事件初始时是隐藏的。 -从V2.5.3以后,也可以使用`\f[...]`来同时绘制一张图片。 + 如前所述,非常不推荐仅仅为了初始隐藏一些图块(如战利品、陷阱门墙、埋伏怪等)就去绑定一堆没有指令的普通事件。更安全的做法是“从0转变图块”(支持淡入效果)和“关门”(这样还有音效,多香)。 +3. 通行状态:除怪物和道具外,所有图块本身都具有“可通行性”属性。 -其基本写法是`\f[img,x,y]`,或者`\f[img,x,y,w,h]`,或者`\f[img,sx,sy,sw,sh,x,y,w,h]`。 + 您可以设置此项去覆盖地图中这一点的可通行性,譬如强行让一格空地不可通行,勇士撞击时出现一堵墙(51层魔塔第23层的效果)。 +4. 显伤:在对怪物使用覆盖触发器后,表面上看不出它和一般怪物的不同。 -从V2.6.3开始,也可以在最后加上alpha值,即`\f[img,sx,sy,sw,sh,x,y,w,h,alpha]`。 -
从V2.7开始,也可以在图片名结尾加上 `:x, :y, :o`,分别表示将图片水平翻转、竖直反转、旋转180°。
-需要注意的是,这个图片是绘制在UI层上的,下一个事件执行时即会擦除;同时如果使用了\t的图标动画效果,重叠的地方也会被图标动画给覆盖掉。 -``` json -[ - "\t[勇士]\b[up,hero]\f[1.png,100,100]以(100,100)为左上角绘制1.png图片", - "\t[hero]\f[1.png,100,100]\f[2.png,300,300]同时绘制了两张图片", - "\f[1.png,100,100,300,300]也可以填写宽高,这样会把图片强制进行放缩到指定的宽高值", - "\f[1.png,64,64,128,128,100,100,128,128]裁剪1.png上以(64,64)开始的128x128图片,并绘制到画布的(100,100)处", - "\f[1.png,64,64,128,128,100,100,128,128,0.5]同上,不透明度0.5", -] -``` +如有必要(比如触碰这怪物根本不战斗),可不勾选显伤以示区别。 -![](img/events/5.jpg) +如数量较多,可注册一个相同素材的NPC,比如样板中的仙子。 -从V2.5.5以后,也可以使用`\\i[...]`来在对话框中绘制一个图标。 +如需在一段剧情中关闭所有显伤,请调用core.removeItem(’book’) +## 自动事件(橙) +在“右键绑定机关门”中,我们已经初见了自动事件的端倪。 -这里可以使用一个合法ID(32x48图块除外),或使用一个系统图标(`core.statusBar.icons`中的内容)。 -``` json -[ - "\t[勇士]\b[up,hero]这是一个楼层传送器\\i[fly],这是一个破墙镐\\i[pickaxe]", - "\t[hero]也可以使用系统图标,比如这是存档\\i[save],这是工具栏\\i[toolbox]", -] -``` +在游戏中,我们经常需要监听大量乱七八糟的状态,根据状态的变化去做出及时的处理,比如勇士生命小于等于0会触发游戏失败。比如51层魔塔第39层监听9扇黄门的状态来触发中心对称飞行器的出现、第49层监听8名魔法警卫的状态来封印假魔王。 -![](img/events/6.jpg) +如果给9扇黄门都绑定类似的开门后事件、给8名警卫都绑定类似的战后事件,就非常繁琐。 -**可以在控制台中输入`core.statusBar.icons`以查看所有的系统图标定义。** -
!> 注意,在事件块中,允许只写一个反斜杠`\i`,系统会自动转义成`\\i`;但是在脚本中必须两个反斜杠都写上!`\c`、`\d`、`\e` 和 `\z` 同理
-从V2.6.3开始,也可以使用`\\c[...]`来切换当前字号,`\\d`来加粗或取消粗体,`\\e`来加斜体或取消斜体。
从V2.7开始,还可以使用`\\z[...]`来调节打字速度。 -``` json -[ - "这是原始字号,\\c[20]使用20号字体,\\c[10]使用10号字体", - "\\c如果不加中括号则切换回原始字号。", - "\\d这是粗体\\d取消粗体,\\e加斜体\\e取消斜体", - "\t[hero]\b[hero]让我想想...\\z[10]有了!" // 打出省略号后,暂停相当于打10个字的时间 -] -``` -另外值得一提的是,我们是可以在文字中计算一个表达式的值的。只需要将表达式用 `${ }`整个括起来就可以。 -``` json -[ - "1+2=${1+2}, 4*5+6=${4*5+6}", // 显示"1+2=3, 4*5+6=26" -] -``` +而自动事件则不然,它不需要您去主动考虑所有“改变状态”的原因,而是简单地在每次刷新状态栏时,检查是否满足触发条件,满足的话就执行。 -我们可以使用 `status:xxx` 代表勇士的一个属性值;`item:xxx` 代表某个道具的个数;`flag:xxx` 代表某个自定义的变量或flag值;`switch:A-Z`代表某个独立开关的值。 +每个自动事件具有以下几个属性: +1. 触发条件:自动事件最重要的属性,为支持冒号缩写量的逻辑表达式。 -从V2.6开始,也可以使用`global:xxx`代表全局存储(和存档无关的存储)。 + 譬如上述两个例子中,触发条件就是“某两个点没有图块而某7个点图块为黄门”和“某四个点没有图块而某四个点图块为魔法警卫”。 -从V2.6.5开始,也可以使用`enemy:id:xxx`来获得某个怪物的属性,`blockId:x,y`来获得某个点的图块ID,`blockCls:x,y`来获得某个点的图块类别,`equip:N`来获得某个装备孔的装备ID。 + 关于冒号缩写量,详见[只读块]值块和冒号缩写量。 +2. 优先级:一般不需要改动。当多个自动事件的条件同时满足时,优先执行此级别较大的。此级别也相等时,允许跨层触发则优先执行楼层较矮的。同一楼层优先执行横坐标较小的,横坐标相等时优先执行纵坐标较小的,同一点处优先执行页码较小的。每个点初始提供了两个自动事件页,您还可以再在数据区最上面单击“添加自动事件页”。 +3. 仅在本层检测:如题,一般不需要改动。除非您要制作一些全局的效果,如“勇士生命低于上限的1/3时改变背景音乐”。 +4. 事件流中延迟执行:勾选此项后,在执行其他事件时触发此自动事件则会将其内容追加到待执行事件的末尾,否则插队到待执行事件的开头。 +5. 允许多次执行:如果不勾选,则此事件最多只会被触发一次。即使勾选了,每次执行的过程中也会暂时禁止自己被触发。勾选后,请记得在此事件的指令中将条件变得不满足。 +## 公共事件(逗号键) -从V2.7开始,也可以使用`temp:A-Z`来获得某个临时变量,一般在循环遍历中使用。 -``` json -[ - "你当前的攻击力是${status:atk}, 防御是${status:def},坐标是(${status:x},${status:y})", - "你的攻防和的十倍是${10*(status:atk+status:def)}", - "你的红黄蓝钥匙总数为${item:yellowKey+item:blueKey+item:redKey}", - "你访问某个老人的次数为${flag:man_times}", - "当前的存档编号是${global:saveIndex}", - "绿色史莱姆的攻击力是${enemy:greenSlime:atk}", - "(2,3)点的图块ID是${blockId:2,3},图块类型是${blockCls:2,3}", - "装备孔0的当前装备ID是${equip:0}", - "当前的临时变量A的值是${temp:A}", // blockly中还可以使用中文,如图 -] -``` +有几个事件,如战后加点、毒衰咒处理、回收钥匙商店,会在战后脚本或全局商店等处频繁用到。于是它们被整理成了公共事件,您也可以追加自己的。 -![](img/events/7.png) -- `status:xxx` 获取勇士属性时如下几个较为特殊:x(勇士的横坐标),y(勇士的纵坐标),direction(勇士的方向)。其他的单词 `xxx` 会直接解析为 `core.status.hero.xxx` 的值。 -- `item:xxx` 中的 `xxx `为道具ID。所有道具的ID定义在 `project\items.js` 中,请自行查看。例如,
`item:centerFly` 代表中心对称飞行器的个数。 -- `flag:xxx` 中的xxx为一个自定义的变量/Flag(支持中文);如果没有对其进行赋值则默认值为0。 -- `global:xxx` 中的xxx为一个全局存储的名称(支持中文);如果没有对其进行赋值则默认值为0。 -- `enemy:xxx:yyy` 中的xxx为怪物ID;yyy为要获得的项,比如hp, atk, def等等 -- `blockId:x,y` 和 `blockCls:x,y` 中的x,y为坐标值 -- `equip:x` 中的x为装备孔编号,从0开始。 +公共事件在内容上和其他事件并无不同,只是在插入公共事件时(如core.insertCommonEvent(“回收钥匙商店”))可以提供一个“参数列表”。 -### autoText:自动剧情文本 - -使用`{"type": "autoText"}`可以使用剧情文本。 -``` json -[ - {"type": "autoText", "text": "一段自动显示的剧情文字", "time": 5000} -] -``` - -![](img/events/8.jpg) - -text为文本正文内容,和上面的写法完全一致。 - -time为可选项,代表该自动文本的时间。可以不指定,不指定默认为3000毫秒。 - -用户无法跳过自动剧情文本,只能等待time时间结束后自动过。 - -回放录像时将忽略自动剧情文本的显示。 -
!> 由于用户无法跳过自动剧情文本,因此对于大段剧情文本请自行塞进“是否跳过剧情”的确认框分支,否则可能会非常不友好。 -### scrollText:滚动剧情文本 - -使用`{"type": "scrollText"}`可以使用滚动剧情文本,即将一段文字从屏幕最下方滚动到屏幕最上方。 -``` json -[ - {"type": "scrollText", "text": "第一排\n第二牌\n\n空行后的一排", "time": 5000, "lineHeight": 1.4, "async": true}, -] -``` - -![](img/events/9.jpg) - -text为正文文本内容。可以使用`${ }`来计算表达式的值,且使用`\n`手动换行。系统不会对滚动剧情文本进行自动换行。 - -time为可选项,代表总的滚动时间。默认为5000毫秒。 - -lineHeight为可选项,代表行距。默认为1.4。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -可以使用下面的[设置剧情文本的属性](event#setText:设置剧情文本的属性)来对文字颜色、文字大小、粗体、距离左边的偏移量进行设置。 - -!> 滚动剧情文本会绘制在UI层(和对话框冲突)!如果是异步处理请注意不要和对话框混用。 - -### setText:设置剧情文本的属性 - -使用`{"type": "setText"}`可以设置剧情文本的各项属性。 -``` json -[ - {"type": "setText", "title": [255,0,0], "text": [255,255,0], "background": [0,0,255,0.3], "time": 70}, - {"type": "setText", "position": "up", "offset": 15, "bold": true, "titlefont": 26, "textfont": 17}, - "这段话将显示在上方(距离顶端15像素),标题为红色,正文为黄色粗体,背景为透明度0.3的蓝色,标题26px,正文17px,70毫秒速度打字机效果", - {"type": "setText", "background": "winskin.png"} // 还可以一张使用WindowSkin作为皮肤。 -] -``` - -![](img/events/10.jpg) - -title为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示标题(名字)颜色。 默认值:`[255,215,0,1]`, - -可以通过单击RGBA值后面的色块呼出调色器,进行16进制转换等复杂取色操作,其他使用RGBA的事件也是类似的。 - -text为可选项,如果设置则为一个RGB三元组或RGBA四元组,表示正文颜色。 默认值:`[255,255,255,1]` - -background为可选项,如果设置可为一个RGB三元组或RGBA四元组,表示背景色。 默认值:`[0,0,0,0.85]` - -V2.5.2以后,background也可以为一个WindowSkin的文件名。详见[剧情文本控制与界面皮肤](element#剧情文本控制与界面皮肤)。 - -position为可选项,表示设置文字显示位置。只能为up(上),center(中)和down(下)三者。 默认值: `center` - -offset为可选项,如果设置则为代表距离如果显示位置是上/下的话,距离顶端/底端的像素值。也作为滚动剧情文本时距离左边的像素值。 - -bold为可选项,如果设置则为true或false,表示正文是否使用粗体。 默认值:`false` - -titlefont为可选项,表示标题字体大小(px为单位)。默认值:`22` - -textfont为可选项,表示正文字体大小(px为单位)。默认值:`16` - -time为可选项,表示文字添加的速度。若此项设置为0将直接全部显示,若大于0则会设置为相邻字符依次显示的时间间隔。 默认值:`0` - -interval为可选项,表示文字之间的间距。单位为像素值。默认值:`0` - -lineHeight为可选项,表示行距。单位为像素值。 -### tip:显示一段提示文字 - -`{"type": "tip"}`可以在左上角显示一段提示文字。 -``` json -[ - {"type": "tip", "text": "这段话将在左上角以气泡形式显示", "icon": "book"} -] -``` - -![](img/events/11.jpg) - -text必填,为显示的内容,支持`${}`的表达式计算。 - -icon是可选的,如果设置则会绘制图标,其可以是一个有效的ID,或者`core.statusBar.icons`中的系统图标。 - -### comment:添加注释 - -使用`{"type": "comment"}`可以添加一段注释 -``` json -[ - {"type": "comment", "text": "这是一段会被跳过的注释内容"} -] -``` - -![](img/events/12.jpg) - -这个事件将在运行时被游戏跳过。 - -### setValue:设置勇士的某个属性、道具个数,或某个变量/Flag的值 - -`{"type": "setValue"}` 能修改勇士的某个属性、道具个数、或某个自定义变量或`Flag`的值。 - -其大致写法如下: -``` json -[ // 设置一个属性、道具、自定义Flag、独立开关、全局存储、临时变量 - {"type": "setValue", "name": "...", "operator": "...", "value": "..."}, -] -``` -使用 `setValue` 需要指定 `name`、`operator` 和 `value` 选项。
-`name` 为你要修改的属性/道具/Flag/独立开关/全局存储/临时变量,每次只能修改一个值。写法和 `${}` 中完全相同,`status:xxx` 表示勇士一个属性,`item:xxx` 表示某个道具个数,`flag:xxx` 表示某个变量或flag值。参见上面的介绍。
-`operator` 为运算的类型,目前支持八种,详见下面的例子和图示。
-`value` 是一个表达式,将通过这个表达式计算出的结果作为另一个运算量。该表达式同样可以使用`status:xxx`, `item:xxx`, `flag:xxx`, `global:xxx`等的写法表示勇士当前属性,道具个数,某个变量/Flag值和某个全局存储值等。 -``` json -[ - {"type": "setValue", "name": "global:一周目已通关", "value": "true", "norefresh": true}, // 设置全局存储“一周目已通关”为true,用于二周目中触发隐藏分支 - {"type": "setValue", "name": "status:name", "operator": "+=", "value": "'之王'", "norefresh": true}, // 勇士名称结尾增加两个字“之王”,不立即刷新状态栏 - {"type": "setValue", "name": "flag:hatred", "operator": "-=", "value": "10", "norefresh": true}, // 减少10点仇恨值 - {"type": "setValue", "name": "status:hp", "operator": "*=", "value": "2", "norefresh": true}, // 生命值加倍,即圣水道具的效果 - {"type": "setValue", "name": "switch:A", "operator": "/=", "value": "10", "norefresh": true}, // 独立开关A的值缩小到原来的十分之一,可能产生小数 - {"type": "setValue", "name": "item:yellowKey", "operator": "**=", "value": "3", "norefresh": true}, // 黄钥匙的数量变为它原来值的立方 - {"type": "setValue", "name": "temp:A", "operator": "//=", "value": "3", "norefresh": true}, // 临时变量缩小到原来的三分之一,向靠近0的方向取整 - {"type": "setValue", "name": "status:atk", "operator": "%=", "value": "100"}, - ] // 攻击力对100取余数,即只保留最后两位,然后刷新状态栏 -``` - -![](img/events/13.jpg) - -从V2.6.5开始,当设置了`"norefresh": true`后可以不刷新状态栏、地图显伤和自动事件,从而加速事件执行。 - - -在刷新的情况下,如果hp被设置成了0或以下,将触发lose事件,直接死亡。 - -### setEnemy:设置怪物属性 - -使用`{"type":"setEnemy"}`可以设置某个怪物的某个属性 - -``` json -[ - {"type": "setEnemy", "id": "greenSlime", "name": "hp", "value": "1000"}, // 设置绿色史莱姆生命1000 - {"type": "setEnemy", "id": "redSlime", "name": "special", "value": "[1,2]"}, // 设置红色史莱姆先攻魔攻 - {"type": "setEnemy", "id": "redSlime", "name": "name", "value": "'小史莱姆'"}, // 设置怪物名称 -] -``` - -![](img/events/15.png) - -id为必填项,代表要修改的怪物ID。 - -name为必填项,代表要修改的项,例如`hp`, `atk`, `def`, `money`, `exp`, `point`, `special`, `name`。 - -value为必填项,代表要修改到的内容。对于修改名称的,必须加单引号。 - -### setFloor:设置楼层属性 - -使用`{"type":"setFloor"}`可以设置某层楼的楼层属性。 -``` json -[ - {"type": "setFloor", "name": "title", "value": "'主塔 0 层'" } // 设置当前楼层的中文名为主塔0层 - {"type": "setFloor", "name": "canFlyTo", "floorId": "MT2", "value": "false" } // 设置MT2层不可飞行 - {"type": "setFloor", "name": "cannotViewMap", "floorId": "MT0", "value": "true" } // 设置MT0层不可被浏览地图 - {"type": "setFloor", "name": "ratio", "value": "5" } // 设置当前楼层的宝石血瓶属性加成为5 - {"type": "setFloor", "name": "images", "value": "[[0,0,'tree.png',2]]" } // 设置当前楼层的楼层贴图,设置完以后记得用core.drawMap()刷新一下 - {"type": "setFloor", "name": "upFloor", "value": "[2,3]" } // 设置当前楼层的上楼梯 - {"type": "setFloor", "name": "bgm", "floorId": "MT10", "value": "'233.mp3'" } // 设置当前楼层的背景音乐 -] -``` - -![](img/events/15.jpg) - -name为必填项,代表要修改的楼层属性,和楼层属性中的一一对应。 - -floorId为可选项,代表要修改的楼层ID;可以省略代表当前楼层。 - -value为必填项,代表要修改到的数值。其应该和楼层属性中的对应数值类型完全一致,对于字符串需要加单引号,其他类型(数字、true/false、数组)等则不需要引号。 - -!> 如果修改到的是字符串类型,比如楼层中文名、状态栏名称、地面素材ID、背景音乐等,必须加引号,否则会报错。 - -### setGlobalAttribute:设置一个全局属性 - -使用`{"type":"setGlobalAttribute"}`可以设置一个全局属性。 -``` json -[ - {"type": "setGlobalAttribute", "name": "font", "value": "Consolas"}, // 设置字体为Consolas -] -``` - -![](img/events/16.jpg) - -name必填项,代表要修改的全局属性。 - -value为必填项,代表要修改到的结果。此项无需再手动加单引号。 - -### setGlobalValue:设置一个全局数值 - -使用`{"type":"setGlobalValue"}`可以设置一个全局数值。 -``` json -[ - {"type": "setGlobalValue", "name": "lavaDamage", "value": 200}, // 设置血网伤害为200 -] -``` - -![](img/events/17.jpg) - -name必填项,代表要修改的全局数值,其和全塔属性中的values一一对应。 - -value为必填项,代表要修改到的结果。该项必须是个数值。 - -### setGlobalFlag:设置一个系统开关 - -使用`{"type":"setGlobalFlag"}`可以设置一个系统开关。 -``` json -[ - {"type": "setGlobalFlag", "name": "steelDoorWithoutKey", "value": true}, // 设置开铁门不需要钥匙 -] -``` - -![](img/events/18.jpg) - -name必填项,代表要修改的系统开关,其是全塔属性中的flags中的一部分。 - -value为必填项,只能为true或false,代表要修改到的结果。 - -### show:将一个禁用事件启用 -我们上面提到了,除自动事件外,事件都必须靠其他事件驱动来完成,不存在当某个 `flag` 为 `true` 时自动执行的说法。那么,我们自然要有启用事件的写法。
-使用`{"type":"show"}`可以将一个本身禁用的事件启用。 -``` json -[ - {"type": "show", "loc": [3,6], "floorId": "MT1", "time": 500}, // 启用MT1层[3,6]位置事件,动画500ms - {"type": "show", "loc": [3,6], "time": 500}, // 如果启用目标是当前层,则可以省略floorId项 - {"type": "show", "loc": [3,6]}, // 如果不指定动画时间,则立刻显示,否则动画效果逐渐显示,time为动画时间 - {"type": "show", "loc": [[3,6],[2,9],[1,2]], "time": 500}, // 我们也可以同时动画显示多个点。 - {"type": "show", "loc": [3,6], "time": 500, "async": true} // 可以使用异步动画效果 -] -``` - -![](img/events/19.jpg) - -show事件需要用loc指定目标点的坐标,可以简单的写[x,y]代表一个点,也可以写个二维数组[[x1,y1],[x2,y2],...]来同时显示多个点。 - -从V2.2开始,loc也可以用变量来代替,例如 `"loc": ["flag:x", "flag:y"]`。下同。 - -floorId为目标点的楼层,如果不是该楼层的事件(比如4楼小偷开2楼的门)则是必须的,如果是当前楼层可以忽略不写。 - -time为动画效果时间,如果指定了某个大于0的数,则会以动画效果慢慢从无到有显示,动画时间为该数值;如果不指定该选项则无动画直接立刻显示。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -!> **要注意的是,调用show事件后只是让该事件从禁用状态变成启用,从不可见不可交互变成可见可交互,但本身不会去执行该点的事件。** -### hide:将一个启用事件禁用,或将其从地图永久删除 -`{"type":"hide"}`和show刚好相反,它会让一个已经启用的事件被禁用。 - -其参数和show也完全相同,loc指定事件的位置,floorId为楼层(同层可忽略),time指定的话事件会以动画效果从有到无慢慢消失,async代表是否是异步效果。 - -loc同样可以简单的写[x,y]表示单个点,或二维数组[[x1,y1],[x2,y2],...]表示多个点。 - -但是和show事件有所区别的是:loc选项也可以忽略;如果忽略loc则使当前事件禁用。(即使禁用当前事件,也不会立刻结束当前正在进行的,而是仍然会依次将列表中剩下的事件执行完)另外还多了一个“同时删除”的勾选项,如果勾选此项就不会禁用而是直接从地图永久删除(不可再被重新显示) - -请注意,一次性事件必须要加 `{"type":"hide"}`,尤其是例如走到某个点,触发对话或机关门(陷阱)这种,否则每次都会重复触发。 - -NPC对话事件结束后如果需要NPC消失也需要调用 `{"type": "hide"}`,可以不写loc选项代表当前事件,可以指定time使NPC动画消失。 -``` json -[ - {"type": "hide", "loc": [3,6], "floorId": "MT1", "time": 500}, // 禁用MT1层[3,6]位置事件,动画500ms - {"type": "hide", "loc": [3,6], "time": 500}, // 如果启用目标是当前层,则可以省略floorId项 - {"type": "hide", "loc": [3,6]}, // 如果不指定动画时间,则立刻消失,否则动画效果逐渐消失,time为动画时间 - {"type": "hide", "loc": [[3,6],[2,9],[1,2]], "time": 500}, // 也可以同时指定多个点消失 - {"type": "hide", "time": 500}, // 如果不指定loc选项则默认为当前点, 例如这个就是500ms消失当前对话的NPC - {"type": "hide"}, // 无动画将当前事件禁用,常常适用于某个空地点(触发陷阱事件、触发机关门这种) - {"type": "hide", "loc": [3,6], "time": 500, "async": true} // 可以使用异步动画效果 -] // 此事件实际直接调用的函数是core.removeBlock(x, y),开门打怪捡道具后也会自动调用此函数 -``` - -![](img/events/20.jpg) - -### trigger:立即触发另一个地点的事件 - -`{"type":"trigger"}` 会立刻触发当层另一个地点的自定义事件。 - -其基本写法如下: -``` json -[ - {"type": "trigger", "loc": [3,6]}, // 立即触发loc位置的事件,当前剩下的事件全部不再执行 - {"type": "trigger", "loc": [3,6], "keep": true}, // 触发loc位置的事件,不结束当前事件 -] -``` - -![](img/events/21.jpg) - -其后面带有loc选项,代表另一个地点的坐标。 - -keep可选,如果此项为true则不会结束当前的事件列表,否则会中断当前的事件流。 - -从V2.5.4开始允许执行另一个点的系统事件,如打怪开门拾取道具等等,对应点的战后等事件也会被插入执行。 - -值得注意的是,此事件会**改变当前点坐标**为目标点。 - -### insert:插入公共事件或另一个地点的事件并执行 - -`{"type":"insert"}` 会插入公共事件或另一个地点的事件并执行。 - -其基本写法如下: -``` json -[ - {"type": "insert", "name": "加点事件", "args": [10] }, // 插入公共事件:加点事件,传入参数10 - {"type": "insert", "name": "毒衰咒处理", "args": [0]}, // 插入公共事件:毒衰咒处理,传入参数0 - {"type": "insert", "loc": [3,6]}, // 插入[3,6]点的事件并执行 - {"type": "insert", "loc": [10,10], "floorId": "MT1"}, // 插入MT1层[10,10]点的事件并执行 - {"type": "insert", "loc": [2,2], "args": [1,"flag:abc","status:atk+status:def"]}, // 传入三个参数 - "上面的插入事件执行完毕后会接着继续执行后面的事件" -] -``` - -![](img/events/22.jpg) - -`insert`的写法有两种,可以写`name`,或者`loc`。 - -- 如果写了`"name": "xxx"`,则会去公共事件列表中找寻对应的事件,并执行。 - - name为公共事件的名称,如果对应公共事件不存在则跳过。 -- 否则,如果写了`"loc": [x,y]`,则会插入另一个地点的事件 - - loc为另一个地点的坐标 - - floorId可选,代表另一个地点所在的楼层;如果不写则默认为当前层。 - - 从V2.6开始,还可以传可选的which,可以为`afterBattle`/`afterGetItem`/`afterOpenDoor`,代表插入该点的战后/获得道具后/开门后事件。 - -和`type:trigger`不同点如下: -- `type:trigger`只能指定当前楼层且会改变当前点坐标,`type:insert`可以跨楼层且不会改变当前点坐标。 -- `type:trigger`如果不设置`keep:true`则还会结束当前事件,`type:insert`而是将另一个点的事件插入到当前事件列表中执行。 -- `type:trigger`可以触发系统事件,`type:insert`只能触发该点的普通事件或 `afterXxx` 事件等。 -- `type:trigger`要求目标点启用,`type:insert`会无视目标点启用与否。 - -插入的事件执行完毕后,会继续执行接下来的内容。 - -从V2.6开始,插入事件允许传参。如果需要传参,则需要增加一个`args`数组。 - -例如: `"args": [1,"flag:abc","status:atk+status:def"]` 传入了三个参数。 - -系统会自动把`flag:arg1`设置为第一个参数数值,`flag:arg2`设置为第二个参数数值,等等。 - -(`flag:arg0`则会被置为公共事件名称,或者插入的点的坐标) - -即可在事件中直接取用`flag:arg1`等等来获得各项参数值!。 -### exit:立刻结束当前事件 -可以使用`{"type":"exit"}`立刻结束事件。调用 `exit` 后,将立刻结束一切事件,清空事件列表、清空 `@temp` 临时变量和 `arg0-9` 参数变量,并返回游戏。
-例如玩家点击商人的"离开"选项,则可以调用exit返回游戏。 -``` json -[ - {"type": "exit" }, // 立即结束事件并恢复游戏,一切列表中的事件都将不再被执行 - "执行exit后,这段文字将不会再被显示" -] -``` - -![](img/events/24.jpg) - -### setBlock:设置某个图块 - -我们可以采用 `{"type": "setBlock"}` 来改变某个地图块。 -``` json -[ - {"type": "setBlock", "floorId": "MT1", "loc": [3,3], "number": 233}, // 将MT1层的(3,3)点变成数字233 - {"type": "setBlock", "loc": [2,1], "number": 121}, // 省略floorId则默认为本层 - {"type": "setBlock", "number": 57}, // loc也可省略,默认为当前点 - {"type": "setBlock", "number": "yellowDoor"}, // 从V2.6开始也允许写图块ID -] -``` - -![](img/events/25.jpg) - -floorId为可选的,表示要更改的目标楼层。如果忽略此项,则默认为当前楼层。 - -loc为可选的,表示要更改地图块的坐标。如果忽略此项,则默认为当前事件点。 - -number为**要更改到的数字**,有关“数字”的定义详见参见[素材的机制](personalization#素材的机制)。 - -从V2.6开始,number也允许写图块的ID,将自动转成对应的数字。 - -从V2.7开始,还可以指定转变的动画时间。您可以用于该点原本是空地的场合,从而避免“仅仅为了做个淡入效果,就去创建了一个本身没有任何指令的普通事件”。
-指定动画时间的话,前一半时间会用于将该点原有的图块淡出,后一半用于将新图块淡入。图块更改后: - - 其启用/禁用状态不会发生任何改变。原来是启用还是启用,原来是禁用还是禁用。 - - 可通行状态遵循覆盖原则,即**首先取该图块的 `canPass` 属性(道具和怪物没有此属性,道具可通行,怪物不可通行),如果该点的普通事件中定义了 `noPass` 则覆盖**。 - - 触发器( `trigger` )亦采用覆盖原则,即**首先取该图块的默认触发器(例如怪物是battle,道具是getItem,门是openDoor),如果该点绑定了楼层转换事件(绿)或普通事件(红)中覆盖触发器,则覆盖**。 -图块更改往往与[同一个点的多事件处理](#同一个点的多事件处理)相关。 -### showFloorImg / hideFloorImg:显隐楼层贴图 -使用`{"type":"hideFloorImg"}`可以隐藏某个楼层的贴图。使用`{"type":"showFloorImg"}`可以显示楼层的贴图。
-有关贴图说明请参见[使用自己的图片作为某层楼的背景/前景素材](personalization#使用自己的图片作为某层楼的背景前景素材)。 -``` json -[ - {"type": "hideFloorImg", "loc": [32,64], "floorId": "MT1"}, // 隐藏[32,64]的贴图 - {"type": "hideFloorImg", "loc": [32,64]}, // 如果是当前层,则可以省略floorId项 - {"type": "showFloorImg", "loc": [[32,64],[256,96],[128,256]]} // 我们也可以同时显隐多个贴图。 -] -``` - -![](img/events/26.jpg) -loc为要显隐的贴图的左上角像素坐标,可以简单的写[x,y]代表一个点,或二维数组[[x1,y1],[x2,y2],...]来同时显隐多个点。
-如果同时存在若干个贴图都是是该坐标为左上角,则这些贴图全部会被显隐。
-floorId为目标点的楼层,如果是当前楼层可以忽略不写。 -### showBgFgMap / hideBgFgMap:显隐楼层的某些背景或前景图块 -使用`{"type":"hideBgFgMap"}`可以隐藏背景或前景图块。使用`{"type":"showBgFgMap"}`可以显示背景或前景图块。
-从V2.4.1开始,允许绘制三层图层(背景层,事件层和前景层)。 -``` json -[ - {"type": "hideBgFgMap", "name": "bg", "loc": [3,6], "floorId": "MT1"}, // 隐藏MT1层[3,6]的背景层图块 - {"type": "hideBgFgMap", "name": "bg", "loc": [3,6]}, // 如果是当前层,则可以省略floorId项 - {"type": "showBgFgMap", "name": "fg", "loc": [[3,6],[2,9],[1,2]]} // 我们也可以同时显隐多个图块。 -] -``` - -![](img/events/27.jpg) - -name为必选的,且只能是`bg`和`fg`之一,分别代表背景图层和前景图层。 -
`loc` 为要显隐的图块的坐标,可以简单的写[x,y]代表一个点,也可以写个二维数组[[x1,y1],[x2,y2],...]来同时显示多个点。
-floorId为目标点的楼层,如果是当前楼层可以忽略不写。 -### setBgFgBlock:设置某个背景或前景层图块 - -我们可以采用 `{"type": "setBgFgBlock"}` 来改变某个背景或前景层地图块。 -``` json -[ - {"type": "setBgFgBlock", "name": "bg", "floorId": "MT1", "loc": [3,3], "number": 233}, // 将MT1层背景层的(3,3)点变成数字233 - {"type": "setBgFgBlock", "name": "bg", "loc": [2,1], "number": 121}, // 省略floorId则默认为本层 - {"type": "setBgFgBlock", "name": "fg", "number": 57}, // loc也可省略,默认为当前点 -] -``` - -![](img/events/28.jpg) - -name为必选的,且只能是`bg`和`fg`之一,分别代表背景层和前景层。 - -floorId为可选的,表示要更改的目标楼层。如果忽略此项,则默认为当前楼层。 - -loc为可选的,表示要更改地图块的坐标。如果忽略此项,则默认为当前事件点。 - -图块更改后,其隐藏/显示状态不会发生任何改变,即原来是隐藏还是会不显示。可以使用`showBgFgMap`事件将其显示出来。 - -### setHeroIcon:更改角色行走图 - -使用`{"type": "setHeroIcon"}`可以更改角色行走图。 -``` json -[ - {"type": "setHeroIcon", "name": "hero2.png"}, // 将勇士行走图改成hero2.png;必须在全塔属性的images中被定义过。 - {"type": "setHeroIcon"}, // 如果不加name则恢复最初默认状态 - {"type": "setValue", "name": "status:name", "value": "'可绒'"}, // 修改勇士名;请注意value必须加单引号。 -] -``` - -![](img/events/29.jpg) - -name是可选的,代表目标行走图的文件名。 -
!> **目标行走图必须在全塔属性的 `images` 中被定义过,且宽度至少是128像素(高度不限)。**
如果不加name,则恢复默认的角色行走图 `hero.png` 。
-如果要修改勇士的名称,可以使用`setValue`事件来修改`status:name`,但请注意value必须加单引号,不然会报错。
-如果你需要获取当前的行走图文件名,可以使用 `flags.heroIcon` ,但不要直接修改它。 -### update:立刻更新状态栏和地图显伤 -如果你需要刷新状态栏和地图显伤,只需要简单地调用 `{"type": "update", "doNotCheckAutoEvents": true}` 。 -### showStatusBar / hideStatusBar:显隐状态栏 -使用`{"type": "hideStatusBar"}`可以隐藏状态栏。读档或重新开始游戏时,状态栏会重新显示。 -
可以添加`"toolbox": true`来不隐藏竖屏模式下的工具栏。使用`{"type": "showStatusBar"}`会重新显示状态栏。 -### showHero / hideHero:显隐勇士 -使用`{"type": "hideHero"}`可以隐藏勇士和跟随者。使用`{"type": "showHero"}`会重新显示勇士和跟随者。 -
从V2.7开始,可以指定勇士和跟随者们淡入淡出的时间,也支持异步效果。 -### sleep:等待多少毫秒 -等价于RPG Maker中的"等待x帧",不过是以毫秒来计算。
-基本写法:`{"type": "sleep", "time": xxx}` ,其中xxx为指定的毫秒数。 -``` json -[ - {"type": "sleep", "time": 1000}, // 等待1000ms - "等待1000ms后才开始执行这个事件", - {"type": "sleep", "time": 2000, "noSkip": true}, // 等待2000毫秒,且不可被跳过 -] -``` - -![](img/events/30.jpg)
默认的等待事件可以被Ctrl跳过,下面两种情况下不可被跳过: - - 加上`"noSkip": true`后 - - 当前存在尚未执行完毕的异步事件(异步动画除外)。 - -### battle:强制战斗 - -调用battle可强制与某怪物进行战斗(而无需去触碰到它)。 -``` json -[ - {"type": "battle", "id": "blackKing"}, // 强制战斗黑衣魔王 - {"type": "battle", "loc": [2,3]}, // 强制战斗(2,3)点的怪物 -], -``` - -![](img/events/31.jpg) - -从V2.6开始,有两种写法: -- 写id,则视为和空降怪物进行强制战斗,不会执行一些战后事件,也不会隐藏任何点。 -- 写loc(可选,不填默认当前点),则视为和某点怪物进行强制战斗,会隐藏该点并且插入该点战后事件执行。 - -强制战斗不会自动存档,如果战斗失败则立刻死亡。 - -值得注意的是,如果是和某个点的怪物强制战斗,并且该点存在战后事件,执行时会**修改当前点坐标**为目标点。 - -### openDoor:开门 - -调用`{"type":"openDoor"}`可以打开一扇门。 -``` json -[ - {"type": "openDoor", "loc": [3,6], "floorId": "MT1"}, // 打开MT1层的[3,6]位置的门 - {"type": "openDoor", "loc": [3,6]}, // 如果是本层则可省略floorId - {"type": "openDoor", "loc": [3,6], "needKey": true, "async": true} // 打开此门需要钥匙,异步执行 -] -``` - -![](img/events/32.jpg) - -loc指定门的坐标,floorId指定门所在的楼层ID。如果是当前层则可以忽略floorId选项。 - -如果loc所在的点是一个墙壁,则作为暗墙来开启。 - -如果loc所在的点既不是门也不是墙壁,则忽略本事件。 - -needKey是可选的,如果设置为true且门在当前楼层则需要钥匙才能打开此门。如果没有钥匙则跳过此事件。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -!> needKey仅对当前楼层开门有效!跨楼层的门仍然不需要钥匙即可打开,如有需求请自行判定。 - -值得注意的是,如果该点存在开门后事件,执行时会**修改当前点坐标**为目标点。 -### closeDoor:关门 - -从V2.6开始提供了关门事件`{"type": "closeDoor"}`,拥有关门动画和对应的音效。 -``` json -[ - {"type": "closeDoor", "id": "yellowDoor", "loc": [3,6]}, // 给(3,6)点关上黄门 - {"type": "closeDoor", "id": "specialDoor"}, // 不写loc则视为当前点 -] -``` -![](img/events/33.jpg)
id为你要关门的ID,需要是一个合法的门,系统自带支持如下几种: -``` -yellowDoor, blueDoor, redDoor, greenDoor, specialDoor, steelDoor, -yellowWall, blueWall, whiteWall -``` - -如果需要自己添加门,请参考[新增门和对应的钥匙](personalization#新增门和对应的钥匙)。 - -loc可选,为要关的位置,不填默认为当前点。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -关门事件需要保证该点是空地,否则将无视此事件。 - -### changeFloor:楼层切换 -在事件中也可以对楼层进行切换。一个比较典型的例子就是51层魔塔中,勇士在三楼的陷阱被扔到了二楼,就是一个楼层切换事件。
-changeFloor的事件写法大致如下。 -``` json -[ - {"type": "changeFloor", "floorId": "sample0", "loc": [10, 10], "direction": "left", "time": 1000 }, - //后面几项依次为楼层id,楼层位置(这两项为必填);勇士方向可选,切换时间也是可选。 -] -``` -![](img/events/34.jpg)
可以看到,与之前的楼梯、传送门的写法十分类似。 -但是相比那个而言,这个不支持穿透选项。
-direction为可选的,指定的话将使勇士的朝向变成该方向(从V2.7起,支持三种相对转向)
-time为可选的,指定的话将作为楼层切换动画的时间,不指定则使用玩家设定值。 - -**如果time指定为小于100,则视为没有楼层切换动画。** -### changePos:当前位置切换/勇士转向 -有时候我们不想要楼层切换的动画效果,而是直接让勇士从A点到B点。 - -这时候可以用changePos。其参数和changeFloor类似,但少了floorId和time两个选项。 -``` json -[ - {"type": "changePos", "loc": [10,10], "direction": "left"}, // 直接切换勇士的坐标,loc为目标地点,后面勇士换位后方向 - {"type": "changePos", "loc": [10,10]}, // 如无需指定方向则direction可省略 - {"type": "changePos", "direction": "left"} // loc也可省略,只指定direction;此时等价于当前勇士转向到某个方向。 - {"type": "changePos", "direction": ":left"} // 从V2.7开始,支持相对转向,如":left"会让勇士逆时针旋转90° -] -``` - -![](img/events/35.jpg) - -### useItem:使用道具 - -调用`{"type": "useItem"}`可以使用一个道具。 -``` json -[ - {"type": "useItem", "id": "pickaxe"}, // 尝试使用破 - {"type": "useItem", "id": "bomb"}, // 尝试使用炸 - {"type": "useItem", "id": "centerFly"} // 尝试使用飞 -] -``` - -![](img/events/36.jpg) - -使用道具事件会消耗对应的道具。 - -如果当前不可使用该道具(如没有,或者达不到使用条件),则会进行提示并跳过本事件。 - -不可使用“怪物手册”(请使用【呼出怪物手册】事件)或楼层传送器(如果[覆盖楼传事件](personalization#覆盖楼传事件)则可忽视本项)。 -### loadEquip / unloadEquip:装脱装备 -使用`{"type": "loadEquip"}`可以装上一个装备。使用`{"type": "unloadEquip"}`卸下某个装备孔的装备。 -``` json -[ - {"type": "loadEquip", "id": "sword1"}, // 尝试装上铁剑 - {"type": "unloadEquip", "pos": 0}, // 卸下装备孔0的装备 -] -``` - -id必填,为需要装备的ID。 - -使用装备时仍会检查条件(比如装备是否存在,能否装备等等)。 -pos必填,为要卸下的装备孔编号,从0开始。 -### openShop / disableShop:启用或禁用一个全局商店 -使用openShop可以启用一个全局商店。使用disableShop可以永久禁用全局商店直到再次被openShop启用为止。
有关全局商店的说明可参见[全局商店](#全局商店)。 -### follow / unfollow:跟随勇士或取消跟随 -使用 `{"type": "follow"}` 可以让一个npc加入跟随。 -``` json -[ - {"type": "follow", "name": "npc48.png"}, // 将 npc48.png 这个行走图加入跟随 - {"type": "follow", "name": "enemy48.png"}, // 再将另一个行走图加入跟随 - {"type": "unfollow", "name": "npc48.png"}, // 将第一个 npc48.png 行走图取消跟随 - {"type": "unfollow"} // 不填name,表示取消所有跟随 -] -``` -`name` 为要加入或取消跟随的行走图文件名,取消跟随时取第一个,不填则取消所有。
-`name` 所指定的图片必须存在,在全塔属性中的 `images` 中注册,且为一个合法的行走图(宽至少为128像素,高不限) -
您可以随时使用 `core.status.hero.followers` 去查看当前跟随者们的状态,每个跟随者的状态分为“朝向、坐标和是否已停止”三项,其中“是否已停止”为 `true` 表示该队员当前因与其前一个队员重叠,主角下一步行走时该队员将不动。 -### vibrate:画面震动 - -使用 `{"type": "vibrate", "time": 2000, "async": true}` 可以造成画面震动效果。 -
`time` 可以指定震动时间,必须为500毫秒的倍数,且至少要1000毫秒。
-async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -### animate:显示动画 - -我们可以使用 `{"type": "animate"}` 来显示一段动画。 - -有关动画的详细介绍可参见[动画和天气系统](element#动画和天气系统)。 -``` json -[ - {"type": "animate", "name": "yongchang", "loc": [1,3]}, // 在(1,3)显示“咏唱魔法”动画 - {"type": "animate", "name": "zone", "loc": "hero"}, // 在勇士位置显示“领域”动画 - {"type": "animate", "name": "hand"}, // 可以不指定loc,则默认为当前事件点 - {"type": "animate", "async": true}, // 异步,不等待动画绘制完毕 -] -``` - -![](img/events/37.jpg) - -name为动画名,**请确保动画在全塔属性中的animates中被定义过。** -
loc为动画的位置,可以是`[x,y]`表示在(x,y)点显示,也可以是字符串`"hero"`表示跟随勇士显示(就像踩到血网时)。
-loc可忽略,如果忽略则视为事件当前点。 - -如果async指定为true,则不会等待动画绘制完毕,立刻执行下个事件。 - -否则,在动画播放结束后才会继续执行下一个事件。 -
从V2.7开始,增加了一个勾选项表示该坐标是绝对坐标还是在视野中的相对坐标,譬如13×13样板中,勾选此项并填写坐标 `[6,6]` 就能无视大地图,强制在视野正中心播放动画。 -### showImage:显示图片 - -我们可以使用 `{"type": "showImage"}` 来显示一张图片。 -``` json -[ - {"type": "showImage", "code": 1, "image": "bg.jpg", "loc": [231,297], "opacity": 1, "time" : 0}, // 在(231,297)显示bg.jpg - {"type": "showImage", "code": 12, "image": "1.png", "loc": [209,267], "opacity": 0.5, "time" : 1000}, // 在(209,267)渐变显示1.png,渐变时间为1000毫秒,完成时不透明度为0.5,这张图片将遮盖上一张 - {"type": "showImage", "code": 8, "image": "hero.png", "loc": [349,367], "opacity": 1, "time" : 500, "async": true}, // 在(209,267)渐变显示hero.png,渐变时间为500毫秒,异步执行;这张图片将被上一张遮盖 - {"type": "showImage", "code": 10, "image": "hero.png", "sloc": [100,100,100,100], "loc": [0,0,100,100], "opacity": 1, "time": 0} // 截取原图的一部分绘制到画布上的一部分。 -] -``` - -![](img/events/38.jpg) - -code为图片编号,如果两张图片重叠,编号较大会覆盖编号较小的。该值需要在1~50之间。 - -图片编号的真正意义,请参阅[个性化](personalization)。 - -image为图片名。**请确保图片在全塔属性中的images中被定义过。** - -sloc为可选项;如果设置了则是个2或4元组,代表裁剪原始图片的左上角像素位置和宽高。 - -loc为2或4元组,代表要绘制的画布上的左上角像素位置和宽高。 - -opacity为图片不透明度,在0~1之间,默认值为1,即不透明。 - -time为渐变时间,默认值为0,即不渐变直接显示。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -从V2.7起,提供了“翻转”下拉框,您可以将图片左右翻转、上下翻转或旋转180°。UI绘制事件中的“绘制图片”同理。 -### showTextImage:显示图片化文本 - -我们可以使用 `{"type": "showTextImage"}` 以图片的方式显示文本。 -``` json -[ - {"type": "showTextImage", "code": 1, "text": "第一排\n第二排\n\n空行后的一排", "loc": [231,297], "opacity": 1, "time" : 0}, // 在(231,297)显示"第一排\n第二排\n\n空行后的一排" -] -``` - -code为图片编号,如果两张图片重叠,编号较大会覆盖编号较小的。该值需要在1~50之间。 - -text为要显示的文本。默认行宽为416(15×15样板为480)。 - -loc为图片左上角坐标,以像素为单位进行计算。 - -opacity为图片不透明度,在0~1之间,默认值为1,即不透明。 - -lineHeight为可选项,代表行距。默认为1.4。 - -time为渐变时间,默认值为0,即不渐变直接显示。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -文本通过图片的方式显示后,即视为一张正常图片,可以被清除或者移动。 - -从V2.7开始,和普通的显示图片一样,支持三种翻转效果。 -### hideImage:清除图片 - -我们可以使用 `{"type": "hideImage"}` 来清除一张图片。 -``` json -[ - {"type": "hideImage", "code": 1, "time" : 0}, // 使1号图片消失 - {"type": "hideImage", "code": 12, "time" : 1000}, // 使12号图片渐变消失,时间为1000毫秒 -] -``` - -time为渐变时间,默认值为0,即不渐变直接消除。 - -code为显示图片时输入的图片编号。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -### showGif:显示动图 - -我们可以使用 `{"type": "showGif"}` 来显示一张图片。 -``` json -[ - {"type": "showGif", "name": "timg.gif", "loc": [231,297]}, // 在(231,297)显示一张动图 - {"type": "showGif"} // 如果不指定name则清除所有动图。 -] -``` - -name为图片名。**请确保图片在全塔属性中的images中被定义过。** - -loc为动图左上角坐标,以像素为单位进行计算。 - -如果不指定name则清除所有显示的动图。 - -### moveImage:图片移动 - -我们可以使用 `{"type": "moveImage"}` 来造成图片移动,淡入淡出等效果。 -``` json -[ - {"type": "moveImage", "code": 1, "to": [22,333], "opacity": 1, "time": 1000}, // 将1号图片移动到(22,333),动画时间为1000ms - {"type": "moveImage", "code": 12, "opacity": 0.5, "time": 500}, // 将二号图片的透明度变为0.5,动画时间500ms - {"type": "moveImage", "code": 1, "to": [109,167], "opacity": 0, "time": 300, "async": true}, // 将1号图片移动到(109,167),透明度设为0(不可见),动画时间300ms,异步执行 -] -``` - -![](img/events/39.jpg) - -code为图片编号。该值需要在1~50之间。 - -to为终点图片左上角坐标,以像素为单位进行计算,不填写则视为当前图片位置。 - -opacity为完成时图片不透明度,移动过程中逐渐变化。在0~1之间。 - -time为总移动的时间。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -### setCurtain:更改画面色调 - -我们可以使用 `{"type": "setCurtain"}` 来更改画面色调。 -``` json -[ - {"type": "setCurtain", "color": [255,255,255,0.6], "time": 1000}, // 更改画面色调为纯白,不透明度0.6,动画时间1000毫秒 - {"type": "setCurtain", "color": [0,0,0], "async": true}, // 更改画面色调为纯黑,不透明度1,不指定动画时间(使用默认时间),且异步执行 - {"type": "setCurtain"} // 如果不指定color则恢复原样。 -] -``` - -![](img/events/40.jpg) - -color为需要更改画面色调的颜色。它是一个数组,分别指定目标颜色的R,G,B,A值。 -- 常见RGB颜色: 纯黑[0,0,0],纯白[255,255,255],纯红[255,0,0],等等。 -- 第四元为Alpha值,即不透明度,为一个0到1之间的数。可以不指定,则默认为Alpha=1 - -如果color不指定则恢复原样。 - -time为可选的,如果指定,则会作为更改画面色调的时间。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -从V2.7开始,色调、天气和bgm的更改都提供了“持续到下个本事件”勾选项,勾选此项后,设置的结果将分别计入 `flags.__color__ , flags.__weather__ , flags.__bgm__` ,也会计入存档,并无视楼层切换带来的色调、天气和bgm变化,直到再次遇到本事件。但您也可以随时手动干预或清除这三个 `flag` -### screenFlash:画面闪烁 - -我们可以使用 `{"type": "screenFlash"}` 来进行画面闪烁。 -``` json -[ - {"type": "screenFlash", "color": [255,255,255,0.6], "time": 500, "times": 1}, // 闪光为白色,不透明度0.6,动画时间1000毫秒 - {"type": "screenFlash", "color": [255,0,0,1], "time": 100, "times": 2, "async": true}, // 闪光为红色,强度最大,动画时间100毫秒,闪烁两次且异步执行 -] -``` - -color为闪光的颜色。它是一个数组,分别指定目标颜色的R,G,B,A值。 -- 常见RGB颜色: 纯黑[0,0,0],纯白[255,255,255],纯红[255,0,0],等等。 -A即闪光的不透明度,为一个0到1之间的数,值越高闪烁效果越强。默认为1 - -time为闪烁时间,默认值为500 - -times为闪烁次数,两次闪烁会连续进行,默认值为1 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -### setWeather:更改天气 - -我们可以使用 `{"type": "setWeather"}` 来更改天气。 -``` json -[ - {"type": "setWeather", "name": "rain", "level": 6}, // 更改为雨天,强度为6级 - {"type": "setWeather", "name": "snow", "level": 3}, // 更改为雪天,强度为3级 - {"type": "setWeather"} // 更改回晴天 -] -``` -name为天气名。起初只支持 `rain` 和 `snow` ,即雨天和雪天。从V2.5.3开始,也支持雾天 `fog` - -level为天气的强度等级,在1-10之间。1级为最弱,10级为最强。 - -如果想改回晴天则直接不加任何参数。 -### move:让某个NPC/怪物移动 - -如果我们需要移动某个NPC或怪物,可以使用`{"type": "move"}`。 - -下面是该事件常见的写法: -``` json -[ - {"type": "move", "time": 750, "loc": [x,y], "steps": [ - // 动画效果,time为移动和淡出速度(比如这里每750ms一步),loc为位置可选,steps为移动数组 - "right", "right", "down" // 向右两格,向下一格 - ], "keep": true, "async":true }, // keep可选,如果为true则不消失,否则渐变消失;async可选,如果为true则异步执行。 -] -``` - -![](img/events/41.jpg) -
time选项必须指定,为每移动一步和淡出所需要用到的时间。 - -loc为需要移动的事件位置。可以省略,如果省略则移动本事件。 - -steps为一个数组,其每一项是`up, down, left, right`之一,表示这一步应该朝哪个方向走。 -
对于有 `faceIds` 的NPC,也支持 `forward, backward` ,表示前进和后退。
-keep为一个可选项,代表该事件移动完毕后是否消失。如果该项指定了并为true,则移动完毕后将不消失,否则以动画效果消失。 - -值得注意的是,当调用move事件时,实际上是使事件脱离了原始地点。为了避免冲突,规定:move事件会自动在该点调用 `core.removeBlock()` 函数。换句话说,当move事件被调用后,该点本身的事件将被永久删除。 - -如果指定了 `"keep": true` ,则相当于会在目标地点触发一个 `setBlock` 和一个 `show` 事件;
如需能继续对话交互请在目标地点再写事件。
-阻击属性的移动效果就是这样,推箱子和阻击类似但目标点只 `setBlock` 不 `show` ,请自行注意可能的隐患。
-如果想让move后的NPC/怪物仍然可以被交互,需采用如下的写法: -``` json -"4,3": [ // [4,3]是一个NPC,比如小偷 - {"type": "move", "time": 750, "steps": [ // 向上移动两格,每步750毫秒 - "up", "up" - ], "keep": true}, // 移动完毕后不消失 -], -"4,1": { // [4,1]为目标地点 - "enable": false, // 初始时需要是禁用状态,被show调用后将显示出来 - "data": [ - "\t[杰克,thief]这样看起来就好像移动过去后也可以被交互。" - ] -} -``` - -![](img/events/42.jpg) - -即,在移动的到达点指定一个事件,然后move事件中指定"keep":true,然后就可以触发目标点的事件了。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 -### moveHero:无视地形移动勇士 -如果我们需要无视地形移动勇士,可以使用`{"type": "moveHero"}`。下面是该事件常见的写法: -``` json -"x,y": [ // 实际执行的事件列表 - {"type": "moveHero", "time": 750, "async": true, "steps": [// 动画效果,time为移动速度(比如这里每750ms一步),steps为移动数组 - "down", "right", "forward", "backward" // 向下、右、前、后各走一步 - ]}, -] -``` - -可以看到,和上面的move事件几乎完全相同,除了不能指定loc,且少了keep选项。 - -勇士的steps也允许`forward`和`backward`,即前进和后退。 - -不过值得注意的是,用这种方式移动勇士的过程中将无视一切地形,无视一切事件,中毒状态也不会扣血。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 -### moveAction:勇士前进一格或撞击 -如果我们需要像事件外一样移动一步,可以使用`{"type": "moveAction"}`。 -
用这种办法移动时会检查通行性,也会正常触发阻激夹域捕毒和地形效果,如果不可通行则会去撞击(如开门打怪) -### jump:让某个NPC/怪物跳跃 - -如果我们需要移动某个NPC或怪物,可以使用`{"type": "jump"}`。 - -下面是该事件常见的写法: -``` json -[ - {"type": "jump", "from": [3,6], "to": [2,1], "time": 750, "keep": true, "async": true}, -] -``` -from为需要跳跃的事件起点。可以省略,如果省略则跳跃本事件。 - -to为要跳跃到的坐标。可以省略,如果省略则跳跃到当前坐标。 - -time选项必须指定,为全程跳跃所需要用到的时间。 - -keep为一个可选项,同上代表该跳跃完毕后是否不消失。如果该项指定了并为true,则跳跃完毕后不会消失,否则以动画效果消失。 - -如果指定了`"keep": true`,则相当于会在目标地点触发一个 `setBlock` 和一个 `show` 事件;
-和移动一样,如需能继续对话交互请在目标地点再写事件。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -### jumpHero:跳跃勇士 - -如果我们需要跳跃勇士,可以使用`{"type": "jumpHero"}`。 - -下面是该事件常见的写法: -``` json -[ - {"type": "jump", "loc": [3,6], "time": 750, "async": true}, -] -``` - -loc为目标坐标,可以忽略表示原地跳跃(请注意是原地跳跃而不是跳跃到当前事件点)。 - -time选项为该跳跃所需要用到的时间。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -### playBgm:播放背景音乐 - -使用playBgm可以播放一个背景音乐。 - -使用方法:`{"type": "playBgm", "name": "bgm.mp3"}` -
音乐文件放在 `project\sounds` 文件夹,文件名在全塔属性中注册,不得使用中文。
-目前支持 `mp3/ogg/wav` 格式的音乐播放,不支持 `mid` 格式。 - -从V2.6.3开始,还提供了keep项。如果此项为真,则会记录该bgm,并且持续到下次调用本事件位置(楼层切换不改变bgm,读档也有效)。 - -从V2.7开始,还提供了“从第几秒开始”的参数,可加以利用。 - -有关BGM播放的详细说明参见[背景音乐](element#背景音乐) - -### pauseBgm:暂停背景音乐 - -使用`{"type": "pauseBgm"}`可以暂停背景音乐的播放。 - -### resumeBgm:恢复背景音乐 - -使用`{"type": "resumeBgm"}`可以恢复背景音乐的播放。 - -从V2.7开始,还提供了一个勾选项,您可以选择从上次暂停的位置继续播放。 -### loadBgm:预加载一个背景音乐 - -使用loadBgm可以预加载一个背景音乐。 - -使用方法:`{"type": "loadBgm", "name": "bgm.mp3"}` - -有关BGM播放的详细说明参见[背景音乐](element#背景音乐) - -### freeBgm:释放一个背景音乐的缓存 - -使用freeBgm可以预加载一个背景音乐。 - -使用方法:`{"type": "freeBgm", "name": "bgm.mp3"}` - -### playSound:播放音效 - -使用playSound可以立刻播放一个音效。 - -使用方法:`{"type": "playSound", "name": "item.mp3"}` -
音乐文件放在 `project\sounds` 文件夹,文件名在全塔属性中注册,不得使用中文。
-从V2.6开始,也可以加`"stop": true`来停止之前正在播放的音效。 - -### stopSound:停止所有音效 - -使用`{"type": "stopSound"}`可以停止所有音效。 - -这在人物对话音效时很有用。 - -### setVolume:设置音量 - -使用setVolume可以设置音量大小。 - -使用方法: `{"type": "setVolume", "value": 90, "time": 500, "async": true}` - -![](img/events/43.jpg) -
`value` 为音量大小,在0到100之间(玩家设置值为这个值的平方根),默认为100。设置后,BGM将使用该音量进行播放。SE的音量大小不会发生改变。 - -可以设置time为音量渐变时间。 - -async可选,如果为true则会异步执行(即不等待当前事件执行完毕,立刻执行下一个事件)。 - -### win:获得胜利 -`{"type": "win", "reason": "xxx"}` 将会直接调用脚本编辑中的 `win` 函数,并将 `reason` 作为结局传入。
-该事件会显示获胜页面,并重新游戏。 - -可以增加`"norank": 1`来表示该结局不计入榜单。 - -!> 如果`reason`不为空,则会以reason作为获胜的结局! - -从V2.6.6起,也提供了一个“不结束游戏”勾选项(但录像依然会停止录制),您可以勾选它然后做一些结局演出。 -### lose:游戏失败 -`{"type": "lose", "reason": "xxx"}` 将会直接调用脚本编辑中的lose函数,并将reason作为参数传入。
-该事件会显示失败页面,并重新开始游戏。 - -### restart:直接回到标题界面 - -`{"type": "restart"}` 会中断一切执行的事件,并直接直接返回标题界面。 - -### callBook:呼出怪物手册 - -`{"type": "callBook"}` 可以呼出怪物手册,玩家可以自由查看当前楼层怪物数据和详细信息。 - -返回游戏后将继续执行后面的事件。没有怪物手册或在录像播放中,则会跳过本事件。 - -### callSave:呼出存档界面 - -`{"type": "callSave"}` 可以呼出存档页面并允许玩家存一次档。 - -在玩家进行一次存档,或者直接点返回游戏后,将接着执行后面的事件。录像播放将会跳过本事件。 - -### autoSave:自动存档 - -`{"type": "autoSave"}` 可以立刻进行一次自动存档。录像播放不会跳过本事件。 - -### callLoad:呼出读档界面 - -`{"type": "callLoad"}` 可以呼出读档页面并允许玩家进行读档。 - -如果玩家没有进行读档而是直接返回游戏,则会继续执行后面的事件。录像播放将会跳过本事件。 - -### input:接受用户输入数字 - -使用`{"type": "input"}`可以接受用户的输入的数字。 -``` json -[ - {"type": "input", "text": "请输入一个数"}, // 显示一个弹窗让用户输入数字 - "你刚刚输入的数是${flag:input}" // 输入结果将被赋值为flag:input -] -``` - -![](img/events/44.jpg) - -text为提示文字,可以在这里给输入提示文字。这里同样可以使用${ }来计算表达式的值。 - -当执行input事件时,将显示一个弹窗,并提示用户输入一个内容。 -
!> 该事件只能接受非负整数输入,所有非法的输入将全部变成 `0` 。例如用户输入“你好”或者 `-3` ,都将实际得到 `0` 。
-输入得到的结果将被赋值给flag:input,可以供后续if来进行判断。 - -### input2:接受用户输入文本 - -类似于input事件,使用`{"type": "input2"}`可以接受用户的输入的文本。 -``` json -[ - {"type": "input2", "text": "请输入你的ID"}, // 显示一个弹窗让用户输入文本 - "你好,${flag:input},欢迎来到本塔" // 输入结果将被赋值为flag:input -] -``` - -![](img/events/45.jpg) - -text为提示文字,可以在这里给输入提示文字。这里同样可以使用${ }来计算表达式的值。 - -当执行input2事件时,将显示一个弹窗,并提示用户输入一个内容。 - -该事件可以接收任何形式的文本输入,包括中文,空格,标点符号等等。如果用户点击取消按钮,则视为空字符串。 - -输入得到的结果也将被赋值给flag:input,可以供后续使用。 - -### if:条件判断 -使用`{"type": "if"}`可以对条件进行判断,根据判断结果将会选择不同的分支执行。其大致写法如下: -``` json -[ - {"type": "if", "condition": "...", // 测试某个条件 - "true": [ // 条件成立则执行true里面的事件 - - ], - "false": [ // 条件不成立则执行false里的事件 - - ] - }, -] -``` -我们可以在condition中给出一个表达式(能将`status:xxx, item:xxx, flag:xxx`等来作为参数),并进行判断是否成立。 - -如果条件成立,则将继续执行`"true"`中的列表事件内容。 - -如果条件不成立,则将继续执行`"false"`中的列表事件内容。 - -例如下面这个例子,每次将检查你的攻击力是否大于500,不是的场合将给你的攻击力加100点。 -``` json -[ - {"type": "if", "condition": "status:atk>500", // 判断攻击力是否大于500 - "true": [ // 条件成立则执行true里面的事件 - "你的攻击力已经大于500了!", - {"type": "exit"} // 立刻结束本事件 - ], - "false": [ // 条件不成立则执行false里的事件 - "你当前攻击力为${status:atk}, 不足500!\n给你增加100点攻击力!", - {"type": "setValue", "name": "status:atk", "operator": "+=", "value": "100"}, - ] // 攻击力加100, 接着会执行trigger事件 - }, - {"type": "trigger", "loc": ["core.nextX()","core.nextY()"]} -] // 立刻重新触发勇士面前的本事件, 直到攻击力大于500后结束 -``` - -![](img/events/46.jpg) - -需要额外注意的几点: - -- 给定的表达式(condition)一般需要返回true或false。 -- `0、null、undefined、NaN`、空字符串,也会被理解为 `false` -- `flag:xxx` 可取用一个自定义变量或flag。如果从未设置过该flag,则其值默认为0。 -- 即使条件成立的场合不执行事件,对应的 `true` 数组也需要存在,不过简单的留空就好。 -- if可以不断进行嵌套,一层套一层;如成立的场合再进行另一个if判断等。 -- if语句内的内容执行完毕后将接着其后面的语句继续执行。 - - -### switch:多重条件分歧 - -使用`{"type": "switch"}`可以比较判别值和不同分支的条件,根据判断结果选择不同的分支执行。 - -其大致写法如下: -``` json -[ - {"type": "switch", "condition": "...", // 计算某个表达式 - "caseList": [ - {"case": "a", "action": [// 若表达式的值等于a则执行该处事件 - - ]}, - {"case": "b", "nobreak": true, "action": [// 若表达式的值等于b则执行该处事件,不跳出 - - ]}, - {"case": "default", "action": [ // 没有条件成立则执行该处里的事件 - - ]} - ] - }, -] -``` - -我们可以在condition中给出一个表达式(能将`status:xxx`, `item:xxx`, `flag:xxx`来作为参数),并计算它的值 - -如果某条件中的值与其相等,则将执行其对应的列表事件内容。 - -如果没有符合的值,则将执行`default`中的列表事件内容。 - -nobreak是可选的,如果设置,则在当前条件满足并插入事件后,不跳出多重分歧,而是无视接下来的一切条件,挨个插入事件,直到插入完一组没有nobreak的事件,或抵达多重分歧的最底部。 - -例如下面这个例子,将检查当前游戏难度并赠送不同属性。 -``` json -[ - {"type": "switch", "condition": "flag:hard", // 判断当前游戏难度 - "caseList": [ - {"case": "0", "action": [// 若表达式的值等于0则执行该处事件 - "当前为简单难度,赠送100点攻防!", - {"type": "setValue", "name": "status:atk", "value": "status:atk+100"}, - {"type": "setValue", "name": "status:def", "value": "status:def+100"}, - ]}, - {"case": "1", "action": [// 若表达式的值等于1则执行该处事件 - "当前为普通难度,赠送50点攻防!", - {"type": "setValue", "name": "status:atk", "value": "status:atk+50"}, - {"type": "setValue", "name": "status:def", "value": "status:def+50"}, - ]}, - {"case": "default", "action": [ // 其他难度下不赠送属性 - - ]} - ] - }, -] -``` - -![](img/events/47.jpg) - -需要额外注意的几点: - -- 各个条件分支的判断是顺序执行的,因此若多个分支的条件都满足,将只执行最靠前的分支。 - - 同理,请不要在`default`分支后添加分支,这些分支将不可能被执行。 -- `default`分支并不是必要的,如果删除,则在没有满足条件的分支时将不执行任何事件。 -- 即使某个场合不执行事件,对应的action数组也需要存在,不过简单的留空就好。 -- switch语句内的内容执行完毕后将接着其后面的语句继续执行。 - -另外由于`case`中的内容是会被计算的,因此如下写法也是合法的 -```json -[ - {"type": "switch", "condition": "true", // 条件:某一项为真时 - "caseList": [ - {"case": "flag:a==1", "action": [ // 如果 flag:a == 1 - "走进了 flag:a==1 分支!" - ]}, - {"case": "flag:b>=3", "action": [ // 如果 flag:a != 1 && flag:b >= 3 - "走进了 flag:a!=1 && flag:b>=3 分支!" - ]}, - {"case": "default", "action": [ // 上述两条均不成立 - "上述两条均不成立" - ]} - ] - }, -] -``` - -![](img/events/48.jpg) - -### choices:给用户提供选项 - -choices是一个很麻烦的事件,它将弹出一个列表供用户进行选择。 - -当用户做出了不同的选择,可以有着不同的分支处理。 - -其完全类似于RPG Maker中的"显示选择项","XX的场合",只不过同样是需要使用数组来定义。 - -其大致写法如下: -``` json -[ - {"type": "choices", "text": "...", // 提示文字 - "choices": [ - {"text": "选项1文字", "action": [ - // 选项1执行的事件 - ]}, - {"text": "选项2文字", "color": [255,0,0,1], "action": [ - // 选项2执行的事件 - ]}, - {"text": "选项3文字", "icon": "fly", "action": [ - // 选项3执行的事件 - ]}, - ] - }, -] -``` - -其中最外面的"text"为提示文本。同上面的`"type":"text"`一样,支持`${}`表达式的计算,和\t显示名称、图标,\r更改颜色。text可省略,如果省略将不显示任何提示文字。 - -choices为一个数组,其中每一项都是一个选项列表。 - -每一项的text为显示在屏幕上的选项名,也支持${}的表达式计算,但不支持`\t[]`的显示。 - -action为当用户选择了该选项时将执行的事件。 - -color为可选的,可以是一个字符串(#FF0000),或者一个RGBA数组([255,0,0,1])。 - -icon是可选的,如果设置则会在选项前绘制图标,其可以是一个有效的ID,或者`core.statusBar.icons`中的系统图标。 - -选项可以有任意多个(没有提示信息时最多为13或15个),但一般不要超过6个,否则屏幕可能塞不下。 - -从V2.6.3开始,每个子选项允许附加一个“出现条件”,从而做出类似“怒气值满才显示开大招按钮”的效果。 -### confirm:显示确认框 - -`{"type": "confirm"}`将提供一个确认框供用户选择,其基本写法如下: -```json -[ - {"type": "confirm", "text": "...", // 提示文字 - "default": false, // 是否默认选中【确定】 - "yes": [ - // 点击确定时执行的事件 - ], - "no": [ - // 点击取消时执行的事件 - ] - }, -] -``` - -text为必填项,代表提示的文字,支持${}的表达式计算和\n的手动换行。 - -text暂时不支持自动换行、变色\r、图标绘制\i等效果。如有需求请使用choices事件。 - -default可选,如果为true则显示选择项时默认选中【确定】,否则默认选中【取消】。 - -yes和no均为必填项,即用户点击确认或取消后执行的事件。 - -从V2.7开始,“选择项”、“确认框”和后面要讲的“等待用户操作”事件,都允许提供一个限制时间,效果是如果玩家在若干毫秒内不做出选择,就视为什么都没选,并继续后面的事件。 -
您可以使用这个功能去制作如《新新魔塔2》那样的QTE战斗。 -### while:前置条件循环 -从V2.2.1开始,我们提供了循环处理( `while` 事件)。其大致写法如下: -``` json -[ - {"type": "while", "condition": "...", // 循环测试某个条件 - "data": [ // 条件成立则执行data里面的事件 - - ] - }, -] -``` -它和 `if` 事件非常相似,最大的区别是,每次 `data` 事件列表执行完毕后,都将再次测试 `condition` , -
如果还为 `true` ,则将再次执行 `data` 的内容。下面是一个输出1到10之间的数字,每隔1秒显示一个的例子。 -``` json -[ - {"type":"while", "condition": "flag:i<=10", // 循环处理;注意flag未设置则默认为0 - "data":[ - {"type": "setValue", "name": "flag:i", "operator": "+=", "value": "1"}, // 递增i - "${flag:i}", // 输出i - {"type": "sleep","time":1000}, // 等待1秒 - ] - }, -] -``` - -![](img/events/49.jpg) - -### dowhile:后置条件循环 -`type:dowhile`可以制作一个后置条件循环。其写法与参数和 `type:while` 完全一致,不过与其不同的是,
-会先执行一次事件列表(即首次执行是无条件的),再对条件进行判定,和脚本中的 `do {...} while (...);` 一样。 -![](img/events/50.jpg) -### for:计数循环 -从V2.7开始,`type:for` 可以制作一个计数循环,其基本写法为: -``` json -[ - {"type": "for", "name": "temp:A-Z", "from": "...", "to": "...", "step": "...", "data": [ - // 可以在这里引用临时变量A-Z,循环执行一些内容 - ]}, -] -``` -其中 `name` 为循环的计数器,只能使用临时变量 `A-Z` ,`from` 和 `to` 为两个表达式,表示计数器的初始值和边界值 - -`step` 为每轮循环结束后计数器的增量,也允许填表达式甚至负数,填负数的话 `from` 当然就要比 `to` 更大或相等了。 - -当计数器以正步长越过(即大于)边界值时,循环终止;当计数器以负步长越过(即小于)边界值时,循环也终止。 - -下面是13×13小地图中,模拟大黄门钥匙的使用效果: -![大黄门钥匙](./img/bigKey.png) -### forEach:数组迭代 -从V2.7开始,`type: forEach` 可以循环迭代一个数组,逐项读取其每个元素,其基本写法为: -``` json -[ - {"type": "forEach", "name": "temp:A-Z", "list": [..., ..., ..., ...], "data": [ - // 可以在这里引用临时变量A-Z,循环执行一些内容 - ]}, -] -``` -和 `for` 一样只能使用临时变量,实际执行时,每轮循环会从 `list` 的开头移除第一项,代入临时变量,直到 `list` 变空。 - -要注意的是,`list` 中的字符串不会被自动解释为那些带冒号的缩写量,你需要手动调用 `core.calValue()` 去求值: -![数组迭代](./img/forEach.png) -这个事件会让勇士说出“我的`status:atk`属性为`10`”这样的句子。 -### break:跳出当前循环或公共事件 -使用 `{"type": "break"}` 可以跳出当前循环或公共事件。
-跳出公共事件的原理是,公共事件实际上是作为一个“条件为 `false` 的后置条件循环”去执行的。
-!> 如果break事件不在任何循环或公共事件中被执行,则和exit等价,即会立刻结束当前事件! -### continue:提前结束本轮循环 -使用 `{"type": "continue"}` 可以提前结束本轮循环。上面的输出例子也可以这么写: -``` json -[ - {"type":"while", "condition": "true", // 循环处理;永远为真 - "data":[ - {"type": "setValue", "name": "flag:i", "operator": "+=", "value": "1"}, // 递增i - "${flag:i}", // 输出i - {"type": "sleep","time":1000}, // 等待1秒 - {"type": "if", "condition": "flag:i<10", // 测试i是否小于10 - "true": [{"type": "continue"}], // 是,提前结束本轮循环,避免被后面的break跳出 - "false": [] - }, - {"type": "break"}, // 跳出循环 - ] - }, -] -``` - -![](img/events/51.jpg) -
!> 如果continue事件不在任何循环或公共事件中被执行,则和exit等价,即会立刻结束当前事件! -### wait:等待用户操作 - -使用 `{"type": "wait"}` 可以等待用户进行操作(如点击、按键等)。 - -当用户执行操作后: -- 如果是键盘的按键操作,则会将flag:type置为0,并且把flag:keycode置为按键的keycode。 -- 如果是屏幕的点击操作,则会将flag:type置为1,并且设置flag:x和flag:y为点击的位置坐标,flag:px和flag:py为点击的像素坐标。 - -下面是一个while事件和wait合并使用的例子,这个例子将不断接收用户的点击或按键行为,并输出该信息。 -如果用户按下了ESC或者点击了屏幕正中心,则退出循环。 -``` json -[ - {"type": "while", "condition": "true", // 永久循环 - "data": [ - {"type": "wait"}, // 等待用户操作 - {"type": "if", "condition": "flag:type==0", // flag:type==0,键盘按键 - "true": [ - "你当前按键了,keycode是${flag:keycode}", - {"type": "if", "condition": "flag:keycode==27", // ESC的keycode是27 - "true": [{"type": "break"}], // 跳出循环 - "false": [] - } - ], - "false": [ // flag:type==1,鼠标点击 - "你当前点击屏幕了,位置坐标是[${flag:x},${flag:y}],像素坐标是[${flag:px},${flag:py}]", - {"type": "if", "condition": "flag:x==6 && flag:y==6", // 点击(6,6) - "true": [{"type": "break"}], // 跳出循环 - "false": [] - } - ] - } - ] - } -] -``` - -![](img/events/52.jpg) - -从V2.6.6开始,也允许直接在`type:wait`中增加`data`项判定按键或点击坐标。 -```json -[ - {"type": "wait", "data": [ - {"case": "keyboard", "keycode": "13,32", "action": [ - {"type": "comment", "text": "按下回车(keycode=13)或空格(keycode=32)时执行此事件"}, - ]}, - {"case": "mouse", "px": [0,32], "py": [0,32], "action": [ - {"type": "comment", "text": "当点击地图左上角时执行此事件"}, - ]}, - ]}, -] -``` - -![](img/events/52.png) - -`data`是一个数组,每一项中,case只能为`keyboard`和`mouse`二选一,分别对应键盘和鼠标(即`type=0`和`type=1`)。 - -如果是键盘,则可以指定`keycode`为键盘的按键内容;否则指定`px`和`py`为点击的像素区间。 - -action为如果满足该条件时应该执行的事件列表。 - -从V2.7开始,提供了“限制时间”,如果玩家在若干毫秒内不做出响应,就会跳过这些场合,直接继续执行后面的事件。而 `flag:type` 会被置为 `-1` -### waitAsync:等待所有异步事件执行完毕 - -上面有很多很多的异步事件(也就是执行时不等待执行完毕)。 - -由于录像是加速播放,且会跳过`{"type":"sleep"}`(等待X毫秒)事件;因此异步行为很有可能导致录像播放出错。 - -例如,异步移动一个NPC去某格,然后等待X毫秒,再勇士走过去对话; -但是录像播放中,等待X毫秒的行为会被跳过,因此勇士可能走过去时异步还未执行完成,导致录像出错。 - -我们可以使用`{"type":"waitAsync"}`来等待所有异步事件执行完毕。 - -该事件会进行等待,直到所有可能的异步事件(异步动画除外)执行完毕。 - -### previewUI:UI绘制并预览 - -此项可在地图编辑器中预览UI界面的绘制效果。 - -在编辑器中将会把此项包含的所有UI绘制事件进行绘制从而可以进行预览。 - -值得注意的是,在游戏中,UI绘制事件都是绘制在uievent层上的。 - -### clearMap:清除画布 - -UI绘制事件。 - -`{"type": "clearMap"}`可以清除`uievent`画布的内容。 -```json -[ - {"type": "clearMap", "x": 0, "y": 0, "width": "flag:width", "height": 416}, // 清除画布的一部分 - {"type": "clearMap"}, // 清空并删除画布 -] -``` - -x, y, width, height均可选,表示要清除的坐标和长宽。也可以使用`flag:xxx`。 - -如果存在某一项不填则会清空全部画布并删除。 - -### setAttribute:设置画布属性 - -UI绘制事件。 - -此项可以设置`uievent`画布的各项属性。 -```json -[ - {"type": "setAttribute", "font": "17px Verdana", "fillStyle": [255,0,0,1]}, -] -``` - -可以选择性的设置如下几项内容: -- `font`:字体,必须是`[italic] [bold] 14px Verdana`这种形式 -- `fillStyle`:填充样式,必须是三元组RGB或四元组RGBA -- `strokeStyle`:边框样式,必须是三元组RGB或者四元组RGBA -- `lineWidth`:线宽度,必须是正整数 -- `alpha`:不透明度,必须是0到1之间的浮点数 -- `align`:对齐方式,只能是`left`, `center`, `right`,分别代表左对齐,居中和右对齐 -- `baseline`:基准线,只能是`top`, `middle`, `alphabetic`, `bottom`, `ideographic`, `hanging`,分别代表顶部,居中,标准值、底部、中文和悬挂。 -- `z`:画布的z值,必须是正整数。初始创建时画布的z值是135。请注意,闪烁光标所在画布的z值永远比该画布大1。 - -### fillText:绘制文本 - -UI绘制事件。 - -此项可以绘制一行文本。 -```json -[ - {"type": "fillText", "text": "要绘制的文本", "x": 10, "y": 20, "maxWidth": 50} -] -``` - -text必填,为要绘制的文本,支持`${}`的写法,不支持一切转义字符或换行符。 - -x和y必填,为要绘制的左上角坐标。请使用`setAttribute`来设置绘制的对齐方式和基准线。 - -style可选,如果设置需要是三元组RGB或四元组RBGA,代表绘制样式。 - -font可选,如果设置则是要绘制的字体。 - -maxWidth可选,如果设置且不为0,则代表要绘制的最大宽度;超过此宽度会自动放缩。 - -### fillBoldText:绘制描边文本 - -UI绘制事件。 - -此项可以绘制一行描边文本。 -```json -[ - {"type": "fillText", "text":"要绘制的描边文本", "x": 10, "y": 20, "style": [255,0,0,1]} -] -``` - -text必填,为要绘制的文本,支持`${}`的写法,不支持一切转义字符或换行符。 - -x和y必填,为要绘制的左上角坐标。请使用`setAttribute`来设置绘制的对齐方式和基准线。 - -style可选,如果设置需要是三元组RGB或四元组RBGA,代表绘制样式。 - -font可选,如果设置则是要绘制的字体。 - -从V2.7开始,可以选择描边的颜色,初始为黑色。描边原理是先用描边色绘制4份一样的偏移文本,再以文本色覆盖。 -### drawTextContent:绘制多行文本 - -UI绘制事件。 - -此项可以绘制多行文本。 -```json -[ - {"type": "drawTextContent", "text": "要绘制的多行文本", "left": 10, "top": 20, "maxWidth": 100} -] -``` - -text必填,为要绘制的文本,支持所有的文字效果(如\n,${},\r,\\i,\\c,\\d,\\e等),但不支持支持\t和\b的语法。 - -left和top必填,为要绘制的起始像素坐标。实际绘制时会将textBaseline设置为'top',因此只需要考虑第一个字的左上角位置。 - -maxWidth可选,为单行最大宽度,超过此宽度将自动换行,不设置不会自动换行。 - -color可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。如果不设置则使用剧情文本设置中的正文颜色。 - -bold可选,是否粗体。如果不设置默认为false。 - -align可选,文字对齐方式,仅在maxWidth设置时有效,默认为'left'。 - -fontSize可选,为字体大小,如果不设置则使用剧情文本设置中的正文字体大小。 - -lineHeight可选,绘制的行距值,如果不设置则使用fontSize*1.3(即1.3倍行距)。 - -此项不支持字体样式的设置,使用的是全塔属性中的全局字体;如有需要请使用“设置全局属性”事件来设置字体样式。 -### fillRect:绘制实心矩形 -UI绘制事件。此项可以绘制一个实心矩形。 -```json -[ - {"type": "fillRect", "x": 100, "y": 100, "width": 120, "height": 120, "style": [255,0,0,1]} -] -``` - -x, y, width, height必填,为要绘制的起点坐标和宽高;也可以用`flag:xxx`。 - -color可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。 -### strokeRect:绘制空心矩形 -UI绘制事件。此项可以绘制一个空心矩形。 -```json -[ - {"type": "strokeRect", "x": 100, "y": 100, "width": 120, "height": 120, "style": [255,0,0,1], "lineWidth": 4} -] -``` - -x, y, width, height必填,为要绘制的起点坐标和宽高;也可以用`flag:xxx`。 - -style可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。 - -lineWidth可选,表示边框的线宽。 - -从V2.7起,实心和空心矩形都支持圆角,您可以指定圆角的半径。 -### drawLine:绘制线段 -UI绘制事件。此事件可以绘制一条直线段,循环使用的话您甚至可以画出带渐变色的复杂曲线。 -```json -[ - {"type": "drawLine", "x1": 0, "y1": 0, "x2": "flag:x", "y2": 200, "style": [255,0,0,1]} -] -``` - -x1, y1, x2, x2必填,为要绘制的起点和终点坐标;也可以用`flag:xxx`的写法。 - -style可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。 - -lineWidth可选,表示边框的线宽。 - -下面是一个循环绘制直线段形成抛物线的例子:
-`for (var x = 0; x < 20; ++x) core.drawLine('ui', x * 20, x * x, (x + 1) * 20, (x + 1) ** 2)` -### drawArrow:绘制箭头 - -UI绘制事件。此事件可以绘制一个箭头。 - -参数和写法与`drawLine`完全一致,只不过是会多画一个箭头标记。 -### fillPolygon:绘制实心多边形 -UI绘制事件。此事件可以绘制一个多边形。 -```json -[ // 实际绘制原理是把顶点依次用直线段连起来,因此请自行注意顶点的顺序 - {"type": "fillPolygon", "nodes": [[0,0],[0,100],[100,0]], "style": [255,0,0,1]} -] -``` - -nodes必填,为一个二维数组,其中每一项都是多边形一个顶点坐标。(与显示/隐藏事件写法相同) - -style可选,表示绘制时的颜色,为三元组RGB或四元组RGBA。 -### strokePolygon:绘制空心多边形 -UI绘制事件。此事件可以绘制一个多边形边框。 - -参数列表和`fillPolygon`基本相同,不过多了一个`lineWidth`表示的绘制线宽。 -### fillEllipse/strokeEllipse/fillArc/strokeArc:绘制实心/空心椭圆/扇形/弧 -``` json -[ - {"type": "fillEllipse", "x": 0, "y": 0, "a": 100, "b": 100, "angle": 0}, - // 绘制实心椭圆,x和y为中心坐标,a和b为长短半轴,angle为旋转度数 - {"type": "strokeEllipse", "x": 0, "y": 0, "a": 100, "b": 100, "angle": 0}, - // 绘制空心椭圆,参数意义同上 - {"type": "fillArc", "x": 0, "y": 0, "r": 100, "start": 0, "end": 90}, - // 绘制扇形,x和y为顶点坐标,r为半径,start和end为起终点角度 - {"type": "strokeArc", "x": 0, "y": 0, "r": 100, "start": 0, "end": 90}, - // 绘制弧,参数意义同上 -] -``` -如果您需要绘制渐变色的椭圆,可以使用参数方程。譬如:(这个例子画在了UI层,UIevent层也是一样的道理) -``` js -for(var x = 0; x < 6.28; x += .01) - core.drawLine('ui', 208 + 200 * Math.cos(x), 208 + 100 * Math.sin(x), 208 + 200 * Math.cos(x + .01), 208 + 100 * Math.sin(x + .01),[x * 20, 255 - x * 20, core.rand2(256), 1]) -``` -### drawImage:绘制图片 -UI绘制事件。此事件可以绘制一个图片。和“显示图片”一样,从V2.7开始支持三种翻转效果。 -```json -[ - {"type": "drawImage", "image": "bg.jpg", "x": 0, "y": 0}, // 在(0,0)绘制bg.jpg - {"type": "drawImage", "image": "bg.jpg", "x": 0, "y": 0, "w": 100, "h": 100}, // 在(0,0)绘制bg.jpg,且放缩到100x100 - // 裁剪并放缩图片 - {"type": "drawImage", "image": "bg.jpg", "x": 0, "y": 0, "w": 100, "h": 100, "x1": 0, "y1": 0, "w1": 100, "h1": 100} -] -``` - -image必填,为图片名。图片必须在全塔属性中被注册过。 - -此函数有三种写法: - -- 只写x和y:表示要绘制到的位置。 -- 写x, y, w, h:表示要绘制到的位置,且将图片放缩到指定宽高。 -- 写x, y, w, h, x1, y1, w1, h1:从原始图片上裁剪[x,y,w,h]的图片,并绘制画布上的[x1,y1,w1,h1] - -可以查看下面的文档以了解各项参数的信息: -http://www.w3school.com.cn/html5/canvas_drawimage.asp - -### drawIcon:绘制图标 - -UI绘制事件。此事件可以绘制一个图标。 -```json -[ - {"type": "drawIcon", "id": "yellowKey", "x": 100, "y": 100}, // 在(100,100)绘制黄钥匙 -] -``` - -id必填,为要绘制的图标ID。可以是一个注册过的图标ID,也可以使用状态栏的图标ID,例如lv, hp, up, save, settings等。 - -x, y必填,为要绘制的左上角坐标。width和height可选,如果设置则会将图标放缩成对应的宽高。 - -从V2.7开始,对于多帧图块,允许指定绘制哪一帧,默认绘制第一帧(0)。 -### drawBackground:绘制背景图 - -UI绘制事件。此事件可以绘制一个背景图。 -```json -[ - {"type": "drawBackground", "background": "winskin.png", "x": 0, "y": 0, "width": 100, "height": 100}, -] -``` - -background必填,为要绘制的背景图内容。其可以是一个三元组RGB或四元组RGBA(纯色绘制),或一个WindowSkin的图片名。 - -x, y, width, height必填,分别为要绘制的起点坐标和长宽。 - -可以使用“设置画布属性”来设置不透明度和纯色绘制时的边框颜色。 - -### drawSelector:绘制闪烁光标 - -UI绘制事件。此事件可以绘制闪烁光标。 -```json -[ - {"type": "drawSelector", "image": "winskin.png", "code": 1, "x": 0, "y": 0, "width": 100, "height": 100}, - {"type": "drawSelector", "code": 1} // 清除1号闪烁光标 -] -``` - -image为要绘制的WindowSkin图片名;如果不填则视为“清除闪烁光标”。 - -`x, y, width, height` 分别为要绘制的起点坐标和长宽。`code` 为要绘制或清除的光标编号,必须为正整数。 - -闪烁光标将会一直存在即使事件流结束;请使用本事件并只填 `code` 来清除闪烁光标。 -### function: 自定义JS脚本 - -上述给出了这么多事件,但有时候往往不能满足需求,这时候就需要执行自定义脚本了。 -``` json -[ - {"type": "function", "function": "function(){ // 执行一段js脚本 - // 这里写js代码 - alert(core.getStatus('atk')); // 弹窗显示勇士的攻击力 - }"}, -] -``` - -`{"type":"function"}`需要有一个`"function"`参数,它是一个JS函数,里面可以写任何自定义的JS脚本;系统将会执行它。 - -系统常见可能会被造塔所用到的的API都在[API列表](api)中给出,请进行参照。 - -**警告:自定义脚本中只能执行同步代码,不可执行任何异步代码,比如直接调用core.changeFloor(...)之类都是不行的。** - -[API列表](api)中的所有异步API都进行了标记;如果你不确定一个函数是同步的还是异步的,请向小艾咨询。 - -如果需要异步的代码都需要用事件(insertAction)来执行,这样事件处理过程和录像回放才不会出错。 - -举个例子,如果我们想随机切换到某个楼层的某个点,我们可以这么写自定义脚本: - -``` js -var toFloor = core.floorIds[core.rand(core.floorIds.length)]; // 随机一个楼层ID -var toX = core.rand(13), toY = core.rand(13); // 随机一个点 -core.insertAction([ - {"type": "changeFloor", "floorId": toFloor, "loc": [toX, toY]} // 插入一个changeFloor事件,并在该脚本结束后执行。 -]) // 你会注意到此时事件参数允许使用var型变量,这也是insertAction的强大之处 -// 请勿直接调用 core.changeFloor(toFloor, ...),这个代码是异步的,会导致事件处理和录像出问题! -``` - -!> 从V2.5.3开始,提供了一个"不自动执行下一个事件"的选项(`"async": true`)。如果设置了此项,那么在该部分代码执行完毕后,不会立刻执行下一个事件。你需要在脚本中手动调用`core.events.doAction()`来执行下一个事件。可以通过此项来实现一些异步的代码,即在异步函数的回调中再执行下一个事件。使用此选项请谨慎,最好向开发者寻求咨询。 - -## 自动事件 - -从V2.6.4开始,提供了自动事件。每个点都可以绑定若干个自动事件,其类似于RM的事件页。 - -自动事件可以设置一个触发条件,当满足此条件时将自动执行。 - -![](img/autoEvent.png) - -自动事件可以设置如下几项内容: - -- 条件:当满足此条件时将自动执行 -- 优先级:当多个自动事件的条件同时满足时,将按照优先级从大到小执行;相同优先级的按照楼层和坐标排序。 -- 仅在本层检测:是否仅在本层检测该条件。 -- 事件流中延迟执行:如果此项为true,则若满足条件时正在事件流的处理中,则将该自动事件延迟到事件流结束时执行。 -- 允许多次执行:如果此项为true,则该自动事件允许被多次触发;否则只会被触发一次。值得注意的是,即使允许多次触发,也不允许在正在执行本自动事件时再触发。(即在执行本自动事件时将暂时禁用自身,直到执行完毕为止) - -自动事件的检测时机为刷新状态栏,即每次刷新状态栏时都会进行检测。 - -可以给自动事件加上【转变图块】,从而达到类似RM的多事件页并转变图块的效果 - -## 独立开关 - -从V2.5.3开始,针对每个事件都提供了独立开关。 - -独立开关的写法是`switch:A`, `switch:A`直到`switch:Z`,共计26个。 - -独立开关算是特殊的flag,它在事件中使用时会和事件的楼层及坐标进行绑定;换句话说每个事件对应的`switch:A`都是不同的。 - -事实上,在某个楼层某个点的事件的独立开关A对应的系统flag为`floorId@x@y@A`, -比如在`MT0`层的`[2,5]`点事件,对应的`switch:B`独立开关,实际会被映射到`flag:MT0@2@5@B`。 - -如果在事件外想访问某个事件的独立开关也需要通过上面这个方式。 - -通过独立开关的方式,我们无需对某些NPC的对话都设立单独的互不重复flag,只需要关注该事件自身的逻辑即可。 - -![](img/events/53.jpg) - -## 同一个点的多事件处理 - -我们可以发现,就目前而且,每个点的事件是和该点进行绑定,并以该点坐标作为唯一索引来查询。 - -而有时候,我们往往需要在同一个点存在多个不同的事件。这涉及到同一个点的多事件处理。 -
我们可以依靠两种指令来实现。**`setBlock` 事件**和 **`if+flag` 的条件判断**。
-下面以几个具体例子来进行详细说明。 - -### 打怪掉宝 - -我们注意到怪物和道具都是系统默认事件,因此无需写events,而是直接在afterBattle中setBlock即可。 -``` json -"afterBattle": { - "x,y": [ - {"type": "setBlock", "number": 21} // 变成黄钥匙。注意是当前点因此可省略floorId和loc - ] -} -``` - -### 打怪变成楼梯 - -因为涉及到多事件处理,因此我们不能写changeFloor那一项,而是使用events(自定义事件里写楼层转换)。 - -注意到events中不覆盖trigger,则还是怪物时,存在系统trigger因此会战斗并触发afterBattle;变成NPC后没有系统trigger因此会触发自定义事件(楼层转换)。 - -请注意打死怪物时默认会禁用该点,因此替换后需要手动进行show来启用。 -``` json -"events": { - "x,y": [ - {"type": "changeFloor", "loc": [0,0], "floorId": "MT1"} - ] -}, -"afterBattle": { - "x,y": [ - {"type": "setBlock", "number": 87}, // 变成上楼梯 - {"type": "show"} // 启用该点 - ] -} -``` - -![](img/events/54.jpg) - -### 获得圣水后变成墙 - -这个例子要求获得圣水时不前进(也就是不能走到圣水地方),然后把圣水位置变成墙。 - -因此需要我们需要覆盖系统trigger(getItem),并覆盖noPass。 - -通过if来判断有没有获得圣水,没有则触发圣水(生命x2)然后变成墙,否则不执行。 -``` json -"events": { - "x,y": { - "trigger": "action", // 覆盖系统trigger,默认的getItem不会执行 - "noPass": true, // 覆盖可通行状态,不允许走到该点 - "data": [ - {"type": "if", "condition": "flag:hasSuperPotion", // 条件判断:是否喝过圣水 - "true": [], // 喝过了,不执行 - "false": [ - {"type":"setValue", "name":"status:hp", "value":"status:hp*2"}, - {"type":"setBlock", "number": 1}, // 生命翻倍,将该点变成墙 - {"type":"setValue", "name":"flag:hasSuperPotion", "value": "true"} - ] // 标记已经喝过了。你会发现这种写法并不涉及圣水道具本身,它只是个素材 - } - ] - } -} -``` - -![](img/events/55.jpg) - -总之,记住如下两点: - - - 可以使用setBlock来更改一个图块。 - - 可通行状态遵循覆盖原则,即**首先取该图块的默认 `canPass` 属性,如果该点的普通事件中定义该点的 `noPass` 则覆盖**。 - - 触发器(trigger)亦采用覆盖原则,即**首先取该图块的默认触发器(例如怪物是 `battle` ,道具是 `getItem` ,门是 `openDoor` ),如果该点绑定了楼层转换事件(绿)或普通事件(红)中覆盖触发器则覆盖**。 - - 可以通过if语句和flag来控制自定义事件具体走向哪个分支。 - - 如果弄不清楚系统trigger和覆盖触发器的区别,也可以全部覆盖为自定义事件,然后通过type:battle,type:openDoor等来具体进行控制。 - - 如果弄不清楚通行性,也可以全部覆盖为不可通行,并在本该通行的场合用事件让勇士前进。 - - 在上述两种覆盖的情形下,请善用“图块ID:x,y”和“图块类别:x,y”这两个缩写量去判断该图块是什么。 - - 多事件处理时请不要使用`changeFloor`那一项,而是使用`events`或者`afterXXX`来处理。 -## 并行脚本处理 -从V2.4.3后,H5样板开始支持并行脚本处理。
-在脚本编辑里面提供了一个parallelDo函数,这个函数可以用来做并行处理内容。 - -从V2.5.2开始,每层楼的楼层属性中也增加了一个parallelDo选项,可以在里面写任何脚本代码。该部分代码仅在人物在该楼层时才会被反复执行。 - -``` js -"parallelDo": function (timestamp) { - // 并行脚本处理,可以在这里写任何需要并行处理的脚本或事件 - // 该函数将被系统反复执行,每次执行间隔视浏览器或设备性能而定,一般约为16.6ms一次 - // 参数timestamp为“从游戏资源加载完毕到当前函数执行时”的时间差,以毫秒为单位 - - // 检查当前是否处于游戏开始状态 - if (!core.isPlaying()) return; - - // 执行当前楼层的并行事件处理 - if (core.isset(core.status.floorId)) { - try { - eval(core.floors[core.status.floorId].parallelDo); - } catch (e) { - main.log(e); - } - } - - // 下面是一个并行事件开门的样例 - /* V2.6.4起,提供了自动事件,不再推荐用并行脚本去做这样的处理 - // 如果某个flag为真 - if (core.hasFlag("xxx")) { - // 千万别忘了将该flag清空!否则下次仍然会执行这段代码。 - core.removeFlag("xxx"); - // 使用insertAction来插入若干自定义事件执行 - core.insertAction([ - {"type":"openDoor", "loc":[0,0], "floorId": "MT0"} - ]) - // 也可以写任意其他的脚本代码 - } - */ -} -``` -该函数将被系统反复执行,执行间隔试浏览器或设备性能而定,一般约为16.6ms一次(60fps)。 - -此函数有个参数timestamp,为**从游戏资源加载完毕到当前函数执行时**的时间差,以毫秒为单位。可以使用此参数来制作一些时间相关内容或者特效等。 - -如果要执行并行的自定义事件,请使用if+flag判断的形式,然后insertAction将自定义事件插入到事件列表中。 - -!> 判定flag后千万别忘了将该flag清空!否则下次仍然会执行这段代码。 - -每层楼的并行脚本处理类似,只有角色在当前楼层时才会反复执行当前楼层中parallelDo部分的代码。 - -下面是一个打怪开门的样例:(假设每打一个怪的战后事件把`flag:door`+1) - -``` js -// 每层楼的并行事件处理代码样例 -if (core.getFlag("door",0)==2) { - // 将该flag清空 - core.removeFlag("door"); - // 开门,如果是当前层则无需写floorId - core.insertAction([ - {"type":"openDoor", "loc":[0,0]} - ]); -} -``` - -## 加点事件 -打败怪物后可以进行加点。要启用加点,首先需要在全塔属性中勾选“启用战后加点”。 - -如果要对某个怪物进行加点操作,则首先需要修改该怪物的`point`数值,代表怪物本身的加点数值。 - -从V2.5.5开始,加点事件移动到了[公共事件](personalization#公共事件)之中,会通过传参的形式来传递怪物的加点值。 - -```js -// 如果有加点 -var point = core.material.enemys[enemyId].point; -if (core.flags.enableAddPoint && point > 0) { - core.push(todo, [{ "type": "insert", "name": "加点事件", "args": [point] }]); -} -``` - -## 全局商店 - -我们可以采用上面的choices方式来给出一个商店。这样的商店确实可以有效地进行操作,但是却是"非全局"的,换句话说,只有在碰到NPC的时候才能触发商店事件。 - -我们可以定义"全局商店",其可以直接被快捷栏中的"快捷商店"进行调用。换句话说,我们可以定义快捷商店,让用户在任意楼层都能快速使用商店。 -
全局商店定义在全塔属性中,找到shops一项。
-从V2.2以后,全局商店也可以使用图块进行编辑,但仍需知道每一项的使用。 -``` json -"shops": [{ - "id": "shop1", - "text": "\t[贪婪之神,moneyShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:", - "textInList": "1F金币商店", - "mustEnable": false, - "disablePreview": false, - "choices": [ - {"text": "生命+800", "need": "status:money>=20+2*flag:shop1", "action": [ - {"type": "setValue", "name": "status:money", "operator": "-=", "value": "20+2*flag:shop1"}, // 从V2.7起,全局商店由自带插件实现。标准商店中需要手动处理扣费和涨价问题 - {"type": "setValue", "name": "flag:shop1", "operator": "+=", "value": "1"}, - {"type": "setValue", "name": "status:hp", "operator": "+=", "value": "800"}]}]}] -``` -- id 为商店的唯一标识符(ID),请确保任何两个商店的id都不相同 -- text 为商店所说的话。可以使用\t效果和${}表达式求值。 -- textInList 为其在快捷商店栏中显示的名称,如"3楼金币商店"等 -- mustEnable 是否必须是只在开启状态才在列表显示;如果此项为true则未开启的快捷商店不予显示 -- disablePreview 是否禁止预览,如果此项为true则不能预览 -- choices 为商店的各个选项,是一个list,每一项是一个选项 - - text 为显示文字。同样支持 ${} 的表达式计算,预览时、或未满足购买条件的项则会显示为灰色。 - - need 和 condition 分别为该选项的购买条件和出现条件,“出现条件”的含义和“显示选择项”事件中一致。 - - action 为该选项的效果;从V2.7开始,选项效果支持任意类型的事件,当然也就不再支持长按连续购买。 - -像这样定义了全局商店后,即可在V键(从V2.7开始,不再支持K键)菜单或非自绘状态栏点击金币图标时看到。 - -请注意,快捷商店默认是不可被使用的。直到至少调用一次自定义事件中的 `{"type": "openShop"}` 打开商店后,才能真正在快捷栏中被使用。 -``` json -// 事件列表 -[ - // 打开商店前,你也可以添加自己的剧情 - // 例如,通过if来事件来判断是不是第一次访问商店,是的则显示一段文字(类似宿命的华音那样) - {"type": "openShop", "id": "moneyShop1"}, // 这里的id要和全塔属性中你定义的商店ID完全一致 - {"type": "disableShop", "id": "moneyShop1"} // 如果需要禁用商店,则需要调用disableShop事件 -], -``` - -如果需要禁用一个全局商店,则简单的在事件中调用 `{"type": "disableShop"}` 即可。 - -禁用商店后商店将无法从快捷栏中进行使用,直到再次使用openShop打开商店为止。 - -另外需要注意的一点就是,每层楼都有一个 canUseQuickShop 选项。如果该选项置为false则无法在该层使用快捷商店。 - -从V2.7开始,`canUseQuickShop` 函数被挪动到了插件编写中,且对三种全局商店都有效,您也可以加以利用。 - -**从V2.6开始,也提出了“公共事件化的全局商店”,即打开使用全局商店实际上是执行一个公共事件。** -```json -"shops": [ - // 定义公共事件化的全局商店 - { - "id": "keyShop1", // 商店唯一ID - "textInList": "回收钥匙商店", // 在快捷商店栏中显示的名称 - "mustEnable": false, // 如果未开启则不显示在状态栏中 - "commonEvent": "回收钥匙商店", // 公共事件名 - "args": [], // 向该公共事件传递的参数 - } -] -``` - -![](img/events/56.jpg) - -`id`, `textInList`, `mustEnable`和上述完全相同。 - -`commonEvent`为公共事件名,即选择此项时要执行的公共事件。 - -`args`可选,为向该公共事件传递的参数,参见[type:insert](#insert:插入公共事件或另一个地点的事件并执行)的说明。 - -从V2.6.4开始,自带了道具商店插件,您可以自由设置道具的价格、出售和回收价、进货数量、出现条件等。 -## 系统引发的自定义事件 -我们知道,所有普通事件都是需要定义在`"x,y"`处,并且得让用户经过或撞上才能触发的。 - -但是有一系列的事件,例如战斗、获取道具、开门等,是系统已经预先设定好的事件,我们如果在该点绑定普通事件(红)并覆盖触发器,原本的战斗等事件就会被覆盖。 - -为了解决此问题,在每个点的事件中引入了三个元素:`afterBattle`, `afterGetItem`, `afterOpenDoor`。 -- 当某个战斗结束后,将执行`afterBattle`中,对应位置的事件。 -- 当获取某个道具后,将执行`afterGetItem`中,对应位置的事件。您还可以指定该事件能否被轻按触发。 -- 当开了某个门后,将执行`afterOpenDoor`中,对应位置的事件。 - -例如,下面就是一个典型的杀怪开门的例子。每当杀死一个守卫机关门的怪物,将检查是否满足打开机关门的条件。如果是,则开启机关门。 -``` json -"afterBattle": { // 战斗后可能触发的事件列表 - "9,6": [ // 初级卫兵1 - {"type": "setValue", "name": "flag:door", "value": "flag:door+1"}, // 将"door"这个自定义flag加一 - {"type": "if", "condition": "flag:door==2", // 一个条件判断事件,条件是"door"这个flag值等于2 - "true": [ // 如果条件成立:打开机关门 - {"type": "openDoor", "loc": [10,5]} - ], - "false": [] // 如果条件不成立则无事件触发 - }, - ], - "11,6": [ // 初级卫兵2;注意由于打怪顺序问题,可能都得写一遍。 - {"type": "setValue", "name": "flag:door", "value": "flag:door+1"}, // 将"door"这个自定义flag加一 - {"type": "if", "condition": "flag:door==2", // 一个条件判断事件,条件是"door"这个flag值等于2 - "true": [ // 如果条件成立:打开机关门 - {"type": "openDoor", "loc": [10,5]} - ], - "false": [] // 如果条件不成立则无事件触发 - }, - ], // 从V2.6.4起,提供了右击快速绑定机关门的操作,绑定以后,战后事件只负责累加杀怪数, -}, // 而判定杀怪数是否足够、以及开门的操作则由机关门处的自动事件执行 -``` - -![](img/events/60.jpg) - -!> 多个机关门请分别设置开门变量如door1, door2等等。请勿存在两个机关门用相同的变量! - -除此以外,每层楼还提供了`firstArrive`和`eachArrive`事件,分别为首次到达该楼层和每次到达该楼层时执行的事件。 +参数列表是一个一维数组,其每项会被依次代入core.status.hero.flags.arg1、arg2、……,而arg0则会记录公共事件的中文名,因此请不要在一个公共事件里又插入另一个公共事件。 +在整个事件流结束后(即勇士恢复行动,请注意不是公共事件结束后),这些以arg加纯数字命名的变量、以及以@temp开头的临时变量都会被清空。 ## 滑冰事件 -从V2.6开始,滑冰事件被重写。在新版本中,冰面应该放在背景层上,上面可以放置道具、怪物、门等图块。 +滑冰(ski)是一个非常特殊的触发器,使用此触发器的图块需要画在背景层。 -角色走上冰面后,将一直向前滑行,直到撞上不可通行的图块,或触发事件,或走下冰面为止。 +冰上可以画门、怪物、道具等任何图块,您还可以在前景层画上四种单向通行箭头(样板1层右下方那些),把三个图层的游戏性都发挥出来。 -如果撞上怪物将自动进行战斗,此战斗是强制的,打不过将直接死亡。 +勇士走上冰面后,将一直“前进一格或撞击”。直到滑出冰面或无法再前进,如撞到墙或事件。 -默认情况下,拾取冰面上道具后将停止滑冰行为。如果要继续滑冰,请在`afterGetItem`中插入公共事件:滑冰事件。打怪和开门同理。 +比如撞到怪物会强制战斗,打不过直接游戏失败。走到道具上会捡起来,撞到门则要看有没有钥匙,有的话会把门打开。 -!> 滑冰图块的默认触发器是 `ski` ,您可以将别的图块也改为这个默认触发器并画在背景层,从而做出五颜六色的冰面。 -## 推箱子事件 -关于推箱子,存在三种状态:花(flower),箱子(box)和已经推到花的箱子(boxed)。 +默认情况下,触发事件后勇士会停下来。如果要继续滑冰,可以在这些点的战后事件、开门后事件、(拾获)道具后事件(这里最好勾选“轻按时不触发”)中判断勇士还在不在冰上(core.onSki()函数),在冰上的话就命令“勇士前进一格或撞击”。 +## 事件编辑器 +![image](img/v2.7/blockly.png) +当您从数据区单击任何一个事件类属性的“编辑”按钮时,就会呼出事件编辑器,上图给出了事件编辑器的全貌。 -!> 推箱子的前方不允许存在任何事件层图块(花除外),否则会推不动。 +左下角为指令类别,可以点击它们呼出各类指令菜单,如左上方的值块菜单。 -推完箱子后将触发脚本编辑中的afterPushBox函数,你可以在这里进行开门判断。 +中央为指令区,被一个标识事件类型的紫色块包覆(即左下角的“入口方块”,图中为开门后事件),所有的指令都塞在里面。 +右上角为json区,会随着指令区的编辑而自动变化。core.insertAction()函数的自变量就是它们,所以学有余力的话也建议您经常左右对照去了解每个指令对应的json写法。 + +右下角为调色器,当您单击指令块中的颜色按钮时(如图中“画面闪烁”指令的白块)就会自动呼出,可以进行诸如十进制和十六进制颜色格式互转等操作。 + +左上角为功能区,各功能的含义和用法如下: +1. 确认(Ctrl+S):将指令区的指令组翻译为json写回表格和文件,并关闭事件编辑器。如果手动修改了json区却没有点击变黄的解析按钮,或指令区存在异步事件没有用“等待所有异步事件执行完毕”(图中第二条褐色指令)去等待,则单击确认按钮会弹窗警告。此时如果想放弃对json区的修改,请随便点一下指令区的一个块即可。 +2. 解析:将手动修改后的json区翻译回指令组同步到指令区,一般用于跨作品复制事件,或长距离批量挪动和复制指令。因为blockly使用Ctrl+V粘贴出的块总是出现在原块的旁边,而拖动块时块又跟不上滚轮`-_-`|| +3. 取消:放弃本次编辑,关闭事件编辑器,表格和文件会停留在打开事件编辑器前的状态。 +4. 搜索事件块:当您想不起来需要的指令在哪个类别时,请使用此项,如输入“勇”字就会列出所有带有“勇士”一词的指令。 +5. 地图选点:在编辑事件尤其是大篇幅事件的过程中,如果需要频繁保存并退出事件编辑器去浏览地图尤其是浏览别的楼层就很不方便。单击此按钮,您可以浏览所有楼层及其全景。通过点击地图去确认一个点的坐标,并复制任何一个楼层ID以填入需要的地方。需要填坐标的指令也可以直接双击其指令块从地图选点填入坐标和楼层,从而避免了肉眼数格子和手敲的麻烦和出错的隐患。 +6. 变量出现位置搜索:您可以搜索所有以“变量:xxx”形式出现在事件中的变量的出现位置,请注意“形式”和“事件”。以下形式都是无法被搜索到的(比如仇恨值、阻激夹域捕的禁用开关): ``` js -////// 推箱子后的事件 ////// -"afterPushBox" = function () { - // 推箱子后的事件 - if (core.searchBlock('box').length == 0) { - // 可以通过if语句来进行开门操作 - /* - if (core.status.floorId=='xxx') { // 在某个楼层 - core.insertAction([ // 插入一条事件 - {"type": "openDoor", "loc": [x,y]} // 开门 - ]) - } - */ - } -} + 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的优先级不一致,请在表达式中适当的位置添加圆括弧,或取消勾选此项。 -有时候光战后事件`afterBattle`是不够的,我们可能还需要战前剧情,例如Boss战之前和Boss进行一段对话。 +## 值块和冒号缩写量 -要使用战前剧情,你需要在该点创建普通事件并覆盖触发器,然后在战前剧情后调用`{"type": "battle"}`强制战斗。 +值块并不能单独构成指令,但它们可以被嵌入数值操作、设置怪物属性和很多事件控制类指令。而冒号缩写量的用法就更多了,比如用于`${表达式计算}`和其他任何支持填表达式的地方。\ +值块大体上分为三种:勾选框与运算块、只读块、可读写块,其中后两类对应着冒号缩写量。 +### 勾选框与运算块(附js比较运算大图鉴) -顺便一说,普通事件中还提供了是否显伤的勾选框,您可以不勾选,从而使该怪物在地图上不显示预估伤害。 -``` json -{ - "trigger": "action", // 覆盖触发器 - "data": [ // 该点的自定义事件列表 - // ... 战前剧情 - {"type": "battle", "id": "xxx"}, // 强制战斗 - // ... 战后剧情;请注意上面的强制战斗不会使怪物消失,如有需要请调动{"type": "hide"} - ] -} -``` +包括勾选框块(true和false两个逻辑常量)、否定运算块和二元运算块。 -![](img/events/57.jpg) -另外,从V2.6开始,脚本编辑中提供了战前脚本`beforeBattle`,这里不再详细展开,如有需求可自行前往研究。 -## 经验升级(进阶/境界塔) -样板也支持经验升级,即用户杀怪获得经验后,可以到达某些数值自动进阶,全面提升属性。 +否定运算块(一个“非”字,脚本中写作一个叹号)会把“false、0、null、undefined、NaN和空字符串”(以下简称广义false)变为true,而把别的量都变为false. -要经验升级,你需要在全塔属性中同时勾选“显示等级称号”、“显示经验值”、“开启自动进阶”。 +二元运算块包括四则运算、取余、乘方、比较运算和三种逻辑运算。 -同时,你还需要在全塔属性中的 `levelUp` 来定义每一个进阶所需要的经验值,以及进阶时的效果。 -``` json -"levelUp": [ // 经验升级所需要的数值,是一个数组 - {"need": "0", "title": "", "action": []}, // 第一项为初始等级,仅title生效 - // 每一个里面可以含有四个参数 need, title, clear, action - // need为所需要的经验数值,可以是个表达式。请确保need依次递增 - // title为该等级的名称,也可以省略代表使用系统默认值;本项将显示在状态栏中 - // clear如果为true则自动扣除经验 - // action为本次升级所执行的事件列表 - {"need": "20", "title": "第二级", "clear": true, "action": [ // 加上clear则自动扣除经验 - {"type": "setValue","name": "status:atk","value": "status:atk+10"}, // 攻击+10 - {"type": "setValue","name": "status:def","value": "status:def+10"} // 防御+10 - ]}, - {"need": "40", "effect": [ - {"type": "tip", "text": "恭喜升级"}, - ]}, - // 依次往下写需要的数值即可 -] -``` +四则运算中,两个整数相除会得到小数。两个0的乘方会得到1(数学上无意义) -![](img/events/58.jpg) +八种比较运算中,四种比大小的运算如果两项中有一项是数字,就会把另一项也转换成数字去比,所以会出现这些: -`levelUp`是一个数组,里面分别定义了每个等级的信息。里面每一项有三个参数`need`, `title`, `effect` -- `need` 该等级所需要的经验值,可以是个表达式。请确保数组中的need依次递增。 -- `title` 该等级的名称,比如“佣兵下级”等。该项可以忽略,以使用系统默认的等级。该项将显示在状态栏中。 -- `clear` 是否扣除经验。如果此项为true,则升级时自动扣除经验。 -- `action` 为本次升级要执行的事件流。 -## 开始游戏与难度分歧 -游戏开始时将依次调用全塔属性中的 `levelChoose` 和 `startText` 事件,我们可以修改它们俩的内容来对于不同难度分别设置初始属性。 -``` json -"levelChoose": [ - {"title": "简单", "name": "Easy", "hard": 1, "action": [ - // 在这里写该难度需执行的事件 - {"type": "comment", "text": "在这里写该难度需执行的事件"}, - ]}, - {"title": "普通", "name": "Normal", "hard": 2, "color": [0,255,0,1], "action": [ - ]}, -], ////// 不同难度分别设置初始属性 ////// -"startText": [ - {"type": "switch", "condition": "flag:hard", "caseList": [ - {"case": "1", "action": [ // 简单难度,初始攻击力设为20点 - {"type": "setValue", "name": "status:atk", "value": "20"}, - ]}, - {"case": "2", "action": [ // 普通难度,隐藏主塔10层中央的图块(比如圣水什么的) - {"type": "hide", "loc": [[6,6]], "floorId": "MT10"}, - ]}, - ], }, - "Hi,欢迎来到 HTML5 魔塔样板!\n本样板由艾之葵制作,可以让你在不会写任何代码\n的情况下也能做出属于自己的H5魔塔!", - "这是游戏开始时的剧情。\n你可以在这里写上自己的内容。\n赶快来试一试吧!", -] -``` +`'2' < 10; 10 <= '10'; '10' < 2; null >= 0; null <= 0; 1/0 > 1/-0` + +![image](img/v2.7/compare.png) + +弱(不)等于(==和!=)非常难用,建议放弃,统一使用(不)等于(===和!==)。 + +NaN一般是0/0或字符串瞎做减乘除得到的,它跟谁都没有可比性,包括自己。 + +纯数字字符串(包括十六进制)和对应的数字,都是弱相等关系。如`'0x10' == 16` + +数组和对象,跟自己都是既大于等于又小于等于的关系(因为不是同一个)。 + +单个数字(或什么都没有)用方括号还是引号括起来,对外的比较行为都一致。 + +undefined倒是不用担心,它除了和null弱相等外,和其他值都没有可比性。 + +三种逻辑运算的原则是,“且”的优先级高于“或”,它俩都不满足交换律。 + +若干个由“且”连起来的量中,取第一个广义false(没有则取最后一个量), + +若干个由“或”连起来的量中,取第一个不是广义false的量(没有则同上), + +所以样板中充斥着形如x=x||y和z=x||y的代码,y算是x的默认值。 + +若干个由“异或”连起来的true或false,总结果取决于其中true的个数的奇偶,奇数个true则总结果为1,偶数个true则总结果为0. +### 只读块(怪物属性、图块ID、图块类别、装备孔) {#只读块} +尽管这几个值块是只读的,但您仍然可以使用“设置怪物属性”、“穿脱装备”和“转变图块”等指令去改变它们。 +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+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中读取数据,回放时则直接从录像中读取。 + ========================================================================================== [继续阅读下一章:个性化](personalization) diff --git a/_docs/img/v2.7/blockly.png b/_docs/img/v2.7/blockly.png new file mode 100644 index 00000000..8d5b576c Binary files /dev/null and b/_docs/img/v2.7/blockly.png differ diff --git a/_docs/img/v2.7/changeFloor.png b/_docs/img/v2.7/changeFloor.png new file mode 100644 index 00000000..74a94df2 Binary files /dev/null and b/_docs/img/v2.7/changeFloor.png differ diff --git a/_docs/img/v2.7/compare.png b/_docs/img/v2.7/compare.png new file mode 100644 index 00000000..ed4c7f43 Binary files /dev/null and b/_docs/img/v2.7/compare.png differ diff --git a/_docs/img/v2.7/console.png b/_docs/img/v2.7/console.png new file mode 100644 index 00000000..1ffddc15 Binary files /dev/null and b/_docs/img/v2.7/console.png differ diff --git a/_docs/img/v2.7/control&itemsG.png b/_docs/img/v2.7/control&itemsG.png new file mode 100644 index 00000000..75fbdfc8 Binary files /dev/null and b/_docs/img/v2.7/control&itemsG.png differ diff --git a/_docs/img/v2.7/drawTip.png b/_docs/img/v2.7/drawTip.png new file mode 100644 index 00000000..22572d53 Binary files /dev/null and b/_docs/img/v2.7/drawTip.png differ diff --git a/_docs/img/v2.7/editor.png b/_docs/img/v2.7/editor.png new file mode 100644 index 00000000..875a8e5a Binary files /dev/null and b/_docs/img/v2.7/editor.png differ diff --git a/_docs/img/v2.7/eventsX.png b/_docs/img/v2.7/eventsX.png new file mode 100644 index 00000000..130ff919 Binary files /dev/null and b/_docs/img/v2.7/eventsX.png differ diff --git a/_docs/img/v2.7/firstDataB.png b/_docs/img/v2.7/firstDataB.png new file mode 100644 index 00000000..9737fea5 Binary files /dev/null and b/_docs/img/v2.7/firstDataB.png differ diff --git a/_docs/img/v2.7/floorsV.png b/_docs/img/v2.7/floorsV.png new file mode 100644 index 00000000..e710503a Binary files /dev/null and b/_docs/img/v2.7/floorsV.png differ diff --git a/_docs/img/v2.7/flowCtrl.png b/_docs/img/v2.7/flowCtrl.png new file mode 100644 index 00000000..73e25371 Binary files /dev/null and b/_docs/img/v2.7/flowCtrl.png differ diff --git a/_docs/img/v2.7/images&textY.png b/_docs/img/v2.7/images&textY.png new file mode 100644 index 00000000..c83e89bf Binary files /dev/null and b/_docs/img/v2.7/images&textY.png differ diff --git a/_docs/img/v2.7/keyboard.png b/_docs/img/v2.7/keyboard.png new file mode 100644 index 00000000..0a89fc52 Binary files /dev/null and b/_docs/img/v2.7/keyboard.png differ diff --git a/_docs/img/v2.7/maps&waits&raw.png b/_docs/img/v2.7/maps&waits&raw.png new file mode 100644 index 00000000..8f145f04 Binary files /dev/null and b/_docs/img/v2.7/maps&waits&raw.png differ diff --git a/_docs/img/v2.7/mapsC.png b/_docs/img/v2.7/mapsC.png new file mode 100644 index 00000000..ba500429 Binary files /dev/null and b/_docs/img/v2.7/mapsC.png differ diff --git a/_docs/img/v2.7/parabola.png b/_docs/img/v2.7/parabola.png new file mode 100644 index 00000000..88e09b58 Binary files /dev/null and b/_docs/img/v2.7/parabola.png differ diff --git a/_docs/img/v2.7/quickShops.png b/_docs/img/v2.7/quickShops.png new file mode 100644 index 00000000..18ff1902 Binary files /dev/null and b/_docs/img/v2.7/quickShops.png differ diff --git a/_docs/img/v2.7/server.png b/_docs/img/v2.7/server.png new file mode 100644 index 00000000..096a823a Binary files /dev/null and b/_docs/img/v2.7/server.png differ diff --git a/_docs/img/v2.7/uievent.png b/_docs/img/v2.7/uievent.png new file mode 100644 index 00000000..54e36276 Binary files /dev/null and b/_docs/img/v2.7/uievent.png differ diff --git a/_docs/img/v2.7/values&flagsB.png b/_docs/img/v2.7/values&flagsB.png new file mode 100644 index 00000000..a60003a5 Binary files /dev/null and b/_docs/img/v2.7/values&flagsB.png differ diff --git a/_docs/index.md b/_docs/index.md index e585c3c2..198994d5 100644 --- a/_docs/index.md +++ b/_docs/index.md @@ -1,16 +1,22 @@ # HTML5 魔塔样板说明文档 ?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} * -
当您打开这份帮助文档的瞬间,相信您一定是抱着幼年时的游戏开发梦想前来的。
-众所周知,即时制游戏的开发要比非即时游戏难上许多,像素级游戏的开发又要比网格地图游戏难上许多。
在非即时的网格地图游戏(譬如策略战棋)中,有一类游戏叫做“固定数值RPG”,或者简称“魔塔”。
这是一种基于运筹学的数学优化建模游戏,虽然小众,却不失有自己的圈子。 +当您打开这份帮助文档的瞬间,相信您一定是抱着幼年时的游戏开发梦想前来的。众所周知,即时游戏的开发要比非即时游戏难上许多,像素级游戏的开发又要比网格地图游戏难上许多。 -在当下,魔塔的趋势是向移动端发展,网络上也常常能见到“求手机魔塔”的提问。然而现有的工具中,NekoRPG有着比较大的局限性,游戏感较差,更是完全没法在iOS上运行。而一些APP的魔塔(譬如《魔塔盛宴》和一些登陆了TapTap的魔塔,以及最新的由RPG Maker MV制作的《盖伦排位记》等)虽然可用,但是必须要下载安装,对于Android和iOS还必须开发不同的版本,非常麻烦。 +在非即时网格地图游戏(譬如策略战棋)中,有一类叫做“固定数值RPG”,简称“魔塔”。这是一种基于运筹学的数学优化建模游戏,虽然小众,却不失有自己的圈子。 -但是,现在我们有了HTML5。 HTML5的画布(canvas)以及它被Android/iOS内置浏览器所支持的特性,可以让我们做出真正意义上的全平台覆盖的魔塔。 +在当下,魔塔的趋势是向移动端发展,网络上也常常能见到“求手机魔塔”的提问。然而现有的工具中,NekoRPG有着比较大的局限性,游戏感较差,更是完全没法在iOS运行。而一些APP的魔塔虽然可用,但是必须要下载安装,对于安卓和苹果还必须开发不同的版本,非常麻烦。 -然而,一般而言使用非RPG Maker制作魔塔往往需要一定的编程技术,HTML5魔塔自然也不例外。但是,为了能让大家更加注重于“做塔”本身,而不用考虑做塔以外的各种脚本问题,@艾之葵(GitHub ckcz123)特意制作了这样一部HTML5的魔塔样板。 -> 这个魔塔样板,可以让你在完全不懂任何编程语言的情况下,做出自己的H5魔塔。不会代码?没关系!只要你想做,就能做出来! +但是,现在我们有了HTML5。 +HTML5的画布(canvas)以及它被Android/iOS内置浏览器所支持的特性,可以让我们做出真正意义上的全平台覆盖的魔塔。 + +然而,一般而言使用非RPG +Maker制作魔塔往往需要一定的编程技术,HTML5魔塔自然也不例外。但是,为了能让大家更加注重于“做塔”本身,而不用考虑做塔以外的各种脚本问题,@艾之葵(GitHub +ckcz123)特意制作了这样一部HTML5魔塔样板。 + +这个魔塔样板,可以让你在完全不懂任何编程语言的情况下,做出自己的H5魔塔。不会代码?没关系!只要你想做,就能做出来! + +继续查看文档的详细介绍,让你学会如何使用这一个样板来制作属于自己的HTML5魔塔,或者……任何非即时的网格地图游戏。 -继续查看文档的详细介绍,让你学会如何使用这一个样板来制作属于自己的HTML5魔塔,或者……任何非即时的网格地图游戏。
本说明文档配有较为过时的B站视频教程,可供参考:[https://www.bilibili.com/video/av32781473/](https://www.bilibili.com/video/av32781473/)。 ========================================================================================== diff --git a/_docs/instruction.md b/_docs/instruction.md new file mode 100644 index 00000000..7047a078 --- /dev/null +++ b/_docs/instruction.md @@ -0,0 +1,867 @@ +# 事件指令 +?> 目前版本**v2.7**,上次更新时间:* {docsify-updated} * + +本样板之所以敢宣称“零编程基础的您也能大展身手”,就是因为它搭载了强大的图形化json编辑器(blockly)。 + +熟悉Antlr语法的读者可以根据@zhaouv的另一篇文档去自行修改`_server\MotaAction.g4`等文件去扩展其功能。 + +json代码本身则可以作为core.insertAction()函数的自变量,去执行临时事件。 + +## 指令的分类(注意区分块的颜色和地图的七彩点) + +尽管本章的标题暗示了事件指令和`core.events._action_xxx()`函数是一一对应的,但它们进一步调用的底层函数却分布在libs文件夹的不同文件中。 + +大致上,显示文字类(严格来说需要玩家操作的事件还涉及到actions.js)和UI绘制类在ui.js,数据相关类(这类也有不少道具相关在items.js)和特效声音类在control.js,地图处理类在maps.js,事件控制类(或许应该叫流程控制类)则在events.js,请注意区分libs和project的同名文件。 + +另一种分类方法则是按照同步和异步,分成以下几类: +1. 瞬间就能执行完的:如UI绘制、设置XX属性、显隐和转变图层块等。 +2. 阻塞直到玩家操作的:如显示文章/选择项/确认框、接受用户输入、等待用户操作、呼出xxx等。 +3. 阻塞一段固定时间的:如开关门、显示动画、移动跳跃、淡入淡出等。 +4. 耗时但不阻塞的:如播放音效、显示提示等,会和后面的指令同时执行。 + +上述第3类指令都可以勾选“不等待执行完毕”(即前面提到的异步事件)变为第4类,从而实现诸如同步开关多个门的效果。 + +在json区,每条指令的格式为:`{"type": "xxx", "param1": ..., "param2": ..., ......}`, +实际执行的函数为`core.events._action_xxx(data, x, y, prefix)` + +data为整个指令对象,x和y为当前点坐标,prefix为独立开关的楼层前缀。 + +您可以自行在libs\events.js中追加这样的函数,这样就可以自定义新指令啦。 + +如果需要把新指令做成像已有的指令一样有类别、名称、取色器、勾选框、下拉框、输入框等部件,请查阅@zhaouv撰写的另一篇文档。 + +![image](img/v2.7/images&textY.png) + +## 显示文字类(黄色) +这个类别的指令会负责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)下方,尖角朝上指着这个点。比起上面,这个没有高度问题,不过该点没有图块的话则还是没有尖角。 + + 上述两种写法中,如果把坐标换成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的正数,请自行双击预览。 + +立绘是画在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. 自动剧情文本:和上面的显示文章基本相同,只不过不是由玩家按下确认键或点击屏幕,而是一定毫秒后自动消失,录像回放中则忽略。 + + 比起那个,这个不能通过长按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. 显示图片:和立绘的语法基本类似,只不过多了编号(1—50)和淡入时间。 + + 可以双击预览效果,还可以勾选“不等待执行完毕”来和后面的指令同时执行,比如同时淡入两张图片,或者淡入一张同时淡出/移动另一张。 + + 编号较大的图片会遮盖较小的,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,即快速反应事件。一般表现为需要玩家在收到某信号后尽快做出正确操作,如新新魔塔2中面对白银史莱姆王的猜拳战斗就需要根据其出拳的颜色尽快按下相克的数字键。 + +样板同样支持这类事件,一共有三种,这里先介绍两种。 + +一是“显示确认框”,它会显示一段支持`${表达式求值}`但不支持自动换行和其他转义序列的文字。然后要求玩家在一定毫秒数内选择“确定”或“取消”之一,如果超时就视为哪个都没选,直接继续执行后面的事件。\ +您可以指定闪烁光标的初始停留位置是确定还是取消,还可以指定超时毫秒数为0表示不限时间但玩家必须做出二选一。 + +此指令对应core.drawConfirmBox(text, yesCallback, noCallback)函数,其中两个Callback分别为选择确定和取消后的回调函数。 + +二是“显示选择项”,和RPG Maker不同,我们的选择项不会和它之前的“显示文章”同时出现,可以直接配上除对话框和打字机外的所有文字效果。 + +此指令对应core.drawChoices(content, choices)函数,其中content为提示文字,choices为各子选项文字组成的字符串数组。是的,比起上面的函数,这个不直接支持回调。 + +在没有提示文字的情况下,一次能同时显示的子选项最多为13或15个。 + +和确认框一样,选择项的超时值填0表示不限时间但玩家必须从中选择一个。 + +大于0的话超时视为什么都没选,直接继续执行后面的事件。 + +每个子选项的文字只支持`${表达式求值}`和整行变色,请注意控制字数。 + +文字左侧也支持追加一个图标(多帧图块取第一帧),支持系统图标。 + +每个子选项还可以指定“出现条件”(不指定则一定出现),条件的写法和自动事件的触发条件一样,从而做出形如“怒气值满才显示大招选项”的效果。 + +如果实际执行时所有子选项都不满足出现条件,则直接跳过。 + +当然,如果非要做出“显示但选了没反应”的禁用项也不是不可以, + +只不过往往需要套在一个死循环里并让其他子选项负责跳出这个循环。 + +为了方便地做出这种效果,样板提供了“全局商店”。 + +![image](img/v2.7/quickShops.png) +在“全塔属性——全局商店”中可以编辑各个商店,商店一共有三种: + +1. 公共事件商店:最简单的一种商店,或者应该叫做给玩家准备的快捷功能更合适,因为它的内容完全不一定非得是个做买卖做交易的“商店”,也可以是诸如“开启或关闭主动技能”、“快速换上最强套装”之类的便捷功能。 + + 多说一句,鉴于全局商店列表最多只能同时显示12或14项(还有一项是关闭列表),因此您也可以准备一些永久道具,设置适当的使用条件,并在使用效果事件中去实现这些给玩家的快捷功能。当然全局商店的使用条件更加统一,请自行权衡。 + + 公共事件商店在用法上和一般的“插入公共事件”并无二致,同样可以提供一个参数列表。 + +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. + +本质上,新版商店是套在一个死循环里的。您可以在子选项的执行内容中使用“跳出当前循环”指令来打断该子选项剩余的未执行内容而强制离开商店, + +或使用“提前结束本轮循环”来打断未执行内容而强制重启商店。 + +同理,公共事件(包括公共事件商店)和自动事件本质上是“一次性”的条件为false的后置条件循环,因此使用这两个指令都能跳出它们。 + +## 数据相关类(绿色) +![image](img/v2.7/control&itemsG.png) + +这类的指令会设置各种数据(如怪物属性、楼层属性、全塔属性、六大可读写块),处理弹窗输入和开关全局商店,以及控制玩家最最关心的勇士的各种行为。 + +### 设置各种数据的指令 + +1. 数值操作:最简单的就是最灵活的,本指令能够修改六大可读写块(状态、物品、变量、独立开关、临时变量、全局存储)的值。 + + 修改的运算符有八种,“设为”会将右块的值代入左块, + + “增加、减少、乘以、除以”则是对左块的值进行增减和扩大缩小, + + 除法如想只保留整数商(向零靠近)则改用“除以并取商”, + + 如想要余数(例如想取勇士生命值的后两位)则使用“除以并取余”, + + “乘方”指的是将若干个(不一定是正整数)左块连乘起来的积代入左块。 + + 如将黄钥匙数量变为其立方(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. 接受用户输入:弹窗请求用户输入一个自然数或字符串,提示文字允许使用`${表达式计算}`。 + + 请求输入自然数(支持十六进制)时,负整数会被取绝对值。小数会被向0取整,其他非法输入会变为0. + + 请求输入字符串时,玩家点击取消则视为输入了空字符串。 + + 输入的结果会保存在值块“变量: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) + +这个类型的指令会影响三层地图矩阵的阵元,如果您觉得三层还不够用,“插件编写”(句号键)五图层插件欢迎您。 + +开始介绍前,首先明确一点:改变阵元不会立即影响事件的进程(自动事件除外)。 + +比如因为踩灯、路障和阻激夹域捕怪的分布变化导致勇士行走被妨害的区域发生变化,但不会立即触发妨害效果,而是要等到勇士下次行走。 + +在勇士所在点转变成(显示)一个门/怪物/道具/箱子/楼梯什么的(包括在脚下转变成/显示冰面)都不会立即触发事件,把这些图块移动/跳跃到勇士身上也是。 +反之,“隐藏事件”(转变图块为0)也不会立即中止当前的事件处理,只是下次不会触发。 +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也一样。 + + “不等待执行完毕”的用法如前,但几个图块再加上勇士以各异的速度和总步数移动时安排起来很麻烦,需要用到下述的“等待三姐妹”。 + +### 等待三姐妹、注释和原生js/json + +在讲解“事件控制”(流程控制)类指令之前,这里插播几个比较杂牌的指令。 +1. 等待固定时间:如题,可以用来实现复杂的集体移动效果。 + + 比如说51层魔塔一区结尾的骷髅埋伏圈,就是九只骷髅和四扇机关门组成的复杂演出。 + + 每只骷髅开始移动时都不等待执行完毕,但又需要等待一小段时间再让下一只骷髅开始移动。 + + 本指令还提供了一个勾选项“不可被Ctrl跳过”,如果不勾选此项且当前【没有】正在执行的异步事件(动画不算),则Ctrl可以跳过等待。 + +2. 等待所有异步事件执行完毕:让我们来想象这样一个情景。 + + 您使用了“移动事件”来移动一只怪物到勇士面前,并且“不等待执行完毕”。而下一条指令是“勇士前进一格或撞击”,以期触发战斗。 + + 然而因为怪物移动需要时间,两个指令同时执行,所以战斗没法触发。 + + 类似地,如果您在一个异步事件执行完毕之前就结束了整个事件流,让勇士恢复行动,那么可能这些异步事件还没来得及在游戏性方面生效,导致接下来会发生的事取决于玩家操作的时机和勇士的移速。 + + 尽管这在RPG Maker中很正常(怪物在地图上走来走去,主角要躲着走),但在我们的作品中是致命的。因为我们有录像系统,在录像回放时很多耗时的东西和所有需要用户响应的东西会被跳过。 + + 勇士的移速又可以很快(倍速播放),导致回放结果和原游戏不一致。 + + 总之,当您希望确保一些异步事件完全生效后再开始执行新的指令或结束事件流,“等待所有异步事件执行完毕”就是您的不二之选了,事件编辑器也会在发现缺少本指令时弹窗警告。 +3. 等待用户操作并获得键鼠信息:前面提到三种QTE指令,这是最后一种。 + + 此指令的下一条指令为“清除所有动图”的话,会先清除再开始等待。 + + 之前提到的“确认框”和“选择项”可以复现RPG Maker的回合制战斗, + + 但没法做出更复杂的交互界面,比如技能/天赋树,以及样板的道具商店。 + + 本指令会阻塞事件的执行,直到玩家按下键盘上的某个键(滚轮视为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指令中,我们已经初见了流程控制的端倪。 + +只不过,它们的流程走向是由玩家的选择直接左右的。 + +能否通过对值块的比较等操作自动走向不同的流程分支呢?答案是肯定的。 +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”这次是坐标。 + +其中“触发系统事件”和“插入事件”支持双击从地图选点。 + +## 特效声音类(褐色) +![image](img/v2.7/blockly.png) + +这个类别的指令会负责动画、视角、色调、天气、音频等其他一些细节。 +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(“已自动存档”),此指令一般用于选择项/确认框之前。 +## UI绘制类(瞬间) +![image](img/v2.7/uievent.png) + +这个类别的指令全部是瞬间完成的,有一一对应的API,请放心使用,除“绘制多行文本”外都可以逐个双击预览。游戏中,这些指令都是画在uievent层的。 +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的非负数,此项为“画笔”的不透明度。 + + 只影响接下来画的内容,已经画上去的不受影响。 + 6. 对齐:绘制单行文本的对齐方式,左对齐、左右居中、右对齐。 + 7. 基准线:绘制单行文本的基准线,有六种写法。 + + 绘制单行文本的坐标其实是文本的基准点, + + 而对齐方式和基准线决定了基准点在单行文本矩形区的相对位置, + + 就像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 diff --git a/_docs/personalization.md b/_docs/personalization.md index 77e87529..c33ae315 100644 --- a/_docs/personalization.md +++ b/_docs/personalization.md @@ -54,251 +54,65 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana'); 更多详细API请参见[API列表](api)。 -## 自定义素材 -所有系统素材的图片都在 `project\materials` 目录下。 -- `animates.png` 为所有动画效果。主要是星空熔岩,开门,毒网,传送门之类的效果。为四帧。 -- `enemys.png` 为所有怪物的图片。 -- `enemy48.png` 为所有48x32怪物的图片。 -- `items.png` 为所有道具的图标。 -- `npcs.png` 为所有NPC的图标。 -- `npc48.png` 为所有48x32的NPC图标。 -- `terrains.png` 为所有地形的图标。 +## 单点多事件 -从V2.7起,自动元件和 `tileset` 图片被分别放在了独立的文件夹中,而其余的由作者追加的图片(如动图、勇士和跟随者行走图、楼层贴图、对话皮肤)等留在了 `project\images` 文件夹。
-系统会读取`icon.js`文件,并获取每个ID对应的图标所在的位置。 -### 背景和前景图层 +带有独立开关的商人算是一个最为简单的单点多事件的例子了,单点多事件最常用的指令就是“转变图块”(或关门)和“条件分歧”。下面以几个具体例子来进行详细说明: +1. 打怪变成门或道具、开门变成怪或道具:怪物、门、道具都是系统触发器,直接利用afterXxx事件。如: -从V2.4.1开始,样板允许多个图层叠加,最多支持背景层、事件层和前景层三个图层。 + 战后事件:关门`yellowDoor`(原地关上了一扇黄门) -在地图编辑器中绘图时,下拉框选中“背景层”或“前景层”即可在对应的图层上绘图。 + 战后事件:转变图块为`yellowKey`(怪物掉落了黄钥匙) -其中背景层和前景层可以使用任何素材,以及使用自动元件(autotile)。 + 开门后事件:转变图块为`greenSlime或yellowKey`(开门变成了史莱姆或黄钥匙) -可以使用`showBgFgMap`, `hideBgFgMap`, `setBgFgBlock`等事件对背景和前景图层进行操作。 + 打怪变成别的怪、开门关上别的门、门和怪来回变的,用独立开关计数。 -### 使用自己的图片作为某层楼的背景/前景素材 + 如有批量需求,请使用“脚本编辑——afterXxx”函数。 +2. 打怪/开门/捡道具后变成传送点或npc: -由于HTML5功能(素材)有限,导致了对很多比较复杂的素材(比如房子内)等无法有着较好的绘图方式。 + 这时的传送点就不能用“楼梯、传送门”事件了,而应该用只有一条“场景切换”指令的普通事件。 + + 此事件不勾选“覆盖触发器”,这样怪物、门和道具的系统触发器会触发。 -为了解决这个问题,我们允许用户自己放置一张或多张图片作为某一层的背景/前景素材。 + 在对应的afterXxx事件中“转变图块为”传送点或npc,淡入效果更佳哦。 -要启用这个功能,我们首先需要在全塔属性中将可能的图片进行注册。 -``` json -"images": [ // 在此存放所有可能使用的图片 - // 图片可以被作为背景/前景图,也可以直接用自定义事件进行显示。 - // 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 - // 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 - "bg.jpg", "house.png", "bed.png"// 依次向后添加 -]; -``` + 请注意,因为道具是可通行的,如果勇士走到道具上,就会和npc重合。 -!> 请使用网上的一些[在线图片压缩工具](http://compresspng.com/zh/)对图片进行压缩,以节省流量。 +3. (懒人的选择)利用“图块类别:x,y”和“图块ID:x,y”等值块集中处理: -之后,我们可以在每层剧本的`"images"`里来定义该层的默认背景/前景层的图片素材。 + 如果您实在搞不清楚“覆盖触发器”和“通行状态”这两项,那就干脆勾选前者并把后者设为不可通行,本希望可以通行的场合就得用“无视地形移动勇士”指令前进一步。 -从V2.5.4开始,贴图也允许进行帧动画。从V2.7开始,楼层贴图使用事件编辑器编辑。 -``` json -[ // canvas为贴图所在的图层,可以写bg、fg或auto。"disable": true表示初始隐藏,frame为总帧数 - {"name": "bg.jpg", "canvas": "bg", "x": 0, "y": 0, "disable": true, "sx": 0, "sy": 0, "w": 416, "h": 416, "frame": 4}, -] // x和y为绘制的左上角坐标,sx和sy为裁剪的左上角坐标,w和h为裁剪的宽高(不支持伸缩) -``` -关于图层,`bg` 和 `fg` 分别表示该贴图全部画在背景层(如沼泽)或前景层(如云),被勇士遮挡或遮挡勇士。
`auto` 表示上部分画在前景层,下部分画在背景层。从而可以达到一个“自动调节遮挡的效果”。举例:树、房子等等。
-!> 如果写 `auto` 的话,最好让 `x, y` 和图片高度都是 `32` 的倍数!
-`frame` 为图片的帧数,可选。如果进行了设置,则会将该贴图视为帧动画,并【从左到右】切分成对应的帧数。
-例如,假设图片是100x100的,且帧数设为4,则视为四帧帧动画,每次绘制的图片大小实际上是25x100。 + 用自动事件去转变图块,然后利用上述两个值块判定当前图块的状态等,再用“强制战斗”、“开门(需要钥匙)”和`core.getItem(id)`分别处理吧。 -关于楼层贴图和前景、背景层的层叠覆盖关系,默认是:**地板 - 背景贴图 - 背景图块 - 事件 - 勇士 - 前景贴图 - 前景图块**。 +## 并行脚本:即时制的希望? -可以通过修改`libs/maps.js`的`drawBg`和`drawFg`函数来改变其覆盖关系。 +如前所述,自动事件可以让您不用考虑可能导致各值块发生变化的缘由,而是简单地在刷新状态栏时检测这些值块是否满足某些特定的关系。 +然而,自动事件依然是通过插入到当前待执行指令队列的开头,或追加到队列的结尾来执行的。换言之,它占用的是事件流本身的线程资源。 + +那形如bgs、bgv、飘云飘雾、地图背景旋转等即使玩家挂机也会照常执行的特效,该怎么办呢? + +js语言其实是没有多线程的,但我们可以写一些浏览器帧刷新时执行的脚本,也就是“并行脚本”。 + +并行脚本分为两种,全塔并行和楼层并行。前者在“脚本编辑—并行脚本”,后者在楼层属性。 + +一般来说,当您有多个楼层需要执行相同的并行脚本时,建议写在前者并通过对core.status.floorId的范围进行判定来决定具体执行的内容。 + +并行脚本将被系统反复执行,执行的时机是“浏览器帧刷新”,换言之相邻两次执行的间隔取决于浏览器或设备的性能,上限为60fps即每秒60次。 + +如果有一个bgs是1秒长的心跳声,我们把它注册到了全塔属性的音效中。 + +假设这个bgs要被用于MT0层,那么我们在MT0层的“楼层属性——并行脚本”中写这样的代码: ``` js -////// 绘制背景层 ////// -maps.prototype.drawBg = function (floorId, ctx) { - var onMap = ctx == null; - if (onMap) { - ctx = core.canvas.bg; - core.clearMap(ctx); - } - this._drawBg_drawBackground(floorId, ctx); - // ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。 - this._drawFloorImages(floorId, ctx, 'bg'); - this._drawBgFgMap(floorId, ctx, 'bg', onMap); -} + 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 + +} // 其他特效也是一样的用法。 ``` - -楼层贴图可以被事件隐藏和显示,详见[隐藏贴图](event#hideFloorImg:隐藏贴图)的写法。 - -**如果要让贴图的某些点不可通行,则可以使用noPass或者空气墙。** - -!> 小技巧:可以使用帧动画贴图来贴一些大型怪物,比如魔龙、章鱼,或者《永不复还》中的恐怖利刃等等。如果使用帧贴图来贴怪物,则可以使用一个“透明的怪物”放置在对应位置并写上具体属性数值(这样就可以进行战斗和显伤了);然后可以使用[displayIdInBook](element#怪物的朝向问题)在怪物手册中将该透明怪物映射到另一个有素材的怪物ID上。战斗完毕后使用[隐藏贴图](event#hideFloorImg:隐藏贴图)事件将贴图隐藏即可。 - -### 使用便捷PS工具生成素材 - -如果我们有更多的素材要求,我们可以使用“便捷PS工具”进行处理。 - -![便捷PS工具](img/ps.png) - -我们可以打开有需求改变的素材,和我们需要被替换的素材,然后简单的Ctrl+C和Ctrl+V操作即可。 - -便捷PS工具同样支持图片色相的修改,和RMXP几乎完全相同。 - -用这种方式,我们能极快地替换或素材,包括需要新增的怪物。 - -### 添加素材到游戏 - -在使用地图编辑器编辑的过程中,我们有可能会出现“该数字和ID未被定义”的错误提示。 - -这是因为,该素材没有被定义,无法被游戏所识别。 - -!> 在V2.0中,我们可以简单的在地图编辑器中新增素材,以及定义新增素材的ID和数字,但是仍然**强烈建议**对素材的机制进行了解。 - -#### 素材的机制 - -本塔所有的素材都拥有三个属性:**ID**,**索引**,**数字**。 -- **ID** 为该素材的唯一标识符,任何两个素材的ID都不能相同。 -- **索引** 为该素材的在对应图片上的图标索引,即该素材是图片上的第几个。 -- **数字** 为该素材的对应数字,以方便地图的生成和存储。 - -**`ID-索引` 对应关系定义在icons.js文件中。该文件将唯一确定一个ID在图片上所在的位置。** - -**`ID-数字` 对应关系定义在maps.js文件中。该文件将唯一确定一个ID对应的数字是多少。** - -在V2.0中,我们可以在地图编辑器中很方便查看每个图块的三个属性信息。 - -#### 注册素材 - -在V2.0的地图编辑器中,要注册新素材,我们只需要在图块属性一栏输入新素材的ID和数字。 - -![素材注册](./img/register.png) - -ID必须由数字字母下划线组成,数字在1000以内,且均不能和已有的进行重复。 - -之后刷新编辑器即可。 - -我们也可以进行自动注册,只需要点击“自动注册”按钮,将对该栏下所有未注册的素材进行自动注册(自动分配ID和数字)。 - -素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。 - -#### Autotile自动元件的注册 - -但是,通过上面这种方式,我们是没办法新增并注册Autotile的。 - -除了替换样板现有的几个外,如果我们还需要新添加Autotile,则: - -1. 下拉框切到“追加素材”,导入文件到画板,然后导入一张Autotile自动元件图片。 -2. 下拉框选择autotile,然后点“追加” -3. 看到成功的提示后刷新编辑器即可。 - -### 额外素材 - -从V2.4.2开始,HTML5魔塔样板开始支持额外素材。 - -具体而言,通过上面的“素材导入”的方式,确实可以有效地添加素材到游戏。但是,如果想增加大量自定义素材,需要通过便捷PS工具将这些素材全部导入到`terrains.png`中,并且全部是单列,极度不友好。这也导致了野外风的制作相对变得很困难,增加了大量素材处理的工作量。 - -额外素材就是为了解决这个问题而被提出。 - -所谓`额外素材`,即用户可以自定导入任意张素材图片,无需PS,无需注册,即可直接在游戏中使用。这一点已经十分向RM靠拢了。 - -要使用额外素材,请将你需要的素材图片放在 `project\tilesets` 目录下,并在`全塔属性`的`tilesets`中定义图片名。 -**该素材的宽高必须都是32的倍数,且图片上的总图块数不超过1000(即最多有1000个32*32的图块在该图片上)。** -```json -// 在全塔属性中的tilesets导入素材 -"tilesets": ["1.png", "2.png"] // 导入两个额外素材,文件名分别是1.png和2.png -``` - -刷新后,系统会自动加载该素材并添加到素材区。 - -额外素材无需导入,无需注册。在`tilesets`中定义了图片后,即可直接使用绘图,无需再注册其数字和ID。其ID、索引和数字均为系统自动分配,且不允许修改。 - -请注意,额外素材的ID、索引和数字,与该图片在tilesets数组中的index及该素材在图片上的位置都有关系。 - -!> **因此如果对`tilesets`数组随意删除或修改顺序,可能会导致所有额外素材全部发生变化!这点请务必注意!!!** - -除此之外,额外素材在游戏中的使用和正式素材都是一致的,也能在前景或背景图层绘制。 - -额外素材可以使用“tileset平铺”的方式进行绘制,一次绘制一个矩形区域。 - -“辅助工具”中提供了“额外素材合并”,如果使用此功能,请不要对额外素材进行基于ID、索引和数字的判定和读写等操作,如确有此需求,可以创建一些玩家不可达也不可预览的隐藏样板层,然后用等量代换的办法去从样板层取用。 -## 自定义道具效果 - -本节中将继续介绍如何自己编辑一个道具的效果。 - -道具效果的具体实现都在 `project\items.js` 中。 -### 即捡即用类道具(cls: items) -对于即捡即用类道具,如宝石、血瓶等,我们可以简单地修改全塔属性中的 `values` 一栏即可。 - -如果你想要同种宝石在不同层效果不同的话,可以进行如下操作: - -1. 在楼层的ratio中定义宝石的比率(比如1-10的写1,11-20层写2等) -2. 修改获得道具的itemEffect函数(编辑器中双击进行编辑) - -``` js -core.status.hero.atk += core.values.redGem * core.status.thisMap.ratio -``` - -如果不是倍数增加(比如线性增加)也可以类似来写 - -``` js -// 一个二倍线性增加的例子 -core.status.hero.atk += core.values.redGem + 2*core.status.thisMap.ratio -``` - -### 消耗类道具(cls: tools);永久类道具(cls: constants) - -如果要自己实现消耗类道具或永久类道具的使用效果,则需修改`items.js`中的canUseItem和useItem两个函数。 - -具体过程比较复杂,需要一定的JS能力,在这里就不多说了,有需求可以找`艾之葵`进行了解。 - -从V2.6.6起,道具的“图块属性”中,提供了 `useItemEvent` 项,您可以用事件而不是脚本去书写道具的使用效果(对 `cls: items` 也有效但会打断寻路),参见样板的黄宝石和生命魔杖。 - -如果弄不清楚 `canUseItem` ,也可以干脆统一填写为 `"true"`,先斩后奏,并在使用效果中再行判定,如果发现其实使用失败了,就悄咪咪返还给勇士一个该道具,参见样板的破墙镐和炸弹。 -### 实战!拿到神圣盾后免疫吸血、领域、夹击效果 - -1. 在itemEffect中修改拿到神圣盾时的效果,标记一个自定义Flag。 -``` js -core.status.hero.def += 100; -core.setFlag("shield5", true); // 增加一个自定义Flag:已经拿到神圣盾 -``` -2. 免疫吸血效果:在脚本编辑的getDamageInfo中,编辑成如果存在神圣盾标记,吸血伤害为0。 -``` js -function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) { -// ... 上略 - // 吸血 - if (this.hasSpecial(mon_special, 11)) { - var vampireDamage = hero_hp * enemy.value; - - // 如果有神圣盾免疫吸血等可以在这里写 - // 也可以用hasItem或hasEquip来判断装备 - if (core.hasFlag("shield5")) vampireDamage = 0; // 存在神圣盾,吸血伤害为0 - - vampireDamage = Math.floor(vampireDamage) || 0; - // 加到自身 - if (enemy.add) // 如果加到自身 - mon_hp += vampireDamage; - - initDamage += vampireDamage; - } -// ... 下略 -``` -3. 免疫领域、夹击、阻击效果:在2.4.1之后,可以直接将flag:no_zone设为true来免疫领域效果,其他几个同理。 -``` json -[ // 写在获得道具后事件 - // 设置不同的flag可以分别无视对应的阻激夹域效果 - {"type": "setValue", "name": "flag:no_zone", "value": "true"}, // 免疫领域 - {"type": "setValue", "name": "flag:no_repulse", "value": "true"}, // 免疫阻击 - {"type": "setValue", "name": "flag:no_laser", "value": "true"}, // 免疫激光 - {"type": "setValue", "name": "flag:no_betweenAttack", "value": "true"}, // 免疫夹击 - {"type": "setValue", "name": "flag:no_ambush", "value": "true"}, // 免疫捕捉 - {"type": "setValue", "name": "item:amulet", "value": "1"} // 免疫路障 -] -``` -4. 如果有更高的需求,例如想让吸血效果变成一半,则还是在上面这些地方进行对应的修改即可。 - -## 新增门和对应的钥匙 -如果要新增一个门和对应的钥匙,只需要进行如下三步: -1. 在 `project\images\animates.png` 或 `npc48.png` 中添加开门的四帧动画并注册,其中第一帧也作为未开启的静止门。 -2. 在图块属性中将其默认触发器改为 `openDoor`(如果依然写 `null` 则和三色墙一样可以用来制作暗墙),动画帧数填 `1` 表示门未开启时静止在第一帧。 -3. 在 `doorInfo` 中填写需要哪些钥匙(可以填任何消耗类道具)各多少把,开关门时间、开关门分别播放什么音效等。 ## 覆盖楼传事件 对于特殊的塔,我们可以考虑修改楼传事件来完成一些特殊的要求,比如镜子可以按楼传来切换表里。 @@ -314,23 +128,6 @@ function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) { 除了覆盖楼传事件外,对于快捷商店、虚拟键盘等等也可以进行覆盖,只不过是仿照上述代码重写对应的函数(`openQuickShop`,`openKeyBoard`)即可。 -## 自定义怪物属性 - -如果你对现有的怪物不满意,想自行添加怪物属性也是可以的。具体参见脚本编辑的 `getSpecials`。 - -你需自己指定一个special数字,修改属性名和属性提示文字。提示文字可以直接写字符串,或写个函数传入怪物。 - -如果要改动怪物在手册中的显示数值(也会被用于伤害计算,如模仿),请修改下面的 `getEnemyInfo` 函数。 - -如果要修改伤害计算公式,请修改下面的 `getDamageInfo` 函数。请注意,如果无法战斗,该函数必须返回`null`。 - -!> 如果改动了伤害计算公式,可能导致临界计算崩掉,因此建议将全塔属性中的`useLoop`置为true。 - -对于毒衰咒、自爆、退化怪物和加点、仇恨值累加等战斗后结算在脚本编辑中的 `afterBattle` 函数中。 - -对于领域、夹击、阻击、激光、捕捉怪物的检查在脚本编辑中的 `updateCheckBlock` 函数中。 - -如果想给怪物在血攻防之外添加新的数值项,请阅读 `@zhaouv` 撰写的另一篇文档,并配置表格来实现。 ## 自定义快捷键 如果需要绑定某个快捷键为处理一段事件,也是可行的。 @@ -363,16 +160,6 @@ case 89: // 使用该按键的keyCode,比如Y键就是89 可以使用altKey来判断Alt键是否被同时按下。 -## 公共事件 - -从V2.5.4开始,样板提供了“公共事件”下拉框,我们可以在里面用事件编辑器进行编辑,并通过`{"type":"insert"}`进行调用。 - -![公共事件](./img/commonEvent.png) - -具体详见[插入公共事件或另一个地点的事件并执行](event#insert:插入公共事件或另一个地点的事件并执行)。 - -当然,继续使用**插件**的写法也是可以的。 - ## 插件系统 在H5中,提供了“插件”系统。在V2.6中提供了一个插件下拉框,用户可以自行创建和写插件。 @@ -400,20 +187,6 @@ this.myfunc = function(x) { 详见[函数的转发](script#函数的转发)。 -## 标题界面事件化 - -从V2.5.3开始,我们可以将标题界面的绘制和游戏开始用事件来完成。可以通过绘制画布、全塔属性,flags中的startUsingCanvas可以决定是否开启标题界面事件化。 - -然后就可以使用“事件流”的形式来绘制标题界面、提供选项等等。 - -在这里可以调用任意事件。例如,可以贴若干个图,可以事件切换楼层到某个剧情层再执行若干事件,等等。 - -关于选项,样板默认给出的是最简单的choices事件;你也可以使用贴按钮图,循环处理+等待操作来定制自己的按钮点击效果。 - -!> 开始游戏、读取存档、录像回放的效果已经默认给出,请不要修改或删减这些内容,以免出现问题。 - -标题界面事件全部处理完后,将再继续执行startText事件。 - ## 手机端按键模式 从V2.5.3以后,我们可以给手机端增加按键了,这样将非常有利于技能的释放。 @@ -471,14 +244,13 @@ this.myfunc = function(x) { 如果是在需要给状态栏新定义项目,则需要进行如下几个操作: 1. 定义ID;比如攻速我就定义speed,暴击可以简单的定义baoji;你也可以定义其他的ID,但是不能和已有的重复。这里以speed为例。 -2. 在index.html的statusBar中(46行起),进行该状态栏项的定义。仿照其他几项,插在其应当显示的位置,注意替换掉相应的ID。 +2. 在index.html的statusBar中,进行该状态栏项的定义。仿照其他几项,插在其应当显示的位置,注意替换掉相应的ID。 ``` html

``` -3. 在editor.html中的statusBar(383行起),仿照第二点同样添加;这一项如果不进行则会地图编辑器报错。editor-mobile.html同理。 4. 使用便捷PS工具,打开project/icons.png,新增一行并将魔力的图标P上去;记下其索引比如37(从0开始数)。 5. 在main.js的this.statusBar中增加图片、图标和内容的定义。 ``` js @@ -502,7 +274,7 @@ core.statusBar.speed.innerHTML = core.getStatus('speed'); // 设置其显示内容为flag:speed值,无需额外进行定义。 core.statusBar.speed.innerHTML = core.getFlag('speed', 0); ``` -总的来说不建议这样做,因为 `main.js` 和几个 `html` 文件不在 `project` 文件夹,会导致随样板更新迁移接档变得困难。 +总的来说不建议这样做,因为 `main.js` 和 `html` 文件不在 `project` 文件夹,会导致随样板更新迁移接档变得困难。 ## 技能塔的支持 从V2.5开始,内置了"二倍斩"技能,可以仿照其制作自己的技能。要支持技能塔,可能需要如下几个方面: - 魔力(和上限)的添加;技能的定义 diff --git a/_docs/start.md b/_docs/start.md index 5f698050..b06a2ba0 100644 --- a/_docs/start.md +++ b/_docs/start.md @@ -3,276 +3,86 @@ 在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔! ## 前置需求 -你需要满足如下条件才能进行制作: -- Windows 8 以上操作系统;Windows 7 需要安装 .Net Framework 4.0。(能打开同目录下的“启动服务.exe”即可) - - 其他电脑则需安装 [python 3.8.2](https://www.python.org/getit/) 或更高版本,能打开server.py即可( Windows 也可以这样做)。 - - 安卓手机端需要下载最新版的 [HTML5安卓造塔器](https://h5mota.com/games/_client/H5motaMaker.apk)。 -- [Chrome浏览器](https://www.google.cn/chrome/)。其他浏览器可能会导致本地服务器产生闪退等现象。 -- 强烈推荐安装一个很好的文本编辑器:[VSCode](https://code.visualstudio.com/download)。在某些需要直接修改文件的场合,可能会非常重要。 +你需要满足如下条件才能进行制作:[样板下载地址](https://github.com/ckcz123/mota-js/releases)。 +1. 操作系统: + - Win8或更高版本,Win7则需要安装 .Net Framework + 4.0(能打开根目录的“启动服务.exe”即可) + - 其他电脑则需安装[python + 3.8.3](https://www.python.org/downloads/)或更高版本,能运行根目录的server.py即可(Windows也可以这样做)。 + - 安卓手机需要安装[HTML5安卓造塔器](http://h5mota.com/games/_client/H5motaMaker.apk),推荐搭配ES文件浏览器。 +2. [chrome浏览器](http://google.cn/chrome):其他浏览器可能导致本地服务闪退。 +3. (强烈推荐)[VScode](http://code.visualstudio.com/download):最适合HTML5项目的文本编辑器,能进行跨文件的正则搜索和替换,也能完整发挥根目录的runtime.d.ts文件的作用。 只要满足了上述条件,你就可以开始做自己的塔啦! - ## 启动HTTP服务 -与编辑器闭源的 RPG Maker MV 不同,本样板对文件的绝大部分修改是通过网页编辑器经由本地 HTTP 服务完成的,这样做也有助于编辑器跨平台并最大限度地复用运行时代码,还可以让玩家在在线游戏时查看游戏工程。
-在根目录下有一个“启动服务.exe”,运行之。(非 Windows 电脑则需使用命令行运行 server.py,手机端则使用造塔APP。) -![启动服务](img/server.png) -* “启动游戏”按钮将打开一个网页(您也可以手动在浏览器中键入 127.0.0.1:1055/index.html ,同时开启多个启动服务则1056、1057顺延),你能在里面看到现在游戏的效果。 -* “地图编辑器”允许你以可视化的方式进行编辑游戏(这个名称为历史遗留,两年前它真的只能编辑地图)。您也可以手动在浏览器中键入 127.0.0.1:1055/editor.html -* 以下为 Windows 专用的一些辅助工具,由C#编写: -* “便捷PS工具”能让你很方便的对自定义素材进行添加。参见[自定义素材](personalization#自定义素材)。 -* “地图生成器”能让你从已有的截图(如RMXP项目)中立刻生成可被本样板识别的地图数据。 -* “怪物数据导出”能让你从RMXP(RPG Maker XP 1.03,下同)中导出怪物数据而被HTML5魔塔使用。 -* “RM动画导出”能让你从RMXP中导出动画而被HTML5魔塔使用。 -* “JS代码压缩”能对JS代码和音像素材进行压缩,从而减少IO请求数和文件大小。 -* “额外素材合并”能将用到的tileset素材重新拼成更少的图片,并更新对应的地图矩阵。 -* “伤害和临界值计算器”是一个很便捷的小工具,能对怪物的伤害和临界值进行计算。 -* “动画编辑器”能让你编辑已有的animate动画文件,或自己利用图片制作全新的动画。 -* “[怪物数据生成机](https://pan.baidu.com/s/1w-JMg-ZPRvbsqbbtOwORGA#list/path=%2F -)”能够借助AI生成适当强度的怪物,此工具需要手动下载。 +与编辑器闭源的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/v2.7/editor.png) +------------------------------- +如上图,编辑器页面的结构分为三大部分。左边叫数据区,中央叫地图区,右侧叫素材区,竖屏状态下同时只能显示其中一个,需要经常来回切换。 -## 绘制地图 - -有两种绘制地图的方式:从头绘制地图;从RMXP中导入已有的地图。 - -### 从头绘制地图 - -我们直接打开“地图编辑器”,可以看到一个可视化的UI界面。 - -楼层切换到MT0层,然后可以开始任意绘制地图。 - -![绘制地图](./img/drawmap.jpg) - -如果提示“该素材未被定义”或有红色问号框,请参见[素材注册](#素材注册)。 -
绘制地图时可以右键弹出菜单,复制、交换、删除图块、选中素材、更改出生点或快速创建常用事件。
从V2.4.2开始,可以使用 `Alt+0~9` 对一个图块素材快速保存,大键盘 `0~9` 来快速选用。
-从V2.6.6开始,最近使用的图块也会直接显示在地图下方,您可以随时选取或清空它们。 -
从V2.7开始,除最近使用的图块外,还显示了最常使用的图块,您可以右击它们来置顶和取消置顶。 - -您还可以用右键在地图上拖动或用左键在素材区 `tileset` 区域拖动来批量选中图块,从而进行复制和平铺绘制。 -### 从RMXP导入已有的地图 -!> 注:现在已经不推荐此方法,如需从RMXP复刻魔塔请观看 [RM转H5刻塔器使用教程](https://www.bilibili.com/video/av43125840) 进行操作。
-从V2.7起,RM转H5刻塔器被废弃,导出结果仅供阅读,仍需手动翻译成新样板的合适写法。
-如果我们想复刻一个现有的,已经被RMXP所制作的塔,也有很便捷的方式,那就是用到我们的“地图生成器”。 - -首先,我们打开RMXP和对应的项目,可以看到它的地图。 - -![绘制地图](./img/rmxp2.png) - -我们打开地图编辑器,创建一个地图,宽高需要和RM中的地图一致。 -
之后,我们打开 Windows 10 自带的“截图工具”(非 Windows 10 请使用 Print Screen 键全屏截图后粘贴到“画图”中裁剪,或使用微信/QQ等自带的截图功能),并将整个地图有效区域截图下来,复制到剪切板。 -![绘制地图](./img/rmxp3.png) - -截图时请注意:**只截取有效游戏空间内数据,并且有效空间内的范围必须是创建的地图的大小(至少为13x13)。** - -确认地图的图片文件已经复制到剪切板后,我们打开“地图生成器”,并点“加载图片”。大约1-2秒后,可以得到地图的数据。 - -![生成地图](./img/map1.png) - -然后点击“复制地图”,即可将地图数据复制到剪切板,然后再地图编辑器中切换到“地图编辑”,并在左边的框进行粘贴。 - -!> **地图生成器默认只支持已被定义的素材。如果有自定义素材需求(例如原版的1层小塔那种素材),请先[导入并注册素材](#素材注册)后再进行操作。** -!> **请确保截图范围为你创建的地图大小,并且保证每个位置的像素都是32x32(譬如48×48的RPG Maker MV就需要缩小到2/3比例再截图)。** - -!> **如果宽度超过13,地图生成器将无法显示完全,但是仍然可以粘贴到地图编辑器中进行修改。** - -!> **地图生成器靠左上角来确定偏移量,如果左上角是全黑或者星空之类的素材可能导致识别不准,此时请在左上角放置一个岩浆后再进行截图识别。** - -![岩浆](./img/rmxp4.jpg) - -## 编辑属性 - -当地图绘制完毕后,我们可能需要进行属性的编辑。属性编辑有四类:楼层属性、怪物属性、道具属性、全塔属性。 -### 楼层属性(快捷键V) -我们切换到楼层属性,并进行一项项的编辑。将鼠标放在中间有具体的每一项注释,这里不再细说。 -
从V2.7起,表格的注释被大幅度精简,因此没有下图中显示的那么冗长,上下楼点属性可以通过地图选点指定。
-另外,地面图块被改为了允许使用任何图块(不一定非要是 `terrains.png` 中的)。
-色调的设置提供了颜色选择器,贴图的设置则通过事件编辑器实现,地图的宽高也可以修改了。
-“宝石血瓶效果”的标识符进行了改动,请参考4种血瓶和3种宝石的拾取效果。 -![楼层属性](./img/floor.png) - -### 怪物属性 - -我们点击右边的怪物图块,可以在左边的框内设置该怪物的各项属性。将鼠标放在中间有具体的每一项注释,这里不再细说。 -
从V2.7起,怪物特殊属性的格式强制为数组(即不再允许写单项,之前的单项0也要改为空数组`[]`),在编辑器中通过勾选框的方式启用。游戏作者在“脚本编辑”`getSpecials`中新追加的特殊属性也将在刷新浏览器页面后出现。
-有关怪物的更详细信息可参见[元件说明:怪物](element#怪物)。 - -![怪物属性](./img/enemy.png) - -### 道具属性 - -同理,点击道具可以对道具属性进行编辑。 -
从V2.6.6起,即捡即用类道具的捡拾效果和其他非装备的使用效果可以通过 `useItemEvent` 项用事件而不是脚本来书写。
-从V2.7起,定义道具属性的js文件被大幅度重构,`text` 和 `tip` 不再通过 `eval` 而是通过模板字符串 `${}` 实现。
-道具子类 `cls` 中的 `keys` 被移除,原本的黄蓝红钥匙的子类被改为 `tools`,
-道具属性中追加了一项“不显示在道具栏”可供您利用,例如制作一些隐藏的剧情物品。
-此外,部分道具的素材被重制,如地震卷轴、怪物手册、楼层传送器、四种解药瓶、金钱袋和两种鞋。
-目前大多数道具都已有默认效果。更多信息可参见[元件说明:道具](element#道具)。 -### 全塔属性(快捷键B) -我们切换到全塔属性,并进行一项项的编辑。同样鼠标放在中间可以查看注释。 -
我们可以在这里定义一些全局的属性,比如开始剧情、宝石血瓶数值,破甲反击净化的比例,以及一些系统开关比如是否启用加点,是否允许负伤害等等。
-!> **注:name作为游戏的唯一标识符必须进行修改,否则可能会导致存档等出现问题。** -
从V2.7起,全塔属性被大幅度重构,同时几类属性之间支持折叠。具体有如下变动: -1. 音像素材的注册半自动化:现在编辑器会自动读取文件系统,将支持的格式的文件列出,还可以预览/试听。具体支持的格式类型,可以通过点击左上角的“配置表格”来查阅和修改(关于“配置表格”的详细用法,请阅读 `@zhaouv` 撰写的另一篇文档)。 -2. 支持个性化字体:请将`.ttf` 格式的字体文件放在 `project\fonts` 文件夹。 -3. 部分素材目录变动:背景音乐从 `project\sounds` 移到了 `project\bgms`,主角行走图和对话框皮肤图以外的图片从 `project\images` 被移到了 `project\materials`,自动元件和 `tileset` 类素材从 `project\images` 被移到了专门提供的新文件夹 `project\autotiles` 和 `project\tilesets`,且对后者的追加总会追加在末尾。 -4. “难度分歧”现在由事件编辑器编写,分为“名称、简写、`flag:hard`值、颜色和事件”五项,含义分别为: - 1. 名称:标题界面点击“开始游戏”后弹出的二级菜单中的名称,您可以简要介绍一下该难度的差异(如减伤比例、初始属性变化)。 - 2. 简写:即游戏中 `core.status.hard` 的值,将作为横屏状态栏左下角(竖屏状态栏右下角,该位置也作为数字键盘切换按钮,故无难度分歧的情况下推荐在这里注明此功能)、存读档界面和在线游戏排行榜中显示的难度名称。该值也允许使用中文,但请注意控制字数。 - 3. `flag:hard` 值:同一个名称的游戏结局有多个难度有人通关时,在线游戏排行榜中只统计此flag值最大的难度。 - 4. 颜色:`flag:__hardColor__` 的值,将作为上述“简写”在状态栏和存读档界面的文字颜色。习惯上低难度用冷色,高难度用暖色。 - 5. 事件:在全塔属性 `startText` 之前执行的事件,可以设置一些初始属性和道具。 -5. css设置项被合并,现在叫“主样式”,由事件编辑器编辑,同时横竖屏的标题画面支持用不同的图片啦~ -6. 编辑器和游戏中的所有“魔防”都已改名为“护盾”,所有 `experience` 都已改为 `exp` -7. 主角的初始行走图(包括文件名)可以直接修改了,同时还支持了踏步动画(可以用于剧情对话中,但朝上会自动改为朝下否则不好看),这在表现长翅膀的主角时非常有用。 -8. 第一代全局商店被彻底重构,不再支持长按连续购买。需要自行处理扣钱和涨价问题,但用法也更灵活了,功能也更自由了。 -9. 全局开关被大幅度重构,形如“状态栏是否显示某某项”的开关被合并。其他一些影响道具属性的开关被删除(破炸冰的目标个数请直接在使用效果中指定),检查控制台和夹击上下整也被删除。 - -上述属性全部修改完毕后,保存,然后点启动服务的“开始游戏”,就可以看到我们写的游戏效果啦! - -## 新建和删除楼层、调节尺寸 - -如果要新建楼层,请切换到“地图编辑”,输入新的楼层ID,并新建空白地图,然后刷新编辑器。 - -请注意,楼层ID必须是由字母、数字和下划线组成且不能以数字开头,不能和任何已有的楼层ID重复。 - -你也可以删除当前楼层(比如几个样板层),只需要点击删除楼层再刷新就行。删除楼层并不会删除文件,只是不再被游戏所引入而已。 - -你可以在全塔属性 - floorIds中看到所有的楼层。其顺序将影响到楼传器的顺序、浏览地图的顺序和上下楼器等的顺序。您可以在这里对它们进行顺序的调换和批量删除,只要注意别把出生楼层删了!
-从V2.6.1起,支持修改楼层ID,修改按钮在楼层属性最下面,修改后请立即刷新浏览器页面。
-从V2.7起,还支持调节地图尺寸。调节按钮的位置同上,“偏移”允许你做出“给13×13地图加一圈外墙”、“截取20×20地图的右下角13×13部分”这样的操作。 -## 事件编辑 - -我们点击任意一个图块,都可以进入事件编辑模式。 - -![地图选点](./img/point.png) - -从上至下有若干项,分别代表该点的一些事件。有关事件的详细信息请参见[事件](event)。 - -如果一个点存在事件,则在地图编辑器中该点的左下角会有一个小方框表示。 -
红色为普通事件,橙色为自动事件,黄色为战后事件,绿色为楼层转换,青色为拾获道具后事件,靛色为不可通行性(不是事件),粉(紫)色为开门后事件。 -## 自定义素材的添加与注册 - -有关素材的更多详细信息,包括素材的机制等内容,请参见[自定义素材](personalization#自定义素材)。 - -这里只对如何导入(新增)素材以及注册素材进行简要介绍。 - -### 新素材的添加 - -如果我们需要新增加一些素材,比如样板中没有的怪物等。 -
我们可以从启动服务打开便捷PS工具,然后选择对应的图片进行添加。非Windows系统,请使用“追加素材”功能。 -![便捷PS工具](img/ps.png) -在左边选择你要导入到的文件,比如怪物就是enemys.png,道具就是items.png等等,再在右边导入你的新素材图片。
-之后就可以简单的使用 C 和 V 来复制粘贴了。
-保存后,刷新地图编辑器即可生效。 - -### 素材注册 - -当我们使用新素材后,可能会出现素材不存在的情况,此时绘图时会存在红色问号方框。 - -![素材注册](./img/register.png) - -出现这种情况,是因为我们没有将该素材定义到游戏中,也无法进行使用。 -
要解决这个问题,只需要在左边的图块属性中定义新的图块ID和图块数字即可。ID必须由数字字母下划线组成,ID不允许使用纯数字。图块数字在1000以内,ID和图块数字均不能和已有的重复。
-有关图块的ID和数字定义请参见[素材的机制](personalization#素材的机制)。 - -之后刷新编辑器即可。 -
也可以进行自动注册,只需要点击“自动注册”按钮,将对该栏下所有未注册的素材进行自动注册(自动分配ID和数字,随后强烈建议立即手动修改ID)。
-素材注册完毕后,即可在游戏中正常使用,也可以被地图生成器所识别(需要重开地图生成器)。 - -### 额外素材 - -从2.4.2开始,H5魔塔样板支持额外素材,你可以导入任意个类似RM中的tilesets文件,且无需注册即可使用。 - -要使用额外素材,请在`全塔属性`中的`tilesets`项,添加额外素材的图片名称(从V2.7起,额外素材的图片文件要放在 `project\tilestes` 文件夹),刷新后即可在地图编辑器中使用。 - -额外素材不可注册,其数字、ID和索引都是和该图块在图片上的位置相关,不可编辑。 - -有关额外素材的更多说明参见[额外素材](personalization#额外素材) +请尤其注意中央下方的下拉框,您可以随时按下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. 编辑勇士的出生点和初始属性: + 1. 滚轮切换到主塔0层,右击地图任意位置,绑定出生点为此点(会有一个大大的白色S字母显示出来)。 + 2. 按下B键切换到“全塔属性”,填写core.firstData.hero中勇士的各项初始属性,以及一些全局的数值(如四种血瓶和三种宝石的效果、破甲反击净化的比例等,注意“唯一英文标识符”一定要修改!)。 + 3. 在数据区使用滚轮向下翻(您可以随时折叠全塔属性的几大部分),按需编辑下面的大量勾选框(主要就是状态栏的那些显示项)。 +2. 从素材区选择各种各样的非NPC图块绘制在地图上,如门、怪物、道具、楼梯、路障、箭头、踩灯、箱子等。每当选中一个素材时,数据区就进入了“图块属性”模式,您可以去填写道具的一些说明、以及修改其他一些图块的可通行性等。注意滑冰(触发器为ski)要画在背景层。如果您需要制作机关门,请简单地将机关门和守卫(不支持阻击怪和炸弹)画在地图上,再右击机关门快速绑定即可。(看到机关门左下角出现橙色小方块、守卫们左下角出现黄色小方块即说明绑定成功) +3. 如果您需要制作多个楼层,只需按下Z键将数据区切换到“地图编辑”模式,然后“新建空白地图”即可,不同楼层之间简单地通过楼梯来往返,您可以将楼梯画在地图上再右击快速绑定即可。(看到楼梯左下角出现绿色小方块即说明绑定成功)各个楼层的属性可以通过按下V键将数据区切换到“楼层属性”模式来填写,如能否使用楼传、是否为地下层、画面色调、宝石血瓶倍率等。 +4. 从素材区选择您所使用的各种怪物,在数据区填写它们的各项属性,其中“特殊属性”是通过多选框来编辑的。 +5. 游戏胜利的触发:滚轮切换到样板1层,单击地图上的公主,按下Ctrl+C复制。滚轮切换回您的boss层,(记得给boss设置不可被炸哦)单击boss身后的任何一个空格子,按下Ctrl+V粘贴即可。这样玩家触碰到公主游戏就会胜利。 ## 控制台调试 -HTML5游戏都是可以进行控制台调试的。
-当我们使用Chrome进入游戏后,可以按 `Ctrl+Shift+I` (F12),并找到 `Console` 控制台。 -![控制台](./img/console.png) +![image](img/v2.7/console.png) +--------------------------------- +HTML5项目都是可以进行控制台调试的,下面以edge浏览器为例介绍其部分操作: -在控制台中,我们可以输入一些命令对游戏进行调试,常见的命令有: - -- `core.status.floorId` 获得当前层的floorId。 -- `core.status.thisMap` 获得当前地图信息。例如`core.status.thisMap.blocks`可以获得当前层所有图块。 -- `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.material.items.pickaxe`就是获得破墙镐的信息。 -- `flags.debug = true` 开启调试模式;此模式下可以按住 `Ctrl` 键进行穿墙。 -- `core.updateStatusBar()` 立刻更新状态栏和地图显伤,并检查自动事件。 -- `core.setStatus('atk', 1000)` 直接设置勇士的某项属性。本句等价于 `core.status.hero.atk = 1000`。 -- `core.getStatus('atk')` 返回勇士当前某项属性数值。本句等价于 `core.status.hero.atk`。 -- `core.setItem('pickaxe', 10)` 直接设置勇士某个道具的个数。这里可以需要写道具的ID。 -- `core.getItem('pickaxe', 2)` 令勇士获得两个破墙镐。 -- `core.itemCount('pickaxe')` 返回勇士某个道具的个数。 -- `core.hasItem('pickaxe')` 返回勇士是否拥有某个道具。等价于`core.itemCount('pickaxe') > 0`。 -- `core.getEquip(0)` 返回0号装备类型(武器)的当前装备的itemId,不存在则返回null -- `core.hasEquip('sword1')` 返回某个装备当前是否处于被装备状态 -- `core.setFlag('xxx', 1)` 设置某个flag/自定义变量的值。 -- `core.getFlag('xxx', 10)` 获得某个flag/自定义变量的值;如果该项不存在(未被定义),则返回第二个参数的值。 -- `core.hasFlag('xxx')` 返回是否存在某个变量且不为六种广义 `false` 。等价于 `!!core.getFlag('xxx')` 。 -- `core.setFlag('xxx')` 删除某个flag/自定义变量 -- `core.insertAction(list)` 执行一个公共事件或一段自定义事件。比如 `core.insertAction(["剧情文本"])` 将执行一个剧情文本显示事件。 -- `core.changeFloor('MT2', 'downFloor')` 立刻执行楼层切换到MT2层的下楼点位置。 -- `core.changeFloor('MT5', null, {'x': 4, 'y': 7})` 立刻切换楼层到MT5层的(4,7)点。 -- `core.getBlock(3, 5, 'MT1')` 获得当前地图上某一个块的信息。第三个参数为floorId,可省略表示当前楼层。 -- `core.getBlockId(3, 5, 'MT1')` 获得当前地图上某一个点的图块ID。第三个参数为floorId,可省略表示当前楼层。 -- `core.resetMap()` 重置当前层地图。 -- …… - -更多API和详细参数介绍可参见[API列表](api)。 - -## 编辑器的基本操作 -- **H** 查看所有快捷键 -- **Alt+0~9, 0~9** 保存和读取当前选中图块(V2.7起,也可以用最常/最近使用图块置顶来代替) -- **W/A/S/D** 移动大地图 -- **Ctrl+Z** 撤销上次绘图 -- **Ctrl+Y** 重做上次绘图 -- **PgUp/PgDn,或滚轮** 切换楼层 -- **Ctrl+S** 保存事件编辑器/脚本编辑器 -- **地图上单击** 选中该点 -- **DELETE键** 删除选中点的事件和图块 -- **地图上双击** 选中该点图块 -- **ESC键** 取消选中的点 -- **地图上右键** 弹出菜单栏,包括选中、复制、交换、清除、更改出生点、快速绑定等操作 -- **地图上右键按住并拖动** 批量框选图块,然后可以 `ctrl+C/V` 复制到别处 -- **素材区tileset区域左键按住并拖动** 批量框选素材,然后可以单击地图批量绘制、在地图上拉框平铺 -- **事件编辑器中Ctrl+C, Ctrl+X, 右键, 双击等** 执行相应操作,如进入多行编辑、UI绘制预览等 - -## 报错处理 - -有时候刷新后可能地图编辑器页面变成空白,即无法正确加载,游戏也无法正常进入。 - -出现这种问题的原因往往是如下几种: -- 手动直接打开并错误编辑了文件 -- 文件不存在(被误删等) -- 楼层floorId不合法(必须是字母数字下划线组成,且不能以数字开头) -- 楼层floorId定义存在重复(比如定义了两个MT0层) -- 初始楼层ID不存在(比如修改了全塔属性中的初始楼层ID,但是实际的该ID不存在,也会出错) -- ……(可能各种奇怪的报错问题) - -出现这种问题,(在Chrome浏览器中)请按Ctrl+Shift+I打开控制台,并找到Console查看报错。 - -一般都会具体到哪个楼层文件出错。 - -解决方式:哪个楼层文件出错,请使用VSCode等打开project目录下的data.js文件,并将出错的那个楼层定义删除。 - -例如下面这个问题: - -![检查错误](./img/chrome.png) - -那么使用VSCode打开data.js文件,并将 "floorIds": [..., "MT1"] 这里对它的楼层定义删除,再刷新即可。 - -![删除ID](./img/floorid.png) - -请注意,手动删除楼层时一定要确保“初始楼层ID”是一个有效且存在的floorId! -
如有任何无法解决的问题,欢迎加 QQ 群 [959329661](https://jq.qq.com/?_wv=1027&k=5C87qeQ) 寻求帮助。 +首先按下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)。 +``` js + alert('Hello world!'); // 弹窗警告,请勿放在正常游戏流程中可以触发的地方 + console.log('Hello world'); // 在控制台打印一条信息,可用于游戏流程的任何部分 + Math.xxx(); // 执行一个数学函数计算,如Math.random()会得到一个小于1的随机正数 + // 以上是所有网页通用的命令,下面介绍HTML5魔塔样板特有的两个API. + // 样板API都是以core.xxx开头的,比如: + core.material; // 查看游戏的所有元件(只读),如动画、音频、图片、道具和怪物等 + core.status; // 查看游戏的所有状态,其中又以core.status.hero为核心 + core.getItem('yellowKey', n); // 获得n个某道具(支持即捡即用类,n不写视为1),提示并播放音效 +``` ========================================================================================== [继续阅读下一章:元件说明](element)