From 55e153928b59d50eb3e8c0e5a8afbc2e2a7bcb40 Mon Sep 17 00:00:00 2001 From: oc Date: Wed, 14 Mar 2018 00:22:34 +0800 Subject: [PATCH] V2.0 Docs --- docs/V2.0.md | 89 +++++++++++++++++++++++++++++ docs/_sidebar.md | 1 + docs/editor.md | 51 ----------------- docs/element.md | 24 ++++---- docs/event.md | 107 +++++++++++++++++++++------------- docs/img/floordata.png | Bin 32686 -> 5801 bytes docs/img/server.png | Bin 7226 -> 6396 bytes docs/personalization.md | 117 ++++++++++++++++++++++---------------- docs/start.md | 36 +++++++++--- project/floors/MT0.js | 2 +- project/floors/sample0.js | 2 +- project/floors/sample1.js | 2 +- project/floors/sample2.js | 2 +- 13 files changed, 268 insertions(+), 165 deletions(-) create mode 100644 docs/V2.0.md delete mode 100644 docs/editor.md diff --git a/docs/V2.0.md b/docs/V2.0.md new file mode 100644 index 00000000..66fa428e --- /dev/null +++ b/docs/V2.0.md @@ -0,0 +1,89 @@ +# V2.0版本介绍 + +?> 目前版本**v2.0**,上次更新时间:* {docsify-updated} * + +目前样板已经更新到V2.0版本,本章将对V2.0的一些内容进行介绍。 + +请确保已经看过前面的几个文档(2.0都有部分更新),前面已经描述过的东西这里将不再赘述。 + +也欢迎通过看B站的视频教程来具体了解2.0版本的使用方法。 + +## 目录结构的改变 + +在1.x中,所有数据和逻辑都是一体的,例如怪物数据和怪物伤害计算公式等等。这导致样板的版本更新时会十分不便。 + +在2.0中,我们将数据和逻辑进行了分离,拆分成了libs和project两个目录。 + +- libs目录为游戏核心库文件,包括一些游戏逻辑等内容 +- project目录为针对每个塔的目录,是和游戏逻辑是分离的。 + +我们只需要修改project目录下的各项内容,而无需去动libs目录(有特殊需求除外); +将来如果想把塔迁移到新的版本上,也只需要迁移project即可。 + +另外一点的就是,我们将libs目录中的core.js进行了拆分,从而使每个文件的具体工作更加一目了然,也避免了接近6K行的大文件会导致打开IDE的卡顿问题。 + +## 全GUI造塔 + +在1.X版本中,我们提供了一个地图编辑器。但是它的功能十分弱,只能进行绘图的功能,实际的各项操作还是需要通过VSCode打开js文件实际进行编写代码。 + +但是在2.0中,我们大大拓展了地图编辑器的功能,从而达到了“全GUI造塔”的功能,用户再也不用手动打开任何一个文件进行编辑了。 + +GUI界面分为`地图编辑器`,`事件编辑器`和`文本编辑器`。 + +!> 即使现在可以全GUI造塔,也强烈建议对1.X的造塔方式进行了解,因为这是一切的基础。 + +### 地图编辑器 + +地图编辑器分为三个区域,左侧的`编辑区`,中间的`画布区`,右侧的`素材区`。 + +画布区下方有切换地图和编辑器模式的下拉菜单,点击`保存地图`后画布的内容才会真正写入到js文件中。 + +在素材区点击图块时,会选中该图块,此时tips会显示该图块的信息,编辑区会进入图块属性模式,怪物或物品可以直接在里面编辑数值。如果图块的数字和ID没有被定义,则可以直接在左侧定义,**定义新图块后需要保存并刷新页面后才能生效**。 + +在tips中有图块信息时,在画布上点击或拖拽可以把图块画上去,可以使用ctrl+Z撤销操作以及对应的ctrl+Y恢复撤销。擦除方块可以使用素材区最左上角的擦除块。 + +点击界面中的空白,tips中的图块信息会被清空,此时再点击画布上的点,则编辑器会进入地图选点模式。此模式下可以编辑改点的`events`,`afterBattle`,`changeFloor`等事件或者是`canMove`来改变各方向的通行状态。 + +切换地图会使编辑区进入楼层属性模式,这里可以修改首次到达该楼层时会触发的事件`firstArrive`,楼层显示的名称,默认的前景背景图片,默认天气和色调等等。 + +!> 这里不允许编辑楼层的ID,需要修改ID的场合请直接改js文件,并保持三个标识符完全一致。`data.js`中的`floorIds`也需要对应进行修改。 + +全塔属性中编辑整个塔为单位的属性,例如起始剧情`startText`,`name`,提供哪些难度,主角的起始属性,全局商店,各种数值以及系统FLAG等。**创建新塔时需要认真编辑这里面的所有选项。** + +脚本编辑模式可以修改常用的需要更改的函数。例如,给不同的难度设置不同的内容`setInitData`,加点`addPoint`,以及修改游戏中的关于界面`drawAbout`等等。 + +追加素材模式可以导入一个图片到该标签的画板中,然后依次点击画板中的图块,点追加就可以按顺序把这些图片添加到对应的画布区素材的最下方,**需要刷新来生效**。 + +地图编辑模式中可以导入来自地图生成器的地图数组,同时创建新楼层需要在这里通过另存为来实现,可以点清除地图把另存为出的新楼层清空。 + +!> 编辑区的表格可以直接修改,推荐通过双击,在事件编辑器和文本编辑器中进行编辑。编辑区中的修改需要点保存才会生效。 + +### 事件编辑器 + +地图选点中的事件类表格,以及楼层属性中的`firstArrive`和全塔属性的`startText`,在双击时会进入事件编辑器,是由[antlr-blockly](https://github.com/zhaouv/antlr-blockly)生成的图块式的可视化编辑器. + +把左侧的方块拖到面板中,下方就会实时的显示对应的js的代码(以及数值不正确时的提示). + +每个方块点击右键会展开一个菜单,点帮助可以跳转到此文档中对应的内容。利用好复制功能可以极大提高编辑的效率。注释选项请不要使用,编辑器并不会保留这里的注释。 + +`template`中提供了一些模板事件,例如战前剧情,打怪开门。 + +`显示文章`的两个方块,以及`自动剧情文本`,`选项`和`自定义JS脚本`这5个方块,可以通过双击在文本编辑器中(以多行的方式)编辑其中的文字。 + +### 文本编辑器 + +事件编辑器之外的内容双击后由文本编辑器来编辑,是有js高亮支持的多行文本编辑器[CodeMirror](https://github.com/codemirror/CodeMirror),点confirm即可使编辑的文本替换到表格中。 + +### 拓展地图编辑器 + +> 面向有一定编程基础的用户 + +修改`project/`下的`*comment.js`可以让地图编辑器对自己添加的属性有更好的支持.例如: ++ 给`comment.js`中`enemys`加入新的键值对,就可以更方便的给怪物在UI界面中添加对应的值. ++ 在`data.comment.js`中把自己添加的内容标记为叶节点,不再在表格中展开到最末端. + +地图编辑器的部分API见`_server/README.md` + +## 部分事件和API更新 + +在2.0中,有部分的事件和API存在更新,也增加了包括48x32素材的支持,在这里将不再赘述,请仔细阅读前面的几个文档进行了解。 diff --git a/docs/_sidebar.md b/docs/_sidebar.md index 039c2ea0..a7960592 100644 --- a/docs/_sidebar.md +++ b/docs/_sidebar.md @@ -3,4 +3,5 @@ - [元件说明](element) - [事件](event) - [个性化](personalization) +- [V2.0版本介绍](V2.0) - [附录:API列表](api) diff --git a/docs/editor.md b/docs/editor.md deleted file mode 100644 index 3b5470b8..00000000 --- a/docs/editor.md +++ /dev/null @@ -1,51 +0,0 @@ -# 地图编辑器使用说明 - -## 地图编辑器 - -UI界面分为3个区域,左侧的编辑区,中间的画布区,右侧的素材区,以及两个弹窗形式的分别是事件编辑器和文本编辑器. - -画布区下方有切换地图和编辑器模式的下拉菜单,点击`保存地图`后画布的内容才会写入到文件中.同时一个显示信息的tips区. - -在素材区点击图块时,会选中该图块,此时tips会显示该图块的信息,编辑区会进入图块属性模式,怪物或物品可以直接在里面编辑数值.如果地图的数字和ID未被定义,可以在左侧定义,定义新图块需要刷新才能生效. - -在tips中有图块信息时,在画布上点击或拖拽可以把图块画上去,可以使用ctrl+Z撤销操作以及对应的ctrl+Y恢复撤销.擦除方块可以使用素材区最左上角的擦除块. - -点击界面中的空白,tips中的图块信息会被清空,此时再点击画布上的点,编辑器会进入地图选点模式.此时可以编辑改点的`events`,`afterBattle`,`changeFloor`等事件或者是`canMove`来改变各方向的通行状态. - -切换地图会使编辑区进入楼层属性模式,这里可以修改首次到达该楼层时会触发的事件`firstArrive`,楼层显示的名称,默认的前景背景图片,默认天气和色调,是否允许使用快捷商店等等.注:这里不允许编辑楼层的ID,需要修改ID的场合请直接改js文件,并保持注释中的三个标识符一致. - -全塔属性中编辑整个塔为单位的属性,例如起始剧情`startText`,塔的ID,提供哪些难度,主角的起始属性起始道具,全局商店,各种数值以及系统FLAG.创建新塔时需要认真编辑这里面的所有选项. - -脚本编辑模式可以修改常用的需要更改的函数.例如,给不同的难度设置不同的内容,加点,推箱子达成后的触发,以及修改游戏中的`关于`界面. - -追加素材模式可以导入一个图片到该标签的画板中,然后依次点击画板中的图块,点追加就可以按顺序把这些图片添加到对应的画布区素材的最下方,需要刷新来生效. - -地图编辑模式中可以导入来自地图生成器的地图数组,同时创建新楼层需要在这里通过另存为来实现,可以点清除地图把另存为出的新楼层清空. - -> 编辑区的表格可以直接修改,推荐通过双击,在事件编辑器和文本编辑器中进行编辑.编辑区中的修改需要点保存才会生效. - -## 事件编辑器 - -地图选点中的表格,以及楼层属性中的`firstArrive`和全塔属性的`startText`,在双击时会进入事件编辑器,是由[antlr-blockly](https://github.com/zhaouv/antlr-blockly)生成的图块式的可视化编辑器. - -把左侧的方块拖到面板中,下方就会实时的显示对应的js的代码(以及数值不正确时的提示). - -每个方块点击右键会展开一个菜单,点帮助可以跳转到此文档中对应的内容.利用好复制功能可以极大提高编辑的效率.注释选项请不要使用,编辑器并不会保留这里的注释. - -template中提供了一些模板事件,例如战前剧情,打怪开门. - -`显示文章`的两个方块,以及`自动剧情文本`,`选项`和`自定义JS脚本`这5个方块,可以通过双击方块,在文本编辑器中(以多行的方式)编辑其中的文字. - -## 文本编辑器 - -事件编辑器之外的内容双击后由文本编辑器来编辑,是有js高亮支持的多行文本编辑器[CodeMirror](https://github.com/codemirror/CodeMirror),点confirm即可使编辑的文本替换到表格中 - -## 拓展地图编辑器 - -> 面向有一定编程基础的用户 - -修改`project/`下的`*comment.js`可以让地图编辑器对自己添加的属性有更好的支持.例如: -+ 给`comment.js`中`enemys`加入新的键值对,就可以更方便的给怪物在UI界面中添加对应的值. -+ 在`data.comment.js`中把自己添加的内容标记为叶节点,不再在表格中展开到最末端. - -地图编辑器的部分API见`_server/README.md` \ No newline at end of file diff --git a/docs/element.md b/docs/element.md index d66b2c41..299c00a6 100644 --- a/docs/element.md +++ b/docs/element.md @@ -1,6 +1,6 @@ # 元件说明 -?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.0**,上次更新时间:* {docsify-updated} * 在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。 @@ -37,7 +37,7 @@ 怪物可以有特殊属性,每个怪物可以有多个自定义属性。 -怪物的特殊属性所对应的数字(special)在下面的`getSpecialText`中定义,请勿对已有的属性进行修改。 +怪物的特殊属性所对应的数字(special)在`libs/enemys.js`中的`getSpecialText`中定义,请勿对已有的属性进行修改。 ``` js enemys.prototype.getSpecialText = function (enemyId) { @@ -66,6 +66,8 @@ enemys.prototype.getSpecialText = function (enemyId) { if (this.hasSpecial(special, 19)) text.push("自爆"); if (this.hasSpecial(special, 20)) text.push("无敌"); if (this.hasSpecial(special, 21)) text.push("退化"); + if (this.hasSpecial(special, 22)) text.push("固伤"); + if (this.hasSpecial(special, 23)) text.push("重生"); return text.join(" "); } ``` @@ -125,6 +127,8 @@ N连击怪物的special是6,且我们可以为它定义n代表实际连击数 ![怪物退化](./img/tuihua.png) +固伤怪则需要在后面增加`damage`选项,代表战前扣血数值。 + 如有额外需求,可参见[自定义怪物属性](personalization#自定义自定义怪物属性),里面讲了如何设置一个新的怪物属性。 ## 路障,楼梯,传送门 @@ -153,10 +157,10 @@ floorId指定的是目标楼层的唯一标识符(ID)。 现在我们的H5魔塔支持播放动画,也支持天气系统了。 -要播放动画,你需要先使用“RM动画导出器”将动画导出,放在animates目录下,然后在main.js中定义。 +要播放动画,你需要先使用“RM动画导出器”将动画导出,放在animates目录下,然后再data.js中定义。 ``` js -this.animates = [// 在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名 +"animates": [// 在此存放所有可能使用的动画,必须是animate格式,在这里不写后缀名 // 动画必须放在animates目录下;文件名不能使用中文,不能带空格或特殊字符 "hand", "sword", "zone", "yongchang", "thunder" // 根据需求自行添加 ] @@ -164,8 +168,6 @@ this.animates = [// 在此存放所有可能使用的动画,必须是animate !> 动画必须是animate格式,名称不能使用中文,不能带空格或特殊字符。 -目前暂时不支持带旋转和翻转的帧。 - 导出动画时可能会进行一些压缩以节省流量,因此清晰度可能不如原版。 动画播放时,是按照每秒20帧的速度(即50ms/帧)。 @@ -192,13 +194,13 @@ this.animates = [// 在此存放所有可能使用的动画,必须是animate 要播放音乐和音效,你需要将对应的文件放在sounds目录下,然后在main.js中进行定义 ``` js -this.bgms = [ // 在此存放所有的bgm,和文件名一致。第一项为默认播放项 +"bgms": [ // 在此存放所有的bgm,和文件名一致。第一项为默认播放项 // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 - '058-Slow01.mid', 'bgm.mp3', 'qianjin.mid', 'star.mid' + 'bgm.mp3', 'qianjin.mid', 'star.mid', ]; -this.sounds = [ // 在此存放所有的SE,和文件名一致 +"sounds": [ // 在此存放所有的SE,和文件名一致 // 音频名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 - 'floor.mp3', 'attack.ogg', 'door.ogg', 'item.ogg' + 'floor.mp3', 'attack.ogg', 'door.ogg', 'item.ogg', 'zone.ogg' ] ``` @@ -245,7 +247,7 @@ this.sounds = [ // 在此存放所有的SE,和文件名一致 - **[ESC]** 打开/关闭系统菜单 - **[H]** 打开帮助页面 - **[Z]** 转向 -- **[R]** 回退 +- **[R]** 回放录像 - **[SPACE]** 轻按(仅在轻按开关打开时有效) - **[1]** 快捷使用破墙镐 - **[2]** 快捷使用炸弹/圣锤 diff --git a/docs/event.md b/docs/event.md index 2966278f..f661e1d3 100644 --- a/docs/event.md +++ b/docs/event.md @@ -1,6 +1,6 @@ # 事件 -?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.0**,上次更新时间:* {docsify-updated} * 本章内将对样板所支持的事件进行介绍。 @@ -20,6 +20,13 @@ 在事件列表中使用`type: show`和`type: hide`可以将一个禁用事件启用,或将一个启用事件给禁用。 +## 关于V2.0的重要说明 + +在V2.0版本中,所有事件均可以使用blockly来进行块的可视化编辑。 + +它能通过拖动、复制粘贴等方式帮助你快速生成事件列表,而不用手动打大量字符。 + +但是,仍然强烈建议要对每个事件的写法进行了解。 ## 自定义事件 @@ -615,13 +622,13 @@ loc可忽略,如果忽略则显示为事件当前点。 ``` js "x,y": [ // 实际执行的事件列表 - {"type": "showImage", "name": "bg", "loc": [231,297]}, // 在(231,297)显示bg.png - {"type": "showImage", "name": "1", "loc": [109,167]}, // 在(109,167)显示1.png + {"type": "showImage", "name": "bg.jpg", "loc": [231,297]}, // 在(231,297)显示bg.jpg + {"type": "showImage", "name": "1.png", "loc": [109,167]}, // 在(109,167)显示1.png {"type": "showImage"} // 如果不指定name则清除所有图片。 ] ``` -name为图片名。**请确保图片在main.js中的this.images中被定义过。** +name为图片名。**请确保图片在data.js中的images中被定义过。** loc为图片左上角坐标,以像素为单位进行计算。 @@ -769,10 +776,12 @@ move完毕后移动的NPC/怪物一定会消失,只不过可以通过immediate ### win: 获得胜利 -`{"type": "win", "reason": "xxx"}` 将会直接调用events.js中的win函数,并将reason作为参数传入。 +`{"type": "win", "reason": "xxx"}` 将会直接调用events.js中的win函数,并将reason作为结局传入。 该事件会显示获胜页面,并重新游戏。 +!> 如果`reason`不为空,则会以reason作为获胜的结局! + ### lose: 游戏失败 `{"type": "lose", "reason": "xxx"}` 将会直接调用`events.js`中的lose函数,并将reason作为参数传入。 @@ -1059,19 +1068,24 @@ core.insertAction(list) //往当前事件列表中插入一系列事件。使用 打败怪物后可以进行加点。 -如果要对某个怪物进行加点操作,则首先需要修改该怪物的点数值,即在怪物定义的后面添加`point`,代表怪物本身的加点数值。 +要启用加点,首先需要在`data.js`中将`enableAddPoint`置为true。 + +如果要对某个怪物进行加点操作,则首先需要修改该怪物的`point`数值,代表怪物本身的加点数值。 ``` js -... 'def': 0, 'money': 1, 'experience': 1, 'special': 0, 'point': 1}, // 在怪物后面添加point代表怪物的加点数 +... 'def': 0, 'money': 1, 'experience': 1, 'point': 1, 'special': 0}, // 在怪物后面添加point代表怪物的加点数 ``` -然后在`events.js`文件中找到`addPoint`函数。它将返回一个choices事件。修改此函数为我们需要的加点项即可。 +然后在`functions.js`文件中找到`addPoint`函数。它将返回一个choices事件。修改此函数为我们需要的加点项即可。 + +!> V2.0版本可以直接在“脚本编辑 - 加点事件”中双击进行修改! ``` js -////// 加点 ////// -events.prototype.addPoint = function (enemy) { - var point = enemy.point; // 获得该怪物的point - if (!core.isset(point) || point<=0) return []; +////// 加点事件 ////// +"addPoint" : function (enemy) { + // 加点事件 + var point = enemy.point; + if (!core.flags.enableAddPoint || !core.isset(point) || point<=0) return []; // 加点,返回一个choices事件 return [ @@ -1230,11 +1244,13 @@ events.prototype.addPoint = function (enemy) { 上面的afterBattle事件只对和怪物进行战斗后才有会被处理。 -如果我们想在使用炸弹后也能触发一些事件(如开门),则可以在`events.js`里面的`afterUseBomb`函数进行处理: +如果我们想在使用炸弹后也能触发一些事件(如开门),则可以在`functions.js`里面的`afterUseBomb`函数进行处理: + +!> V2.0版本可以直接在“脚本编辑 - 使用炸弹后的事件”中双击进行修改! ``` js ////// 使用炸弹/圣锤后的事件 ////// -events.prototype.afterUseBomb = function () { +"afterUseBomb": function () { // 这是一个使用炸弹也能开门的例子 if (core.status.floorId=='xxx' && core.terrainExists(x0,y0,'specialDoor') // 某个楼层,该机关门存在 && !core.enemyExists(x1,y1) && !core.enemyExists(x2,y2)) // 且守门的怪物都不存在 @@ -1262,11 +1278,11 @@ events.prototype.afterUseBomb = function () { !> 推箱子的前方不允许存在任何事件(花除外),包括已经禁用的自定义事件。 -推完箱子后将触发events.js中的afterPushBox事件,你可以在这里进行开门判断。 +推完箱子后将触发functions.js中的afterPushBox事件,你可以在这里进行开门判断。 ``` js ////// 推箱子后的事件 ////// -events.prototype.afterPushBox = function () { +"afterPushBox" = function () { var noBoxLeft = function () { // 地图上是否还存在未推到的箱子,如果不存在则返回true,存在则返回false @@ -1290,6 +1306,33 @@ events.prototype.afterPushBox = function () { } ``` +## 怪物数据的动态修改 + +有时候我们可能还需要在游戏过程中动态修改怪物数据,例如50层魔塔的封印魔王,或者根据难度分歧来调整最终Boss的属性数据。 + +而在我们的存档中,是不会对怪物数据进行存储的,只会存各个变量和Flag,因此我们需要在读档后根据变量或Flag来调整怪物数据。 + +我们可以在functions.js中的`afterLoadData`进行处理。 + +``` js +////// 读档事件后,载入事件前,可以执行的操作 ////// +"afterLoadData" : function(data) { + // 读档事件后,载入事件前,可以执行的操作 + if (core.hasFlag("fengyin")) { // 如果存在封印(flag为真) + core.material.enemys.blackKing.hp/=10; // 将怪物的血量变成原来的十分之一 + // ... + } + // 同样难度分歧可以类似写 if (core.getFlag('hard', 0)==3) {... +} + +// 在封印时,可以调用setValue将该flag置为真,然后调用自定义脚本 core.afterLoadData() 即可。 +"x,y": [ // 封印 + {"type": "setValue", "name": "flag:fengyin", "value": "true"}, + {"type": "function", "function": function() { + core.afterLoadData(); + }} +] +``` ## 战前剧情 @@ -1361,7 +1404,7 @@ events.prototype.afterPushBox = function () { ``` js ////// 不同难度分别设置初始属性 ////// -events.prototype.setInitData = function (hard) { +"setInitData": function (hard) { if (hard=='Easy') { // 简单难度 core.setFlag('hard', 1); // 可以用flag:hard来获得当前难度 // 可以在此设置一些初始福利,比如设置初始生命值可以调用: @@ -1386,7 +1429,7 @@ events.prototype.setInitData = function (hard) { ``` js ////// 游戏获胜事件 ////// -events.prototype.win = function(reason) { +"win": function(reason) { core.ui.closePanel(); var replaying = core.status.replay.replaying; core.stopReplay(); @@ -1396,19 +1439,21 @@ events.prototype.win = function(reason) { core.drawText([ "\t[恭喜通关]你的分数是${status:hp}。" ], function () { - core.events.gameOver('', replaying); + core.events.gameOver(reason||'', replaying); }) }); } ``` -其参数reason为获胜原因(即type:win事件里面的reason参数)。你可以在这里修改自己的获胜界面显示的文字。 +其参数reason为获胜原因(即type:win事件里面的reason参数)。 + +!> 如果reason不为空,则将会作为结局名! 当失败(`{"type": "lose"}`,或者被怪强制战斗打死、被领域怪扣血死、中毒导致扣血死,路障导致扣血死等等)事件发生时,将调用`events.js`中的`lose`事件。其直接显示一段文字,并重新开始游戏。 ``` js ////// 游戏失败事件 ////// -events.prototype.lose = function(reason) { +"lose": function(reason) { core.ui.closePanel(); var replaying = core.status.replay.replaying; core.stopReplay(); @@ -1424,26 +1469,6 @@ events.prototype.lose = function(reason) { 其参数reason为失败原因。你可以在这里修改失败界面时显示的文字。 -如果要设置多种不同的结局,只需要在win的传参中把`core.events.gameOver('', replaying);`的空字符串改成具体的结局名。 - -例如: - -``` js -events.prototype.win = function(reason) { // 传入参数"reason"为结局名 -// ... 上略 - ], function () { - core.events.gameOver(reason, replaying); // 使用reason作为结局名 - }) - }); -} - -// 然后在事件可以调用 -{"type": "win", "reason": "TRUE END"}, // TE结局 -{"type": "win", "reason": "NORMAL END"} // NE结局 -``` - -上面这个例子中,我们直接把reason作为结局名的参数传入gameOver函数,这样的话就可以直接在{"type": "win"}中加上"reason"代表具体的结局。 - ========================================================================================== [继续阅读下一章:个性化](personalization) diff --git a/docs/img/floordata.png b/docs/img/floordata.png index 64db97de1af7fc7011744b6e2979551c96780393..ed28b6285daf0f3762064a41c33637d083b43e3c 100644 GIT binary patch literal 5801 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 bCBGdqG12u}^!>3Z0DK|zj4u~nbPoM55eMq9 literal 32686 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 o!09FCe}5as{+z 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 G&A$Nj@dHW# literal 7226 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 diff --git a/docs/personalization.md b/docs/personalization.md index 288d9eeb..3e6fa458 100644 --- a/docs/personalization.md +++ b/docs/personalization.md @@ -1,18 +1,37 @@ # 个性化 -?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.0**,上次更新时间:* {docsify-updated} * 有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。 +## 图层的说明 + +HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们之间有一个覆盖关系,后面的图层将覆盖前面的图层。 + +所有图层从低往高依次如下: + +- bg:背景层;绘制地面素材,或者作为背景的图片素材 +- event:事件层;所有事件(道具、墙壁、NPC、怪物等)都绘制在这一层进行处理 +- hero:勇士层;主要用来绘制勇士 +- event2:事件2层;本层主要用来绘制48x32的图片素材的上半部分(避免和勇士错位),也可以用来绘制该层的前景图片素材 +- fg:显伤层;主要用来绘制怪物显伤和领域显伤 +- animate:动画层;主要用来绘制动画,图块的淡入/淡出效果,图块的移动。showImage事件绘制的图片也是在这一层。 +- weather:天气层;主要用来绘制天气(雨/雪) +- curtain:色调层;用来控制当前楼层的画面色调 +- ui:UI层;用来绘制一切UI窗口,如剧情文本、怪物手册、楼传器、系统菜单等等 +- data:数据层;用来绘制一些顶层的或更新比较快的数据,如左上角的提示,战斗界面中数据的变化等等。 + ## 自定义素材 所有素材的图片都在`images`目录下。 - `animates.png` 为所有动画效果。主要是星空熔岩,开门,毒网,传送门之类的效果。为四帧。 - `autotile.png` 为Autotile块。 -- `enemys.png` 为所有怪物的图片。其对应的数字,从上至下依次是会从201开始计算(即,绿色史莱姆为201,小蝙蝠为205,依次类推)。请注意,动画效果为两帧,一般是原始四帧中的1和3。(四帧中12相同,34相同,因此只取1和3即可) +- `enemys.png` 为所有怪物的图片。 +- `enemy48.png` 为所有48x32怪物的图片。 - `heros.png` 为勇士行走图。 - `items.png` 为所有道具的图标。 -- `npcs.png` 为所有NPC的图标,也是两帧。 +- `npcs.png` 为所有NPC的图标。 +- `npc48.png` 为所有48x32的NPC图标。 - `terrains.png` 为所有地形的图标。 系统会读取`icon.js`文件,并获取每个ID对应的图标所在的位置。 @@ -23,38 +42,38 @@ 如果你需要某个素材已经存在,则可以直接将其覆盖images目录下的同名文件,就能看到效果。 -### 使用自己的图片作为某层楼的背景素材 +### 使用自己的图片作为某层楼的背景/前景素材 由于HTML5功能(素材)有限,导致了对很多比较复杂的素材(比如房子内)等无法有着较好的绘图方式。 为了解决这个问题,我们允许用户自己放置一张或多张图片作为某一层的背景素材。 -要启用这个功能,我们首先需要在`main.js`中将可能的图片进行加载。 +要启用这个功能,我们首先需要在`data.js`中将可能的图片进行加载。 ``` js -this.images = [ // 在此存放所有可能使用的图片 +"images": [ // 在此存放所有可能使用的图片 // 图片可以被作为背景图(的一部分),也可以直接用自定义事件进行显示。 // 图片名不能使用中文,不能带空格或特殊字符;可以直接改名拼音就好 // 建议对于较大的图片,在网上使用在线的“图片压缩工具(http://compresspng.com/zh/)”来进行压缩,以节省流量 - "bg.jpg", // 依次向后添加 + "bg.jpg", "house.png", "bed.png"// 依次向后添加 ]; ``` -!> 请使用网上的一些[在线图片压缩工具](http://compresspng.com/zh/)对png图片进行压缩,以节省流量。一张500KB的png图片可以被压缩到20-30KB,显示效果不会有太大差异。 +!> 请使用网上的一些[在线图片压缩工具](http://compresspng.com/zh/)对图片进行压缩,以节省流量。 之后,我们可以在每层剧本的`"images"`里来定义该层的默认背景图片素材。 ``` js -"png": [[x,y,"bg.jpg"]], // 背景图;你可以选择一张或多张图片来作为背景素材。 -"png": [], // 无任何背景图 -"png": [[1,1,"house"], [6,7,"house2"]] // 在(1,1)放一个house.png,且(6,7)放house2.png +"images": [[x,y,"bg.jpg",false]], // 背景图;你可以选择一张或多张图片来作为背景/前景素材。 +"images": [], // 无任何背景图 +"images": [[1,1,"house.png",false], [6,7,"bed.png",true]] // 在(1,1)放一个house.png在背景层,且(6,7)放bed.png在前景层 ``` -png为一个数组,代表当前层所有作为背景素材的图片信息。 +images为一个数组,代表当前层所有作为背景素材的图片信息。 -每一项为一个三元组,分别为该背景素材的x,y和图片名。其中x和y分别为横纵坐标,在0-12之间;图片名则必须在上面的this.images中定义过。 +每一项为一个四元组,分别为该背景素材的x,y,图片名和是否为前景。其中x和y分别为横纵坐标,在0-12之间;图片名则必须在上面的images中定义过。 -你的图片背景素材将会覆盖原来本身的背景层。 +如果第四项为true,则会在前景层(event2)上绘制,能覆盖勇士,常常用来作为柱子的上半部分等情况。 **如果你需要让某些点不可通行(比如你建了个房子,墙壁和家具等位置不让通行),则需在`events`中指定`{"noPass": false}`,参见[自定义事件](event#自定义事件)的写法。 @@ -82,6 +101,8 @@ png为一个数组,代表当前层所有作为背景素材的图片信息。 这是因为,该素材没有被定义,无法被游戏所识别。 +!> 在V2.0中,我们可以简单的在地图编辑器中新增素材的ID和数字,但是仍然**强烈建议**对素材的机制进行了解。 + #### 素材的机制 本塔所有的素材都拥有三个属性:**ID**,**索引**,**数字**。 @@ -91,7 +112,7 @@ png为一个数组,代表当前层所有作为背景素材的图片信息。 **`ID-索引` 对应关系定义在icons.js文件中。该文件将唯一确定一个ID在图片上所在的位置。** -**`ID-数字` 对应关系定义在maps.js文件的getBlock函数中。该函数将唯一确定一个ID对应的数字是多少。** +**`ID-数字` 对应关系定义在maps.js文件中。该函数将唯一确定一个ID对应的数字是多少。** 如果需要添加一个素材到游戏,则必须为其分配一个唯一标识符,并同时修改`icons.js`和`maps.js`两个文件。 @@ -106,7 +127,7 @@ png为一个数组,代表当前层所有作为背景素材的图片信息。 3. 修改对应楼层的剧本文件的`defaultGround`项,改成新的ID。 **如果你要在游戏内使用本地形,则操作如下:** -3. 指定一个数字,在maps.js的getBlock函数下类似进行添加。 +3. 指定一个数字,在maps.js中类似进行添加。 #### 新添加Autotile @@ -114,24 +135,26 @@ png为一个数组,代表当前层所有作为背景素材的图片信息。 1. 将新的Autotile图片复制到images目录下。 2. 进入icons.js,在autotile分类下进行添加该文件的名称,索引简单的写0。 -3. 指定一个数字,在maps.js的getBlock函数下类似进行添加。 +3. 指定一个数字,在maps.js中类似进行添加。 !> Autotile的ID和文件名完全相同!且其ID/文件名不能含有中文、空格或特殊字符。 +!> V2.0版本不能在地图编辑器中添加Autotile,请按上面的操作来执行。 + #### 新添加道具 如果你需要新增一个未被定义的道具: 1. 指定一个唯一的英文ID,不能和现有的重复。 2. 进入icons.js,在items分类下进行添加索引(对应图标在图片上的位置,即index) -3. 指定一个数字,在maps.js的getBlock下类似进行添加。 +3. 指定一个数字,在maps.js中类似进行添加。 4. 在items.js中仿照其他道具,来添加道具的信息。 有关如何自行实现一个道具的效果,参见[自定义道具效果](#自定义道具效果)。 #### 新添加怪物 -如果我们需要新添加怪物,请在enemys.png中新增一行,然后复制粘贴上四帧怪物图的**1和3帧**。 +如果我们需要新添加怪物,请在enemys.png中新增一行。 你可以通过便捷PS工具的“更改色相”来将红头怪变成橙头怪等。 @@ -139,9 +162,11 @@ png为一个数组,代表当前层所有作为背景素材的图片信息。 1. 指定一个唯一的英文ID,不能和enemys中现有的重复。 2. 进入icons.js,在enemys分类下进行添加索引(对应图标在图片上的位置,即index) -3. 在maps.js的getBlock下继续进行添加。请注意其ID为200开始的顺序,即如果新增一行为261,依次类推 +3. 在maps.js中继续进行添加。 4. 在enemys.js中仿照其他怪物,来添加怪物的信息。 +!> 如果是48x32的怪物素材,请放在enemy48.png中,然后在icons.js的enemy48下添加索引。 + 有关如何自行实现一个怪物的特殊属性或伤害计算公式,参见[怪物的特殊属性](#怪物的特殊属性)。 #### 新添加NPC @@ -150,6 +175,8 @@ png为一个数组,代表当前层所有作为背景素材的图片信息。 2. 进入icons.js,在npcs分类下进行添加索引(对应图标在图片上的位置,即index) 3. 指定一个数字,在maps.js的getBlock下类似进行添加。 +!> 如果是48x32的怪物素材,请放在npc48.png中,然后在icons.js的npc48下添加索引。 + ### 地图生成器使用自定义素材 地图生成器是直接从js文件中读取数字-图标对应关系的。 @@ -166,30 +193,24 @@ png为一个数组,代表当前层所有作为背景素材的图片信息。 对于即捡即用类道具,如宝石、血瓶、剑盾等,我们可以简单地修改`data.js`中的value一栏即可。 -如果你有更高级的需求(例如每个区域的效果不同),则需要编辑`items.js`文件。具体方式是: +如果你想要同种宝石在不同层效果不同的话,可以进行如下操作: + +1. 在楼层的item_ratio中定义宝石的比率(比如1-10的写1,11-20层写2等) +2. 修改获得道具的itemEffect函数(在items.js中的itemEffect中编辑,V2.0中也可以使用编辑器) -1. 找到`getItemEffect`函数;所有即捡即用类道具的效果都在这里实现。 -2. 算道具效果系数,或应该增加的值。 ``` js -items.prototype.getItemEffect = function(itemId, itemNum) { - var itemCls = core.material.items[itemId].cls; - // 消耗品 - if (itemCls === 'items') { - var floor = parseInt(core.status.thisMap.name); // 获得当前楼层。此name和剧本中的name完全一致。 - var ratio = 1; // 道具效果系数 - if (floor>=11 && floor<=20 ) ratio = 2; // 11-20F(二区),道具效果翻倍 - if (floor>=21 && floor<=30 ) ratio = 3; // 21-30F(二区),道具效果三倍 - // ... 根据自己的需要来写 - - if (itemId === 'redJewel') core.status.hero.atk += core.values.redJewel * ratio; // 将初始效果乘以倍数 - if (itemId === 'blueJewel') core.status.hero.def += core.values.blueJewel * ratio; // 将初始效果乘以倍数 - if (itemId === 'greenJewel') core.status.hero.mdef += core.values.greenJewel * ratio; // 将初始效果乘以倍数 - if (itemId == 'yellowJewel') { // 黄宝石属性:需自己定义 -// ... 下略 +// ratio为楼层的item_ratio值,可以进行翻倍宝石属性 +core.status.hero.atk += core.values.redJewel * ratio ``` -3. 修改同样修改下面的`getItemEffectTip`函数,使提示文字相应变动。 -!> **请注意这里`core.status.thisMap.name`获取的是当前层中,你在剧本文件里写的name那一项(即状态栏中的层数显示)。然后可以通过几个简单的if来判断应该增加的值。** +这里我们可以直接写ratio来取用该楼层中定义的`item_ratio`的值。 + +如果不是倍数增加(比如线性增加)也可以类似来写 + +``` js +// 一个二倍线性增加的例子 +core.status.hero.atk += core.values.redJewel + 2*ratio +``` ### 消耗类道具(cls: tools);永久类道具(cls: constants) @@ -212,12 +233,10 @@ events.prototype.passNet = function (data) { ### 实战!拿到神圣盾后免疫吸血、领域、夹击效果 -1. 在getItemEffect中修改拿到神圣盾时的效果,标记一个自定义Flag。 +1. 在itemEffect中修改拿到神圣盾时的效果,标记一个自定义Flag。 ``` js -if (itemId === 'shield5') { - core.status.hero.def += core.values.shield5; - core.setFlag("shield5", true); // 增加一个自定义Flag:已经拿到神圣盾 -} +core.status.hero.def += core.values.shield5 * ratio; +core.setFlag("shield5", true); // 增加一个自定义Flag:已经拿到神圣盾 ``` 2. 免疫吸血效果:在`enemys.js`的伤害计算中,编辑成如果存在神圣盾标记,吸血伤害为0。 ``` js @@ -239,10 +258,10 @@ enemys.prototype.calDamage = function (monster, hero_hp, hero_atk, hero_def, her } // ... 下略 ``` -3. 免疫领域、夹击、阻击效果:在`core.js`中,找到checkBlock函数,并编辑成如果有神圣盾标记,则将伤害变成0。 +3. 免疫领域、夹击、阻击效果:在`control.js`中,找到checkBlock函数,并编辑成如果有神圣盾标记,则将伤害变成0。 ``` js // 检查领域、夹击、阻击事件 -core.prototype.checkBlock = function () { +control.prototype.checkBlock = function () { var x=core.getHeroLoc('x'), y=core.getHeroLoc('y'); var damage = core.status.checkBlock.damage[13*x+y]; if (damage>0) { @@ -269,9 +288,9 @@ core.prototype.checkBlock = function () { 如果要修改伤害计算公式,请修改下面的calDamage函数。请注意,如果无法战斗,该函数必须返回`999999999`。 -对于毒衰弱怪物的战斗后结算在`events.js`中的afterBattle函数中。 +对于毒衰弱怪物的战斗后结算在`functions.js`中的afterBattle函数中。 -对于领域、夹击、阻击怪物的检查在`events.js`中的checkBlock函数中。 +对于领域、夹击、阻击怪物的检查在`control.js`中的checkBlock函数中。 `getCritical`, `getCriticalDamage`和`getDefDamage`三个函数依次计算的是该怪物的临界值、临界减伤和1防减伤。也可以适当进行修改。 diff --git a/docs/start.md b/docs/start.md index c9a838c0..07dddcde 100644 --- a/docs/start.md +++ b/docs/start.md @@ -1,6 +1,6 @@ # 快速上手 -?> 目前版本**v1.4.1**,上次更新时间:* {docsify-updated} * +?> 目前版本**v2.0**,上次更新时间:* {docsify-updated} * 在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔! @@ -12,9 +12,18 @@ - Chrome浏览器。其他浏览器可能会导致本地服务器产生闪退等现象。 - 一个很好的文本编辑器。推荐带有高亮染色、错误提示等效果。例如:WebStorm,VSCode,或者至少也要Sublime Text。 - ([VSCode下载地址](https://code.visualstudio.com/),群里的群文件中也有,强烈推荐之。) + - **2.0版本可以不需要,但是仍然强烈推荐有一个,从而能对H5造塔有更深的了解。** 只要满足了上述条件,你就可以开始做自己的塔啦! +## V2.0的使用 + +目前版本已经更新到V2.0,在2.0版本中,我们可以进行全GUI造塔。 + +下面的文档主要是讲如何通过代码编辑的方式来造,仍然强烈建议进行阅读从而有着一定的了解。 + +如果想直接知道如何在V2.0造塔,可以直接参见[V2.0版本介绍](V2.0)的说明,或者看[B站视频教程](http://www.bilibili.com/video/av17608025/)。 + ## 启动HTTP服务 在根目录下有一个“启动服务.exe”,运行之。 @@ -25,6 +34,7 @@ * “地图编辑器”允许你以可视化的方式进行编辑地图。 * “便捷PS工具”能让你很方便的对自定义素材进行添加。参见[自定义素材](personalization#自定义素材)。 * “地图生成器”能让你从已有的截图(如RMXP项目)中立刻生成可被本样板识别的地图数据。 +* “RM动画导出器”能让你从RMXP中导出动画而被H5魔塔使用。 * “JS代码压缩工具”能对JS代码进行压缩,从而减少IO请求数和文件大小。 * “伤害和临界值计算器”是一个很便捷的小工具,能对怪物的伤害和临界值进行计算。 @@ -34,7 +44,7 @@ 类似于RMXP,本塔每层楼都是一个“剧本”,剧本内主要定义了本层的地图和各种事件。主函数将读取每个剧本,并生成实际的地图供游戏使用。 -我们打开 `libs/floors/` 目录,这个目录是所有剧本的目录。我们需要指定一个楼层名,例如MT1;然后,我们可以将`MT0.js`(模板)复制重命名为为`MT1.js`,并使用文本编辑器打开。 +我们打开 `project/floors/` 目录,这个目录是所有剧本的目录。我们需要指定一个楼层名,例如MT1;然后,我们可以将`MT0.js`(模板)复制重命名为为`MT1.js`,并使用文本编辑器打开。 ![新建剧本](./img/script.png) @@ -43,11 +53,14 @@ 具体样板文件的每个要素如下: - **`floorId`** 楼层唯一标识符;必须和文件名,以及 `main.floors.xxx` 完全一致 - **`title`** 楼层中文名,将在切换楼层时进行显示 +- **`name`** 楼层再状态栏显示的名称 - **`canFlyTo`** 当前楼层可否被楼传器飞到。如果该层不能飞到,则也在该层也不允许使用楼传器。 - **`canUseQuickShop`** 当前楼层可否使用快捷商店。 -- **`defaultGround`** 该层的背景(地面)素材。需要是在`icon.js`里`terrains`中定义的一个ID,如`ground`, `grass2`等等。 -- **`color`** 该层的画面色调。本项可选,如果不写则色调为默认值(无色调),否则是一个RGBA数组,比如`[255,0,0,0.3]`等。 +- **`defaultGround`** 该层的背景(地面)素材。 +- **`images`** 该层默认显示的前景/背景图片 +- **`color`** 该层的画面色调。 - **`bgm`** 到达该层后默认播放的BGM。本项可忽略。 +- **`item_ratio`** 该层的宝石/血瓶倍率 - **`map`** 本层地图,需要是13x13数组,建议使用地图生成器或者可视化地图编辑器制作。 - **`firstArrive`** 第一次到该楼层触发的事件 - **`events`** 该楼的所有可能事件列表 @@ -55,6 +68,7 @@ - **`afterBattle`** 战斗后可能触发的事件列表 - **`afterGetItem`** 获得道具后可能触发的事件列表 - **`afterOpenDoor`** 开完门后可能触发的事件列表 +- **`cannotMove`** 每个图块不可通行的方向,也就是悬崖效果 我们最终的任务其实是,将每个楼层的剧本(地图&事件)给写完即可。 @@ -72,12 +86,14 @@ 然后可以在上面任意进行绘制地图。 -!> **如果地图的数字和ID未被定义,则会进行提示:数字和ID未被定义!此时可能需要手动在icons.js和maps.js中定义对应的数字和ID。请参见[自定义素材](personalization#自定义素材)。** +!> **如果地图的数字和ID未被定义,则会进行提示:数字和ID未被定义!此时要对素材的ID和数字进行定义,请参见[自定义素材](personalization#自定义素材)。** 绘制地图完毕后,点击"导出地图",即可在左边看到对应的JSON数组,并且已经复制到了剪切板。将其粘贴到剧本中的map位置即可。 ![地图数组](./img/maparray.png) +!> V2.0版本可以直接将当前地图进行保存或另存为,不需要这样手动打开进行编辑。 + ### 从RMXP导入已有的地图 如果我们想复刻一个现有的,已经被RMXP所制作的塔,也有很便捷的方式,那就是用到我们的“地图生成器”。 @@ -117,6 +133,8 @@ 我们打开`data.js`文件,这里面定义了各种全局属性和勇士初始值。 +!> V2.0版本可以直接在地图编辑器的`全塔属性`中进行修改! + 我们可以将本塔标题改名为“1层小塔”, 游戏的唯一标识符叫onefloor,然后可以直接修改勇士的各项初始数据. @@ -139,12 +157,12 @@ 其他的几项暂时不会被涉及到,因此不用考虑。 -全局变量修改完毕后,我们需要告诉主函数加载该楼层。打开`main.js`(该文件和index.html同级),找到`this.floorIds`项,将其值改为楼层ID即MT1。 - -![修改楼层数据](./img/floordata.png) +全局变量修改完毕后,我们需要告诉主函数加载该楼层。打开`data.js`,找到`floorIds`项,将其值改为楼层ID即MT1。 最后一步就是录入怪物数据。打开`enemys.js`文件,依次输入你在本塔内使用到的所有怪物的攻防血的数据。其中怪物的特殊属性(special项)与该文件下面的getSpecialText对应。 +!> V2.0版本可以直接在“图块属性”一栏进行修改怪物属性! + ![怪物数据](./img/enemyarray.png) 只需要修改自己用到的怪物属性即可,其他没有用到的怪物完全无所谓。 @@ -177,7 +195,7 @@ 1. 截图请务必刚好截取13x13的图片,并需要保证每个位置必须为32x32像素。一般无放缩的RMXP符合条件。 2. 游戏的唯一标识符name请务必修改。如果不修改可能会导致存档出现异常。 -3. 别忘了main.js中要修改floorIds指明所用到的所有楼层哦~ +3. 别忘了data.js中要修改floorIds指明所用到的所有楼层哦~ 下面是几个常见的FAQ: diff --git a/project/floors/MT0.js b/project/floors/MT0.js index dc4996fe..03a7db4b 100644 --- a/project/floors/MT0.js +++ b/project/floors/MT0.js @@ -9,7 +9,7 @@ main.floors.MT0 = "canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器) "canUseQuickShop": true, // 该层是否允许使用快捷商店 "defaultGround": "ground", // 默认地面的图块ID(terrains中) - "png": [], // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。 + "images": [], // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。 // "color": [0,0,0,0.3], // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。 // "weather": ["snow",5], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪,第二项为1-10之间的数代表强度。 // "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。 diff --git a/project/floors/sample0.js b/project/floors/sample0.js index 63495eb3..804dee94 100644 --- a/project/floors/sample0.js +++ b/project/floors/sample0.js @@ -9,7 +9,7 @@ main.floors.sample0 = "canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器) "canUseQuickShop": true, // 该层是否允许使用快捷商店 "defaultGround": "ground", // 默认地面的图块ID(terrains中) - "png": [], // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。 + "images": [], // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。 // "color": [0,0,0,0.3] // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。 // "weather": ["snow",5], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪,第二项为1-10之间的数代表强度。 "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。 diff --git a/project/floors/sample1.js b/project/floors/sample1.js index 04775340..669d67b1 100644 --- a/project/floors/sample1.js +++ b/project/floors/sample1.js @@ -9,7 +9,7 @@ main.floors.sample1 = "canFlyTo": true, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器) "canUseQuickShop": true, // 该层是否允许使用快捷商店 "defaultGround": "grass", // 默认地面的图块ID(terrains中) - "images": [[0,0,"bg.jpg",false]], // // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。 + "images": [[0,0,"bg.jpg",false]], // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。 // "color": [0,0,0,0.3] // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。 "weather": ["snow",6], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪,第二项为1-10之间的数代表强度。 // "bgm": "bgm.mp3", // 到达该层后默认播放的BGM。本项可忽略。 diff --git a/project/floors/sample2.js b/project/floors/sample2.js index 233473a0..6f6e5f7b 100644 --- a/project/floors/sample2.js +++ b/project/floors/sample2.js @@ -9,7 +9,7 @@ main.floors.sample2 = "canFlyTo": false, // 该楼能否被楼传器飞到(不能的话在该楼也不允许使用楼传器) "canUseQuickShop": true, // 该层是否允许使用快捷商店 "defaultGround": "snowGround", // 默认地面的图块ID(terrains中) - "png": [], // // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。 + "images": [], // // 该层默认显示的所有图片;详细用法请查看文档“自定义素材”中的说明。 "color": [255,0,0,0.3], // 该层的默认画面色调。本项可不写(代表无色调),如果写需要是一个RGBA数组。 "weather": ["rain",10], // 该层的默认天气。本项可忽略表示晴天,如果写则第一项为"rain"或"snow"代表雨雪,第二项为1-10之间的数代表强度。 "bgm": "qianjin.mid", // 到达该层后默认播放的BGM。本项可忽略。