白鹭H5游戏移植到微信小游戏笔记

我们有个H5项目之前是用白鹭5.0.4开发的,最近花了一些时间进行了迁移工作。以下是整理的一些笔记。

最有用的资源应该算是白鹭的官方FAQ,不过还是有点太言简意赅了,对一些底层机制介绍的太少。

http://developer.egret.com/cn/github/egret-docs/Engine2D/minigame/minigameFAQ/index.html

移植的步骤大概可以分为以下几步
1.前期准备
2.项目迁移
3.真机调试
4.Bug与优化
5.发布
6.接入更多小游戏功能

前期准备

1). 下载最新的EgretLauncher,并升级白鹭引擎到最新的5.1.x
2). 安装最新的微信开发者工具
3). 为了减少麻烦,申请一个正式的小游戏AppID(测试id有时候会莫名失败)

https://mp.weixin.qq.com/

4). 由于5.0.x工程无法直接升级到5.1.x,需要创建一个新项目,假设工程名为wxgame2(我的第二个测试工程)
5). 通过Egret Launcher发布出微信小游戏工程目录,默认位置为与h5工程所在目录,工程目录名<h5_project>_wxgame

这里就是 wxgame2_wxgame了。

6). 通过微信开发者工具打开这个工程,正常应该可以看到白鹭的helloworld页面

至此,准备工作完成,下一步进行正式项目迁移。

项目迁移

1). 拷贝旧项目代码及资源到新项目中
2). 编译试运行

egret build --target wxgame

除非你的项目跟helloworld一样简单,通常来说,都会报一堆的错误,来一个个解决。

3). 第三方库
3.1).下载项目所需的最新的第三方库,包括白鹭自带的第三方库,比如物理引擎 physics,粒子系统 particle

https://github.com/egret-labs/egret-game-library

3.2).将第三方库的模块注册到window变量下,打开 /wxgame/wxgame.ts
找到async onFile(file: plugins.File) 方法,模仿别的库的方法,将particle挂到window下

3.3). 我测试的时候,发现物理引擎库p2按照3.2)的方式添加有问题,所以,我换了一种方式。直接打开physics.js和physisc.min.js,修改如下:

(physics.js)

(physics.min.js)

3.4). 如果你需要解析xml,比如tiledmap文件,则需要引入xmldom库:
下载地址:

http://developer.egret.com/cn/github/egret-docs/Engine2D/minigame/minigameFAQ/xmldom.zip

放到 小游戏项目 (_wxgame) 的根目录下,不要放到js或者libs目录,打包的时候会被清空:

3.5). 将 xml 库挂到window上,可以修改小游戏项目的<project_wxgame>/game.js文件,egret.runEgret之前添加:

3.6). 如果你还用到了其他的第三方库,注意两点:
a). 如果是白鹭的,更新到最新
b). 然后,添加到window上。(参考以上3种添加方式)

4). 新项目默认用assetsmanager,如果用不惯,或者跟我一样遇到api调用错误,修改egretProperties.json,把assetsmanager改回res

5). 如果你用白鹭的eui,那么,请注意,

小游戏中不支持从外部加载exml的方式

具体原因,大概是因为eui库使用了动态生成代码的技术,而这是小游戏所不允许的。

要发布到小游戏,eui必须用commonjs的方式发布,不过,新生成的工程默认已经是这个选项了,并不需要改动什么的。

查看 <h5_project>/scripts/config.wxgame.ts 文件

所以,每次你修改exml文件,都需要重新编译成小游戏项目。

egret build --target wxgame

生成的js文件会自动拷贝到 <project_wxgame>/js/下,并在manifest.js中引用

由于种种原因,你所用到的.thm.json文件和skins文件,最好都放在resource目录,并在egretProperties.json中正确配置。

另外,不要尝试直接或者间接使用exml文件,由于eui的实现机制已经被小游戏禁用了,目前这条路走不通。非要用的话,得自己去解析并构建界面。

6). 如果用到自定义组件,可能需要手动挂到window下。

比如我自己写了一个WxHelper.ts文件,里边放了一个RegisterGlobalClasses方法,用来注册一些自定义组件和外部

然后在这个组件被使用之前,调用这个方法。比如,Main.ts里。

7). 手动拷贝resource目录外的资源到小游戏工程。
egret build或者publish只会帮你处理resource目录下的资源,所以,如果你跟我一样,有些资源是自己管理的,则需要手动拷贝到小游戏工程目录下。

8). 资源配置文件 (默认default.res.json) 暂时可以不改。
9). 现在,应该可以在微信开发者工具里编译调试项目了。

真机调试

如果在微信开发者工具调试没问题,可以尝试到真机进行调试。

在开发者工具中,点击“预览”,项目会被打包上传到微信后台。如果你的项目比较小,那么顺利的话,应该是这样子:

不过,实际上,大部分时候,你会看到另一个错误:

这是因为,开发者工具会把整个工程含资源打包上传。一般来说,除非你的游戏非常小,否则都会超过4M的上限。

