diff --git a/_docs/_sidebar.md b/_docs/_sidebar.md index f7c5a0a1..914ee883 100644 --- a/_docs/_sidebar.md +++ b/_docs/_sidebar.md @@ -3,4 +3,5 @@ - [元件说明](element) - [事件](event) - [个性化](personalization) -- [脚本](api) +- [脚本](script) +- [附录:API列表](api) diff --git a/_docs/api.md b/_docs/api.md index 4783aaaa..346f4bd6 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -1,268 +1,14 @@ -# 脚本 +# 附录:API列表 ?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} * -在V2.6版本中,基本对整个项目代码进行了重写,更加方便造塔者的使用和复写函数。 - -## 控制台的使用 - -在Chrome浏览器中,按(Ctrl+Shift+I)可打开控制台。 - -![](img/console.jpg) - -控制台中有很多的标签,最常用的是`Console`, `Sources`和`Elements`。 - -有关更详尽的控制台使用可自行搜索[Chrome开发者工具](https://www.baidu.com/s?wd=chrome%20%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7)了解更多。 - -### Console:命令行 - -Console页为命令行。可以在这里输入一些命令进行调试。 - -比如,进入游戏后,输入`core.status.hero.atk`即可获得勇士的当前攻击力数值。`core.status.hero.atk=100`可以设置攻击力为100。 - -更多的API可参见[附录:API列表](#附录:API列表)。 - -除此以外,游戏中的报错等信息也是可以在Console中进行查看的。 - -![](img/console1.jpg) - -### Sources:断点调试 - -Sources页可以查看JS源代码,并进行断点调试等。 - -例如,如果相对脚本编辑中的伤害计算函数进行断点调试: -1. 在左边找到`project/functions.js`,单击打开文件 -2. 并找到对应的行(可以Ctrl+F搜索),比如搜索`getDamageInfo` -3. 在行号上点一下打断点,会出现一个蓝色标签 - -之后,当代码运行到你的断点处时,将自动停止运行。 - -![](img/sources.jpg) - -可以将鼠标移动到变量上,将弹窗形式显示这个变量的各项数值,从而查看变量值是否符合预期。 - -图中红色框内有几个按钮,从左到右分别是:**继续执行**,**执行到下一行**,**进入当前函数**,**跳出当前函数**,**单步执行**。 - -通过这几个按钮,可以一行一行的对代码进行执行,执行过程中能不断查看各个变量的数值变化,从而定位问题所在。 - -红圈下方是Call Stack,即当前的函数调用链(从哪些地方调用过来的)。 - -Sources还有更多有趣的功能,在此不做介绍,有兴趣的可自行网上搜索了解。 - -### Elements:网页元素查看 - -Elements页可以查看网页的源代码,调整css布局等。 - -![](img/elements.jpg) - -不过对魔塔样板来说,最重要的是红圈中的按钮。点击此按钮可以进入**手机模式**。 - -手机模式下,左边可以对屏幕分辨率进行调整和模拟。 - -这可以很有效的帮我们进行测试样板在手机端的表现。 - -## 整体项目架构 - -``` text -├── /_server/ # 为可视化地图编辑器提供一些支持的目录 -├── /libs/ # ---- 系统库目录 ---- -│ ├─ /thirdparty/ # 游戏所用到的第三方库文件 -│ ├─ actions.js # 用户交互处理 -│ ├─ core.js # 系统核心文件(游戏入口,接口&转发) -│ ├─ control.js # 游戏逻辑控制 -│ ├─ data.js # 全塔属性等 -│ ├─ enemys.js # 怪物相关处理 -│ ├─ events.js # 各个事件的执行 -│ ├─ icons.js # 图标和素材 -│ ├─ items.js # 道具效果 -│ ├─ loader.js # 各个资源加载 -│ ├─ maps.js # 地图数据和绘制 -│ ├─ ui.js # UI窗口绘制 -│ └─ utils.js # 工具类函数 -├── /project/ # ---- 项目目录 ---- -│ ├─ /animates/ # 动画目录 -│ ├─ /floors/ # 楼层文件 -│ ├─ /images/ # 图片素材 -│ ├─ /sounds/ # bgm和音效 -│ ├─ data.js # 全塔属性 -│ ├─ enemys.js # 怪物属性 -│ ├─ events.js # 公共事件 -│ ├─ functions.js # 脚本编辑 -│ ├─ icons.js # 素材和ID的对应关系定义 -│ ├─ items.js # 道具的定义和效果 -│ ├─ maps.js # 地图和数字的对应关系 -│ └─ plugins.js # 自定义插件 -├── /常用工具/ # 辅助造塔的小工具 -├── editor.html # 地图编辑器 -├── editor-mobile.html # 手机版的地图编辑器 -├── index.html # 主程序,游戏的入口 -├── main.js # JS程序的入口,将动态对所需JS进行加载 -├── style.css # 游戏所需要用到的样式表 -└── 启动服务.exe # 一个本地的HTTP服务器,通过它来运行游戏 -``` - -`_server`为**地图编辑器目录**,里面存放了地图编辑器相关的各项内容。 - -`libs`为**系统库目录**,里面存放了各个系统核心函数。 - -从V2.6开始,请勿直接修改libs下的代码,如有需要修改系统库函数请尝试在插件中[复写函数](#复写函数)。 - -`project`为**项目目录**,你所造的塔的数据全部存放在project下。在不同样板之间接档也是直接迁移project目录即可。 - -## 函数的转发 - -在本样板中,`core.js`里面基本是没有定义什么函数的,所有的游戏内函数都在其他几个文件中实现。 - -例如,常见的获得某个变量值`getFlag`是定义在`control.js`中的: - -```js -////// 获得某个自定义变量或flag ////// -control.prototype.getFlag = function(name, defaultValue) { - if (!core.status.hero) return defaultValue; - var value = core.status.hero.flags[name]; - return value != null ? value : defaultValue; -} -``` - -也就是,我们可以通过`core.control.getFlag(name, value)`来调用此函数。 - -但是这样会十分不便,我们希望能直接调用`core.getFlag(name, value)`,而不需要中间的control。 - -为了达到这个目的,样板设置了**函数转发**,即**将其他文件中定义的函数,转发到core中执行**。 - -上述`getFlag`代码的转发实际上是增加了如下函数: - -```js -////// getFlag函数的转发 ////// -core.getFlag = function (name, defaultValue) { - return core.control.getFlag(name, defaultValue); -} -// 转发后,即可通过 core.getFlag() 来实际调用 core.control.getFlag() -``` - -转发是自动完成的,其满足如下两条规则: -- **在libs中其他文件定义的函数,如果不以下划线`_`开头,就会进行转发。** -- **如果core中已经存在同名函数,则会在控制台中打出一条报错信息,并不转发该函数。** - -具体函数的转发实现代码可参见`core.js`的`_forwardFunc`函数。 - -!> 除此以外,插件中以`this.xxx`来定义的函数也会被转发! - -例如,你可以直接调用`core.drawLight()`来实际调用插件中的`core.plugin.drawLight`。 - -## 复写函数 - -样板的功能毕竟是写死的,有时候我们也需要修改样板的一些行为。 - -在V2.6以前,需要直接打开libs目录下的对应文件并进行修改。但是开libs下的文件就会出现各种问题: -- 不容易随着新样板来接档迁移 -- 也不好找到自己改过什么,从而能整理成新的插件在别的塔使用 -- …… - -好消息的是,从V2.6开始,我们再也不需要开文件了,而是可以直接在插件中对原始函数进行复写。 - -如果我想对xxx文件中的yyy函数进行重写,其模式一般是:`core.xxx.yyy = function (参数列表) { ... }` - -下面是几个例子,从简单到复杂。 - -### 重写怪物手册的背景图绘制,使用winskin而不是默认的黑色 - -直接重写怪物手册的背景图绘制,使用`core.drawBackground`来用winskin绘制一个背景图。 - -```js -// 重写ui.js中的_drawBook_drawBackground函数 -core.ui._drawBook_drawBackground = function () { - // core.__PIXEL__为定义的一个宏,对于13x13的值是416,对于15x15的值是480 - core.drawBackground(0, 0, core.__PIXEL__, core.__PIXEL__); -} -``` - -### 重写点击楼传事件 - -重写点击楼传事件,使得点击楼传按钮时能使用一个道具(比如item:fly)。 - -```js -// 重写events.js的useFly函数,即点击楼传按钮时的事件 -core.events.useFly = function (fromUserAction) { - if (core.isMoving()) { - core.drawTip("请先停止勇士行动"); - return; - } - if (core.status.lockControl || core.status.event.id != null) return; - - if (core.canUseItem('fly')) core.useItem('fly'); - else core.drawTip("当前无法使用"+core.material.items.fly.name); -} -``` - -其他的几个按钮,如快捷商店`openQuickShop`,虚拟键盘`openKeyBoard`的重写也几乎完全一样。 - -### 楼层切换时根据flag来播放不同的音效 - -整体复制并重写整个楼传切换前的函数,将`core.playSound('floor.mp3')`替换成根据flag来判定。 - -```js -// 复制重写events.js中的_changeFloor_beforeChange,修改音效 -core.events._changeFloor_beforeChange = function (info, callback) { - // 直接替换原始函数中的 core.playSound('floor.mp3'); - if (core.getFlag("floorSound") == 0) core.playSound('floor0.mp3'); - if (core.getFlag("floorSound") == 1) core.playSound('floor1.mp3'); - if (core.getFlag("floorSound") == 2) core.playSound('floor2.mp3'); - // ... - - // 下面是原始函数中的剩余代码,保持不变 - window.setTimeout(function () { - if (info.time == 0) - core.events._changeFloor_changing(info, callback); - else - core.showWithAnimate(core.dom.floorMsgGroup, info.time / 2, function () { - core.events._changeFloor_changing(info, callback); - }); - }, 25) -} -``` - -### 每次打开全局商店时播放一个音效 - -打开全局商店是在`events.js`中的`openShop`函数,因此需要对其进行重写。 - -然而,我们只需要在这个函数执行之前插一句音效播放,所以并不需要重写整个函数,而是直接插入一行就行。 - -```js -var openShop = core.events.openShop; // 先把原始函数用一个变量记录下来 -core.events.openShop = function (shopId, needVisited) { - core.playSound("shop.mp3"); // 播放一个音效 - return openShop(shopId, needVisited); // 直接调用原始函数 -} -``` - -### 每次绘制地图前在控制台打出一条信息 - -绘制地图在`maps.js`的`drawMap`函数,因此需要对其进行重写。 - -由于只需要额外在函数执行前增加一句控制台输出,所以直接插入一行即可。 - -但是需要注意的是,`drawMap`中使用了`this._drawMap_drawAll()`,因此使用函数时需要用`call`或者`apply`来告知this是什么。 - -```js -var drawMap = core.maps.drawMap; // 先把原始函数用一个变量记录下来 -core.maps.drawMap = function (floorId, callback) { - console.log("drawMap..."); // 控制台打出一条信息 - drawMap.call(core.maps, floorId, callback); // 需要使用`call`来告知this是core.maps -} -``` - -详见[call和apply的用法](https://www.jianshu.com/p/80ea0d1c04f8)。 - -## 附录:API列表 - 这里将列出所有被转发到core的API,没有被转发的函数此处不会列出,请自行在代码中查看。 本附录量较大,如有什么需求请自行Ctrl+F进行搜索。 如有任何疑问,请联系小艾寻求帮助。 -### core.js +## core.js core.js中只有很少的几个函数,主要是游戏开始前的初始化等。 @@ -421,7 +167,7 @@ core.doFunc(func, _this) 此函数剩余参数将作为参数被传入func。 ``` -### actions.js +## actions.js actions.js主要是处理一些和用户交互相关的内容。 @@ -513,7 +259,7 @@ core.longClick() 如果全部返回false则将停止本次长按行为,直到手指离开屏幕并重新进行长按为止。 ``` -### control.js +## control.js control.js将负责整个游戏的核心控制系统,分为如下几个部分: - requestAnimationFrame相关 @@ -947,7 +693,7 @@ core.resize() 此函数将根据当前的屏幕分辨率信息,生成一个obj,并传入各个注册好的resize函数中执行。 ``` -### enemys.js +## enemys.js enemys.js中定义了一系列和怪物相关的API函数。 @@ -1033,7 +779,7 @@ core.hasEnemyLeft(floorId) 检查某个楼层是否还有剩余的怪物。等价于 core.getCurrentEnemys(floorId).length > 0 ``` -### events.js +## events.js events.js将处理所有和事件相关的操作,主要分为五个部分: - 游戏的开始和结束 @@ -1370,7 +1116,7 @@ core.afterUseBomb() 使用炸弹或圣锤后的事件。实际被转发到了脚本编辑中。 ``` -### icons.js +## icons.js icons.js主要是负责素材相关信息,比如某个素材在对应的图片上的位置。 @@ -1384,7 +1130,7 @@ core.getTilesetOffset(id) 如果该素材不是tileset,则返回null。 ``` -### items.js +## items.js items.js主要负责一切和道具相关的内容。 @@ -1474,7 +1220,7 @@ core.quickLoadEquip() 读取当前套装。index为读取的套装编号。 ``` -### loader.js +## loader.js loader.js主要负责资源加载相关的内容。 @@ -1509,7 +1255,7 @@ core.freeBgm(name) 释放一个bgm的内存并移出缓存列表。如果该bgm正在播放则也会立刻停止。 ``` -### map.js +## map.js maps.js负责一切和地图相关的处理内容,包括如下几个方面: - 地图的初始化,保存和读取,地图数组的生成 @@ -1842,7 +1588,7 @@ core.stopAnimate(id, doCallback) 如果doCallback为真,则会执行该动画所对应的回调函数。 ``` -### ui.js +## ui.js ui.js负责一切UI界面的绘制。主要包括三个部分: - 设置某个画布的属性的相关API @@ -2104,7 +1850,7 @@ core.ui.deleteAllCanvas() 删除所有的自定义画布。 ``` -### utils.js +## utils.js utils.js是一个工具函数库,里面有各个样板中使用到的工具函数。 diff --git a/_docs/element.md b/_docs/element.md index 6f4551d3..4fed9b92 100644 --- a/_docs/element.md +++ b/_docs/element.md @@ -85,7 +85,7 @@ percentage为该装备是否按比例增加属性。 使用`core.getEquip(equipType)`来获得某个装备类型的当前装备。 -更多相关API详见[附录:API列表](api#附录:API列表)。 +更多相关API详见[附录:API列表](api)。 ### 多重装备 diff --git a/_docs/event.md b/_docs/event.md index fbd0b094..9fd851a4 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -1746,11 +1746,11 @@ icon是可选的,如果设置则会在选项前绘制图标,其可以是一 `{"type":"function"}`需要有一个`"function"`参数,它是一个JS函数,里面可以写任何自定义的JS脚本;系统将会执行它。 -系统常见可能会被造塔所用到的的API都在[API列表](api#附录:API列表)中给出,请进行参照。 +系统常见可能会被造塔所用到的的API都在[API列表](api)中给出,请进行参照。 **警告:自定义脚本中只能执行同步代码,不可执行任何异步代码,比如直接调用core.changeFloor(...)之类都是不行的。** -[API列表](api#附录:API列表)中的所有异步API都进行了标记;如果你不确定一个函数是同步的还是异步的,请向小艾咨询。 +[API列表](api)中的所有异步API都进行了标记;如果你不确定一个函数是同步的还是异步的,请向小艾咨询。 如果需要异步的代码都需要用事件(insertAction)来执行,这样事件处理过程和录像回放才不会出错。 diff --git a/_docs/img/plugin.jpg b/_docs/img/plugin.jpg new file mode 100644 index 00000000..d0d69bef Binary files /dev/null and b/_docs/img/plugin.jpg differ diff --git a/_docs/personalization.md b/_docs/personalization.md index 904b6e45..3341f2dd 100644 --- a/_docs/personalization.md +++ b/_docs/personalization.md @@ -51,7 +51,7 @@ core.fillText('test', '这是一段文字', 10, 30, '#FF0000', '16px Verdana'); `core.deleteAllCanvas()`可以删除所有动态创建的画布,`core.relocateCanvas(name, x, y)`和`core.resizeCanvas(name, x, y)`可以对画布的位置和大小进行改变。 -更多详细API请参见[API列表](api#附录:API列表)。 +更多详细API请参见[API列表](api)。 ## 自定义素材 @@ -339,7 +339,7 @@ function (enemy, hero_hp, hero_atk, hero_def, hero_mdef, x, y, floorId) { 要修改楼传事件,需要进行如下两步: -1. 重写楼传的点击事件。在插件中对`core.control.useFly进行重写`。详细代码参见[重写点击楼传事件](api#重写点击楼传事件)。 +1. 重写楼传的点击事件。在插件中对`core.control.useFly进行重写`。详细代码参见[重写点击楼传事件](script#重写点击楼传事件)。 2. 修改楼传的使用事件。和其他永久道具一样,在地图编辑器的图块属性中修改楼传的useItemEffect和canUseItemEffect两个内容。例如: ``` js "useItemEffect": "core.insertAction([...])" // 执行某段自定义事件,或者其他脚本 @@ -429,7 +429,7 @@ this.myfunc = function(x) { 从V2.6开始,在插件中用`this.xxx`定义的函数将会被转发到core中。例如上述的`myfunc`除了`core.plugin.myfunc`外也可以直接`core.myfunc`调用。 -详见[函数的转发](api#函数的转发)。 +详见[函数的转发](script#函数的转发)。 ## 标题界面事件化 diff --git a/_docs/script.md b/_docs/script.md new file mode 100644 index 00000000..817a68a6 --- /dev/null +++ b/_docs/script.md @@ -0,0 +1,313 @@ +# 脚本 + +?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} * + +在V2.6版本中,基本对整个项目代码进行了重写,更加方便造塔者的使用和复写函数。 + +## 控制台的使用 + +在Chrome浏览器中,按(Ctrl+Shift+I)可打开控制台。 + +![](img/console.jpg) + +控制台中有很多的标签,最常用的是`Console`, `Sources`和`Elements`。 + +有关更详尽的控制台使用可自行搜索[Chrome开发者工具](https://www.baidu.com/s?wd=chrome%20%E5%BC%80%E5%8F%91%E8%80%85%E5%B7%A5%E5%85%B7)了解更多。 + +### Console:命令行 + +Console页为命令行。可以在这里输入一些命令进行调试。 + +比如,进入游戏后,输入`core.status.hero.atk`即可获得勇士的当前攻击力数值。`core.status.hero.atk=100`可以设置攻击力为100。 + +更多的API可参见[附录:API列表](#附录:API列表)。 + +除此以外,游戏中的报错等信息也是可以在Console中进行查看的。 + +![](img/console1.jpg) + +### Sources:断点调试 + +Sources页可以查看JS源代码,并进行断点调试等。 + +例如,如果相对脚本编辑中的伤害计算函数进行断点调试: +1. 在左边找到`project/functions.js`,单击打开文件 +2. 并找到对应的行(可以Ctrl+F搜索),比如搜索`getDamageInfo` +3. 在行号上点一下打断点,会出现一个蓝色标签 + +之后,当代码运行到你的断点处时,将自动停止运行。 + +![](img/sources.jpg) + +可以将鼠标移动到变量上,将弹窗形式显示这个变量的各项数值,从而查看变量值是否符合预期。 + +图中红色框内有几个按钮,从左到右分别是:**继续执行**,**执行到下一行**,**进入当前函数**,**跳出当前函数**,**单步执行**。 + +通过这几个按钮,可以一行一行的对代码进行执行,执行过程中能不断查看各个变量的数值变化,从而定位问题所在。 + +红圈下方是Call Stack,即当前的函数调用链(从哪些地方调用过来的)。 + +Sources还有更多有趣的功能,在此不做介绍,有兴趣的可自行网上搜索了解。 + +### Elements:网页元素查看 + +Elements页可以查看网页的源代码,调整css布局等。 + +![](img/elements.jpg) + +不过对魔塔样板来说,最重要的是红圈中的按钮。点击此按钮可以进入**手机模式**。 + +手机模式下,左边可以对屏幕分辨率进行调整和模拟。 + +这可以很有效的帮我们进行测试样板在手机端的表现。 + +## 整体项目架构 + +``` text +├── /_server/ # 为可视化地图编辑器提供一些支持的目录 +├── /libs/ # ---- 系统库目录 ---- +│ ├─ /thirdparty/ # 游戏所用到的第三方库文件 +│ ├─ actions.js # 用户交互处理 +│ ├─ core.js # 系统核心文件(游戏入口,接口&转发) +│ ├─ control.js # 游戏逻辑控制 +│ ├─ data.js # 全塔属性等 +│ ├─ enemys.js # 怪物相关处理 +│ ├─ events.js # 各个事件的执行 +│ ├─ icons.js # 图标和素材 +│ ├─ items.js # 道具效果 +│ ├─ loader.js # 各个资源加载 +│ ├─ maps.js # 地图数据和绘制 +│ ├─ ui.js # UI窗口绘制 +│ └─ utils.js # 工具类函数 +├── /project/ # ---- 项目目录 ---- +│ ├─ /animates/ # 动画目录 +│ ├─ /floors/ # 楼层文件 +│ ├─ /images/ # 图片素材 +│ ├─ /sounds/ # bgm和音效 +│ ├─ data.js # 全塔属性 +│ ├─ enemys.js # 怪物属性 +│ ├─ events.js # 公共事件 +│ ├─ functions.js # 脚本编辑 +│ ├─ icons.js # 素材和ID的对应关系定义 +│ ├─ items.js # 道具的定义和效果 +│ ├─ maps.js # 地图和数字的对应关系 +│ └─ plugins.js # 自定义插件 +├── /常用工具/ # 辅助造塔的小工具 +├── editor.html # 地图编辑器 +├── editor-mobile.html # 手机版的地图编辑器 +├── index.html # 主程序,游戏的入口 +├── main.js # JS程序的入口,将动态对所需JS进行加载 +├── style.css # 游戏所需要用到的样式表 +└── 启动服务.exe # 一个本地的HTTP服务器,通过它来运行游戏 +``` + +`_server`为**地图编辑器目录**,里面存放了地图编辑器相关的各项内容。 + +`libs`为**系统库目录**,里面存放了各个系统核心函数。 + +从V2.6开始,请勿直接修改libs下的代码,如有需要修改系统库函数请尝试在插件中[复写函数](#复写函数)。 + +`project`为**项目目录**,你所造的塔的数据全部存放在project下。在不同样板之间接档也是直接迁移project目录即可。 + +## 函数的转发 + +在本样板中,`core.js`里面基本是没有定义什么函数的,所有的游戏内函数都在其他几个文件中实现。 + +例如,常见的获得某个变量值`getFlag`是定义在`control.js`中的: + +```js +////// 获得某个自定义变量或flag ////// +control.prototype.getFlag = function(name, defaultValue) { + if (!core.status.hero) return defaultValue; + var value = core.status.hero.flags[name]; + return value != null ? value : defaultValue; +} +``` + +也就是,我们可以通过`core.control.getFlag(name, value)`来调用此函数。 + +但是这样会十分不便,我们希望能直接调用`core.getFlag(name, value)`,而不需要中间的control。 + +为了达到这个目的,样板设置了**函数转发**,即**将其他文件中定义的函数,转发到core中执行**。 + +上述`getFlag`代码的转发实际上是增加了如下函数: + +```js +////// getFlag函数的转发 ////// +core.getFlag = function (name, defaultValue) { + return core.control.getFlag(name, defaultValue); +} +// 转发后,即可通过 core.getFlag() 来实际调用 core.control.getFlag() +``` + +转发是自动完成的,其满足如下两条规则: +- **在libs中其他文件定义的函数,如果不以下划线`_`开头,就会进行转发。** +- **如果core中已经存在同名函数,则会在控制台中打出一条报错信息,并不转发该函数。** + +具体函数的转发实现代码可参见`core.js`的`_forwardFunc`函数。 + +!> 除此以外,插件中以`this.xxx`来定义的函数也会被转发! + +例如,你可以直接调用`core.drawLight()`来实际调用插件中的`core.plugin.drawLight`。 + +## 插件编写 + +插件编写是H5魔塔的一个重大特点,从V2.0.1引入,并逐渐发扬光大。 + +对于有一定脚本经验的人来说,可以编写插件来实现各种各样的功能,包括且不仅限于拓展功能的实现,系统代码的复写等等。 + +在V2.5.5以前,插件位置都在脚本编辑中;从V2.6开始则迁移到了新的下拉框中,并进行了切分。 + +你也可以创建自己的插件。 + +![](img/plugin.jpg) + +新的插件切分和原来的单插件使用方法完全一致,单纯进行了切分而已。可参见已有的`init`和`drawLight`的样例。 + +拆分的意义主要是将各个可能的功能独立出来,避免单个框内内容太长,过大和混杂等。 + +在V2.6中,应当每个独立的额外功能实现都新建一个自己的插件,这样也方便进行拓展,例如打包迁移到别的塔上,或发布在网页插件库中。 + +另外一点需要注意的是,所有插件的初始化都会在系统资源加载之前,此时图片等资源尚未进行加载。 + +在所有资源加载完毕时,将会执行init插件中的_afterLoadResources函数,可以在这里对资源进行一些操作,比如切分图片等。 + +```js +function () { + console.log("插件编写测试"); + + // 可以写一些直接执行的代码 + // 在这里写的代码将会在【资源加载前】被执行,此时图片等资源尚未被加载。 + // 请勿在这里对包括bgm,图片等资源进行操作。 + + + this._afterLoadResources = function () { + // 本函数将在所有资源加载完毕后,游戏开启前被执行 + // 可以在这个函数里面对资源进行一些操作,比如切分图片等。 + + // 这是一个将assets.png拆分成若干个32x32像素的小图片并保存的样例。 + // var arr = core.splitImage("assets.png", 32, 32); + // for (var i = 0; i < arr.length; i++) { + // core.material.images.images["asset"+i+".png"] = arr[i]; + // } + + } + + // 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx(); + // 从V2.6开始,插件中用this.XXX方式定义的函数也会被转发到core中,详见文档-脚本-函数的转发。 +} +``` + +网站上提供了一个插件库,[https://h5mota.com/plugins/](https://h5mota.com/plugins/),上面有一些大家分享的插件,可供使用。 + +可以查看附录中的[API列表](api)来查看所有的系统API内容。 + +## 复写函数 + +样板的功能毕竟是写死的,有时候我们也需要修改样板的一些行为。 + +在V2.6以前,需要直接打开libs目录下的对应文件并进行修改。但是开libs下的文件就会出现各种问题: +- 不容易随着新样板接档进行迁移 +- 也不好找到自己改过什么,从而能整理成新的插件在别的塔使用 +- …… + +好消息的是,从V2.6开始,我们再也不需要开文件了,而是可以直接在插件中对原始函数进行复写。 + +如果我想对xxx文件中的yyy函数进行重写,其模式一般是:`core.xxx.yyy = function (参数列表) { ... }` + +下面是几个例子,从简单到复杂。 + +### 重写怪物手册的背景图绘制,使用winskin而不是默认的黑色 + +直接重写怪物手册的背景图绘制,使用`core.drawBackground`来用winskin绘制一个背景图。 + +```js +// 重写ui.js中的_drawBook_drawBackground函数 +core.ui._drawBook_drawBackground = function () { + // core.__PIXEL__为定义的一个宏,对于13x13的值是416,对于15x15的值是480 + core.drawBackground(0, 0, core.__PIXEL__, core.__PIXEL__); +} +``` + +### 重写点击楼传事件 + +重写点击楼传事件,使得点击楼传按钮时能使用一个道具(比如item:fly)。 + +```js +// 重写events.js的useFly函数,即点击楼传按钮时的事件 +core.events.useFly = function (fromUserAction) { + if (core.isMoving()) { + core.drawTip("请先停止勇士行动"); + return; + } + if (core.status.lockControl || core.status.event.id != null) return; + + if (core.canUseItem('fly')) core.useItem('fly'); + else core.drawTip("当前无法使用"+core.material.items.fly.name); +} +``` + +其他的几个按钮,如快捷商店`openQuickShop`,虚拟键盘`openKeyBoard`的重写也几乎完全一样。 + +### 楼层切换时根据flag来播放不同的音效 + +整体复制并重写整个楼传切换前的函数,将`core.playSound('floor.mp3')`替换成根据flag来判定。 + +```js +// 复制重写events.js中的_changeFloor_beforeChange,修改音效 +core.events._changeFloor_beforeChange = function (info, callback) { + // 直接替换原始函数中的 core.playSound('floor.mp3'); + if (core.getFlag("floorSound") == 0) core.playSound('floor0.mp3'); + if (core.getFlag("floorSound") == 1) core.playSound('floor1.mp3'); + if (core.getFlag("floorSound") == 2) core.playSound('floor2.mp3'); + // ... + + // 下面是原始函数中的剩余代码,保持不变 + window.setTimeout(function () { + if (info.time == 0) + core.events._changeFloor_changing(info, callback); + else + core.showWithAnimate(core.dom.floorMsgGroup, info.time / 2, function () { + core.events._changeFloor_changing(info, callback); + }); + }, 25) +} +``` + +### 每次打开全局商店时播放一个音效 + +打开全局商店是在`events.js`中的`openShop`函数,因此需要对其进行重写。 + +然而,我们只需要在这个函数执行之前插一句音效播放,所以并不需要重写整个函数,而是直接插入一行就行。 + +```js +var openShop = core.events.openShop; // 先把原始函数用一个变量记录下来 +core.events.openShop = function (shopId, needVisited) { + core.playSound("shop.mp3"); // 播放一个音效 + return openShop(shopId, needVisited); // 直接调用原始函数 +} +``` + +### 每次绘制地图前在控制台打出一条信息 + +绘制地图在`maps.js`的`drawMap`函数,因此需要对其进行重写。 + +由于只需要额外在函数执行前增加一句控制台输出,所以直接插入一行即可。 + +但是需要注意的是,`drawMap`中使用了`this._drawMap_drawAll()`,因此使用函数时需要用`call`或者`apply`来告知this是什么。 + +```js +var drawMap = core.maps.drawMap; // 先把原始函数用一个变量记录下来 +core.maps.drawMap = function (floorId, callback) { + console.log("drawMap..."); // 控制台打出一条信息 + drawMap.call(core.maps, floorId, callback); // 需要使用`call`来告知this是core.maps +} +``` + +详见[call和apply的用法](https://www.jianshu.com/p/80ea0d1c04f8)。 + +========================================================================================== + +[继续阅读下一章:API列表](api) + + diff --git a/_docs/start.md b/_docs/start.md index f5b4fa12..004ea21f 100644 --- a/_docs/start.md +++ b/_docs/start.md @@ -231,7 +231,7 @@ HTML5的塔都是可以进行控制台调试的。 - `core.resetMap()` 重置当前层地图。 - …… -更多API和详细参数介绍可参见[API列表](api#附录:API列表)。 +更多API和详细参数介绍可参见[API列表](api)。 ## 编辑器的基本操作 diff --git a/libs/ui.js b/libs/ui.js index 6c4501e2..54dbccc1 100644 --- a/libs/ui.js +++ b/libs/ui.js @@ -542,7 +542,7 @@ ui.prototype._calTextBoxWidth = function (ctx, content, min_width, max_width, fo // 如果不存在手动换行,尽量调成半行形式 if (allLines.length == 1) { - var w = core.calWidth(ctx, allLines[0]) + 5; + var w = core.calWidth(ctx, allLines[0]) + 10; if (w