最近在开发微信小游戏,中途遇到了一些问题,在这里进行一下总结,也是自己做个笔记,同时,如果有人需要,希望能够帮的上忙。
首先对开发环境进行简要说明:
1.开发工具 cocos creator 1.9.1
2.开发语言 js
下面对开发内容进行说明。
1. 微信平台的判断
。在开发过程中,会经常调用微信提供的原生方法。微信提供了一个wx的接口,在cocos中默认继承了该API,只要是打包成微信小程序、小游戏,就可以直接用 wx.funcName() 的方式就能调用微信的相关的方法。但是在正常的浏览器调试的时候,要屏蔽掉该内容,此时不能直接用 if (!wx) 方式判断,一个朋友之前用这种方式判断,我也尝试了一下,但是直接报错,所以,不建议这样操作。其实引擎已经给集成了平台判断的方法,就像原生的iOS和Android一样,判断方式如下:
if (cc.sys.WECHAT_GAME == cc.sys.platform) {
// 调用你的要在微信上要执行的方法
}
通过该方式,可以进行平台判断。实际上,creator中定义了一个结构如下:
export class sys {
//...
static WECHAT_GAME: number;
static QQ_PLAY: number;
//...
}
这里只是截取了一部分,这里包含好多平台,包括微信小游戏和QQ玩一玩。但是,注意,并不包含Facebook Instant Game平台
,所以,如果要开发FIG的话,要注意这一点。
2. 加速度计的使用
下面说一下【加速度计】的使用。我开发的项目应用了加速计功能,所以这里对这部分进行一下简单的说明。cocos引擎默认自带加速计功能:
// 加速度计事件监听
cc.systemEvent.setAccelerometerEnabled(true);
cc.systemEvent.on(cc.SystemEvent.EventType.DEVICEMOTION, this.onDeviceMotionEvent, this);
在使用系统自带的加速度计的时候,首先要启用加速度计,然后,设置加速度计方向改变的监听。监听方法实现如下:
onDeviceMotionEvent(event) {
// cc.log(event.acc.x + " " + event.acc.y);
},
在这里,通过event.acc.x 、 event.acc.y 、 event.acc.z 可以获取到x、y、z三个方向,这种方式在手机浏览器、iOS和Android上都管用,但是,在微信小游戏里面是不管用的
,这一点一定要注意。所以,这部分只能用微信提供的接口了。
wx.onAccelerometerChange(function(res) {
// console.log('加速度计方向改变: res ---> ' + JSON.stringify(res));
// console.log('加速度计方向改变: res.x ---> ' + res.x);
// console.log('加速度计方向改变: res.y ---> ' + res.y);
// console.log('加速度计方向改变: res.z ---> ' + res.z);
}
通过这种方式,就可以监听微信的加速度计回调了。当然了,如果为了兼容的话,或者通用,可以找个地方把原生的方法重写,如果是微信小游戏,就直接调用微信的这个借口,然后,将res的x、y、z 映射成为event.acc的x、y、z,类似如下的方式:
function onDeviceMotion() {
var tempFun = cc.systemEvent.on;
cc.systemEvent.on = function (type, callback, target) {
if (type == cc.SystemEvent.EventType.DEVICEMOTION && cc.sys.WECHAT_GAME == cc.sys.platform) {
wx.onAccelerometerChange((res) => {
var event = {
'acc': {
'x': res.x,
'y': res.y,
'z': res.z,
}
};
callback.call(target, event);
});
} else {
tempFun.call(cc.systemEvent, type, callback, target);
}
}
}
在游戏启动的时候,调用一下这个方法,将系统的方法处理一下,方便以后的各个平台发布。虽然我们最后还是这样处理了一下,但是这种强行的映射,总觉得不太好。
4. shader的使用问题
。我们当时做的是一款水底类型的休闲小游戏。所以,当时为了做出水底的感觉,因此,博主找了一个水波纹的shader,当然,这不是我自己写的,是在网上找的一个大神的代码,我只是将ts翻译成了js而已。下面附上大神的代码仓库地址:
shader仓库地址
但是,实际上,微信小游戏是不支持shader的
,我测试了,并不管用,但是在原生平台和H5上还是可以用的。
5. 下面说一下richText的使用问题
,微信小游戏是不支持richText的
,所以,在开发过程中,就不用想着用richText了,而且,本来richText就比较影响性能,所以,不使用也是个不错的选择。而且,如果是分数等的话,可以用艺术字,用着反倒是更方便。谈到艺术字,要声明一下,在小游戏的子域,艺术字以及图片合集是不支持的
。
6. 关于图片的使用问题
。由于微信小游戏对于包体大小进行了限制,要求小于4M,所以,在开发的过程中,考虑过使用webp格式的图片,实际上,在开发过程中,使用webp是没问题的,但是,当打包成微信小游戏的时候,会报错,微信小游戏不支持webp格式的文件
。
7. 关于微信小游戏启动的黑屏的问题
。对于包体大于4M的微信小游戏,微信小游戏在启动的时候,经常会有短暂的黑屏,而且,如果资源很多,可能会时间更长。这个时候,微信其实是在下载资源。如果觉得黑屏不好看,其实可以在启动的main.js文件中设置其他的颜色。
就是如图所示的这个main.xxx.js文件。打开这个js文件,找到 cc.director.loadScene ,在上面添加以下代码,进行颜色修改:
cc.director.setClearColor(new cc.Color(255, 255, 255));
这样那个就把颜色设置成了白色。但是直接这个main文件有个问题,就是每次都要改,为了方便起见,可以考虑做一个模板。
如上所示,在build同级目录下创建一个build-templates目录,然后不同的类型可以创建不同的目录,微信小游戏就创建wechatgame目录,然后把前面的那个main.xxx.js文件复制过来,改为main.js 。到这里还没有完全完成该功能。打包微信小游戏的时候,由于选择了MD5 Cache ,所以,所有的文件都是main.xxx.js 这种命名方式的。所以,打开wechatgame/main.js,从头到尾找一下这种格式的引用,修改一下即可。下面以我这边的为例,进行展示:
var bundledScript = settings.debug ? 'src/project.dev.js' : 'src/project.ea0c1.js';
require(window._CCSettings.debug ? 'cocos2d-js.js' : 'cocos2d-js-min.37a0b.js');
require('src/settings.f6cee.js');
cocos2d.src = window._CCSettings.debug ? 'cocos2d-js.js' : 'cocos2d-js-min.37a0b.js';
找到了这几个文件你,将 project.ea0c1.js 改为 project.js 即可,后面的以此类推。注意,那个project.dev.js不需要修改。至此,一个微信小游戏main文件的模板就修改好了。这个方式,是cocos官网提供的解决办法。链接如下:
定制项目构建流程
8. 关于微信子域的问题
。微信子域的接入问题,在开发过程中,建议还是先参照官方的文档进行处理,然后再参照我的博客:
接入小游戏的子域
官方文档只是一个简单的Demo,在实际开发中,会遇到更多复杂的操作,所以,这里我对自己的开发方式进行简要说明。
cc.Class({
extends: cc.Component,
properties: {
display: cc.Sprite
},
start () {
this.tex = new cc.Texture2D();
},
// 刷新子域的纹理
_updateSubDomainCanvas () {
if (cc.sys.WECHAT_GAME != cc.sys.platform) {
return;
}
if (!wx) {
return;
}
if (!this.tex) {
return;
}
this.tex.initWithElement(sharedCanvas);
this.tex.handleLoadedTexture();
this.display.spriteFrame = new cc.SpriteFrame(this.tex);
},
update () {
this._updateSubDomainCanvas();
}
});
当然了,首先是要在主域里面有一个Sprite,用来展示子域的子域的内容。这里的实现方式是在主域中,获取到shareCanvas,然后赋予到一个texture2D上面,通过这个tex设置Sprite的spriteFrame。子域一般都是用来展示排行榜的,排行榜是个scrollView,所以会刷新,为了保持一致,就在update中反复调用这个渲染的操作,更新到主域上面。
下面说一下可能遇到的问题。首先,如果我们在多个页面都要显示排行榜,显然不能在每个需要的地方都写一遍逻辑。那么,最好的办法,是在某个图层上面,单独进行处理,不管在哪里,都只需要让这个图层负责处理排行榜的问题就好了。此外,还有一个问题,这里进行说明和提醒!!!由于子域的内容是在update的时候渲染出来的,所以,当我们的游戏有暂停功能的时候,如果想要在暂停页面查看排行榜,那么就要保证update是执行的,也就是说,暂停功能不能够使用cocos提供的 cc.director.pause() 方法。cc.director.pause()方法调用之后,不再执行update操作,但是此时还是可以接受点击事件的,所以说,既然无法执行update,那么,就无法刷新子域。
这部分值得注意,我本人就被这个坑过。
子域还有一个问题,就是当你打了一个不带子域的包的时候,如果此时,仍然在update中刷新并获取子域内容,就会有显示错误,因此,要把update中调用的方法注释掉,才会显示正确。
9. 项目打包问题
。小游戏在开发过程中,对包体大小有要求,就是不能够大于4M,所以,在开发过程中,如果是比较小型的游戏,不需要太多的资源,那就要尽量保证资源的大小和代码文件的大小。实际上,在开发过程中,如果我们如果要打包小游戏,在构建微信小游戏的时候,会发现代码文件会很大。如图所示,就是这个文件很大:
从截图中,我们会发现这个cocos2d-js-min.js文件很大,有1.6M,那么,如果此时我们再把子域打包进来的话,那就3.2M了,我们还要写自己的代码,还要放图片资源,很显然,这会很容易超出4M。因此,我们要处理一下这个cocos2d-js-min.js文件,把它变小一下,这样,我们就能够减小小游戏的包体了。cocos creator为我们提供了一个解决办法。点击【项目】->【构建】,然后选择【模块设置】,把不用的模块去掉就行了:
我在这里面选了几个没用到的模块,取消了勾选,并保存了。操作完成后,cocos2d-js-min.js就变小了一些,当然,看自己的需求,如果需要的东西更少的话,可删减的内容就更多了,这个文件的大小也会变得更小。主域和子域的代码都进行删减的话,会节省出来更多的空间,而且,实际上,在子域里面,需要处理的东西很少,可删减的空间更大。
当然,在删减的过程中,如果删减出错了,打包成小游戏的时候,是会报错的,为了防止这个问题的发生,大家可以去官网了解一下各个模块负责哪些功能,根据个人需要进行删减。官方论坛有一篇文章,可以过去参考一下,下面给出文章名字和链接:
由于模块比较多,这里就不依依罗列了,建议大家去官方论坛查看,有问题,多在官方论坛和论坛里面的各位进行沟通。
到这里,基本把项目开发中遇到的问题都简单的进行了一下总结。算是给自己做一个笔记,也希望能够帮别人避免类似的问题。如果有哪里说的有问题,希望大家能够进行批评指正。