所以,要进行真机调试,最重要的步骤是,把资源从项目里分离出来,放到外部服务器,然后在游戏启动后,去动态加载。

步骤如下:
1). 将资源分组,启动组和动态组,其中启动组中包含游戏启动时必须的资源,而动态组,则是后期动态加载的资源。
2). 将动态组的资源从小游戏项目中删除
3). 修改资源配置文件(默认是default.res.json),添加启动组的配置项
4). 修改代码动态加载动态组的资源
5). 将动态组的资源放到外部服务器上
6). 将外部服务器配置到小游戏后台,配置完毕后,你可以在微信开发者工具的“详情”中看到

需要注意的是,如果你的服务器没用https并且域名没有备案,则在真机调试时,需要开启“不校验https证书”等选项

并在游戏里打开调试模式:

7). 资源分好后,再次尝试“预览”,这个时候,上传的包还有可能超过4M,但是只差个几K就可以了。

这是因为,我们用egret build命令时,所有代码都是没有压缩的,并且包含大量的注释,其中白鹭引擎的代码就已经将近3M了,留给我们的代码空间比较小。

如果差的不是很多,你可以尝试以下方法:

a). 删掉没用的ts文件,比如一些没用到的类
b). 去掉大段的注释,比如一些没用到的方法,旧的实现,等等
如果这时候还超,就需要用publish的方式来重新编译项目,这时候,代码会被压缩,一般就不会超4M了。
如果publish还超,说明你的代码量超过4M,已经不是小游戏范畴了……

8). 外部资源的加载
这时候如果去真机上“预览”,通常都会出现很多资源找不到的错误,为什么呢?

原因是,动态资源被放到外部服务器了,但是资源配置文件(default.res.json)中的路径还是指向本地路径。有两个方法:

a). 可以通过修改配置文件,把外部资源的url都带上服务器地址
这样带来一些问题:
一是要改的地方可能会比较多。
二是每次更换服务器,都要改配置文件。

b). 不修改配置文件,而是在代码里,对外部资源的url自动添加服务器地址。
这样的好处是显而易见,调试和管理上都简单很多。
不过,引擎自带的Resource库默认并没有暴露出足够的接口,让我们可以比较方便的去做。所以需要修改引擎代码将所需的接口暴露出来,然后在代码动态添加服务器地址。

9). 走到这一步,差不多应该可以顺利在手机上预览游戏了。

提示,如果要给其他人预览未发布的游戏,则需要在小游戏后台将他们的微信号加入到测试列表里。

BUG与优化

1). 音频

1.1). bug:真机丢声音

白鹭自带的音频库,在微信小游戏真机上会出现丢音效和背景音的问题,需要改用微信自带的音频库
参考官方文档:

https://developers.weixin.qq.com/minigame/dev/tutorial/ability/audio.html

1.2). bug: 真机切后台后,背景音中断

这个严格来说不是bug,而是小游戏的设定。官方文档中写的很清楚,游戏切后台,或者被系统打断时,音频会自动中断,开发者需要自行处理恢复音频的播放。

简单来说,需要在以下两个方法里判定是否需要恢复声音的播放:

1.3). 修改微信小游戏相关的问题的代码量本来不多,但是由于在ts里直接调用微信的api,如wx.onShow等,会出现编译错误,因为编译器找不到wx库。

要解决编译时的问题,需要添加一个wx api的描述文件,也就是通常所说的 .d.ts文件。

这个文件可以从网上找,github上挺多的。如果你需要调用的api比较少,也可以自己写一个,只考虑音频的话,wxgame.d.ts只需要以下几行:

2). 像素游戏不像素

如果你开发的是像素游戏,需要在游戏里设置

egret.Bitmap.defaultSmoothing = false。

正常效果应该是这样:

然而,如果你开启了滤镜(比如发光滤镜)或者遮罩,会发现,图像变模糊了。

这是引擎的一个bug,需要修改引擎的渲染代码,H5是egret.web.js或者WebGLRenderContext.ts

以及小游戏的渲染代码**<project_wxgame>/egret.wxgame.js** 中的方法:

WebGLRenderContext.prototype.drawTextureElements

3). 资源缓存

通过现在的动态加载资源的方法有个很大的弊端,每次游戏重新开启,这些资源都需要重新加载,如果资源比较多,则会导致游戏加载比较慢,所以开启本地缓存是很重要的。这个需要调用小游戏的相关接口来实现。

Release模式(发布模式)

需要注意的,在以上过程中,我们的项目一直都是处于Debug模式,如果要切换到Release模式,则需要用egret publish --target wxgame的命令。

小游戏的发布与H5项目的发布,并没有不同。首先,我们要了解的是Release模式与Debug模式的不同之处:
a). 资源
资源publish以后,需要重新上传到服务器上。
b). 代码
代码在publish过程中会被压缩。

对于小游戏来说,影响最大的,应该是资源的缓存问题。由于缓存空间有限(50M),哪些资源需要缓存,怎样缓存与更新,都是需要小心设计的。

最后,接入更多小游戏功能。