Egret使用已有大半年,相比其他H5引擎,Egret的优势是官方文档齐全,配套工具完善,但性能不是很突出。
曾使用官方提供的配套工具
- 界面排布及属性预设—Egret Wing
- 碎图压缩合成大图及MovieClip动画素材处理—TextureMerger
- 资源管理—ResDepot
- chrome下调试插件—Egret Inspector
- 粒子效果制作—EgretFeather
当然,代码编写还是要用WebStorm及Sublime。以及开发中常用到的小小工具:在线图片压缩—TinyPng.com,合图分割—pngSplit,在线Json转换—bejson,二维码生成器cli.im等等。
调试参数说明及MovieClip
- index.html中,data-entry-class = “Main”,进入游戏访问的第一个Ts文件,入口类;data-orientation=”auto”,旋转方向设置;data-frame-rate = “60”,游戏帧率设置,可更改,建议为60的约数,正式项目基本设置为60,测试时更改。data-show-fps=”false”,默认为false,开启后可看到实时帧率,测试使用;data-show-log = “false”,默认为false,开启后,代码中egret.log()中的内容即显示在屏幕中,测试使用。
- 开启fps后的参数说明。FPS为帧率;Draw为每帧draw方法调用的平均次数,脏矩阵占舞台的百分比;Cost为每帧舞台所有事件处理及矩阵运算耗时,绘制显示对象耗时(单位为ms)。
- MovieClip举例123456789101112131415161718192021222324252627282930class Bomb extends egret.Sprite{private mcf:egret.MovieClipDataFactory;private mc:egret.MovieClip;public constructor(){super();this.init();}public init(str1:string,str2:string,number:number):void{var data = RES.getRes(str1);var tex = RES.getRes(str2);this.mcf = new egret.MovieClipDataFactory(data, tex);this.mc = new egret.MovieClip();this.mc.movieClipData = this.mcf.generateMovieClipData();this.mc.play(number); //playTimes:number — 播放次数。 参数为整数,可选参数,>=1:设定播放次数,<0:循环播放,默认值 0:不改变播 放次数(MovieClip初始播放次数设置为1),this.addChild(this.mc);this.mc.addEventListener(egret.Event.COMPLETE, this.removeBomb, this);}//轰炸完毕private removeBomb(evt:egret.Event):void{if(this.parent!=null){this.parent.removeChild(this);}}}
性能优化
- Audio
- 如果需求中需要同时播放多个音频,则使用WebAudio。X5浏览器内核WebAudio可支持多音频。Egret3.1.4之后,index.html文件中,egret.runEgret({renderMode:”webgl”,audioType:0}); 默认的渲染模式为Canvas,之前微信平台上的游戏使用的均为Canvas。音频类型中,默认为0,IOS7以上表示WebAudio;1表示QQ Audio,项目若在腾讯平台上线如QQ空间中的玩吧,则使用QQ Audio,腾讯解析音频有自己的一套方案;2表示强制使用WebAudio;3表示使用浏览器自带的Audio,不推荐。
- 当多个音频轮询播放播放的时候,如ababa,如果打开网络侦听,有可能发现播放一次向服务器请求一次,原因是不同浏览器内核对音频实现方式不一样。解决方案是:将轮询播放的多个音频拼成一个音频,通过时间段控制播放。
- 由于浏览器的安全限制,加载完成可能无法自动播放背景音乐,这种情况将背景音乐设置成点击播放的形式,如加载完成后,弹出按钮,玩家点击选择是否播放背景音乐。主流H5游戏均是采用这种方式。
- Text
- TextField中使用cacheAsBitmap,可以减少重绘次数。原因是TextField是文本,浏览器渲染通过CPU的计算,对图片渲染速度快,对文本渲染速度慢。
- TextField减少对于描边(stroke)的使用,用图片代替。
- 输入文本框尽量出现在软键盘的上面,手机部分浏览器中,如果输入文本框太靠下,弹出的软键盘会遮挡住输入文本框。
- Image
- 单张图(包括SpriteSheet)的大小不要超过1024*1024,浏览器对图片大小限制会对超过的该尺寸大小的图片进行自动压缩处理导致图片模糊发虚。
- 将碎图合成一张大图,每次进行图片下载时会先进行TCP三次握手协议,这个时间会超过较多小图下载的时间。
- 使用九宫格时,不要使用非整数宽高;在List控件中不要使用九宫格图片来减少draw的次数。
- 单静态页面,cacheAsBitMap可以减少重绘次数。如在大图中取出部分碎图组成的单静态页面。
- 使用SpriteSheet合并的图片尺寸要优于单张图片的总尺寸,尤其是带透明通道的。
- NetWork
- 素材处理。不要一次性下载太多的素材,尽量分布在使用前加载。将碎图和成一张大图,减少下载次数。Png图可以使用压缩工具(如TinyPng)压缩减少体积。
- 配置文件。尽量将配置文件合并到一个大文件里,减少下载次数。在Http请求中,加载单个文件速度要优于加载多个文件。配置文件去掉格式化,利用在线Json格式化工具(如bejson,sojson)处理Json数据。Json数据可以去掉一些不必要的小数和冗长命名。
- 下载处理。资源服务器开启GZIP压缩,提高载入速率;登录加主页面素材不要超过2M;加入静默加载,比如在登录界面操作时下载主页面相关素材。
- Mask
- 遮罩如果是DisplayObject,必须加入到显示列表后,方能正常使用。
- 遮罩如果是Rectangle,修改遮罩数据后,重新将遮罩赋值给对象。
- DisplayObject
Shape/DisplayObjectContainer,能通过父层计算出来的交互不直接在子容器里加。如EUI中,Group组件中有Image组件,Touch Image的监听直接将Touch监听加在Group上,如果是一个Group中有多张图需要有监听事件,可在Group上加一个监听,根据Group的Touch位置进行响应。
禁用不必要显示对象的触摸交互,默认就是关闭的。但是开发时,自己的写的底层框架可能又给打开了,eui的touchenable是默认打开的,不需要touch事件监听时需手动关闭。触摸屏幕实际上就是触摸canvas,canvas根据位置在显示列表中逐层搜索,实际上也是碰撞检测。
1234567var sp :egret.Sprite = new egret.Sprite();this.addChild(sp);sp.touchChildren = false; //确定子孙对象是否接受触摸事件,默认为truesp.touchEnabled = false; //此对象是否接受触摸事件,默认为true能用图片的不用Graphics实现。
- 尽量将静态图或者文字放到一个容器中,并对容器缓存(cacheAsBitMap)。
- 减少显示对象的旋转及缩放。
- 尽可能重用对象,建立对象池,而不创建对象并对其执行垃圾回收。创建对象时,将对象创建在循环外部并在循环内反复重用。需要密集的创建对象,要引入对象池,例如做一款打飞机类型的游戏,进入战斗前,飞机,怪物,掉血特效等对象提前初始化,在过程中实时提取,而不是实时创建。
- 对象复用与释放
- Event派发要合理使用Event自带的静态方法,如egret.Event.dispatchEvent(this,”dragonbones”)。
- 事件删除,用完事件即删除。
- Tween循环结束时,删除。
- 显示列表删除,面板不使用则remove掉。
- 显示停止计时器,让它们准备好进行垃圾回收。暂停清除计数器clearInterval()、clearTimeout()、Timer.stop()。
- TypeScipt
- 尽量不要在使用方法内创建函数,一个函数内不要嵌套另一个函数的定义
- Ts中没有super属性的调用,Js类继承的本质是通过原型链实现的,但是egret提供了egret.superGet 和 egret.superSet 来调用父类属性。
- 类方法中,将this赋值给另一个临时变量self,var self = this;如果当前类this使用较多,如for循环内使用时,使用self。
- 其他
- LocalToGlobal后的坐标不要有小数;一般情况下坐标计算等也尽量不使用小数。
- 对象复用比较高时,如打飞机的子弹,使用对象池优化。
- 尽量减少Alpha混合的使用。
- 多次调用类属性时,避免直接使用this,如果for循环一直用到this.a,可var _a = this.a,用变量做简单缓存再去计算,效率就会提升,如_length = Array.length。
- Event.ENTER_FRAME数量控制。MainLoop包括ENTER_FRAME(每帧主要执行逻辑)->CLEAR(清空上一帧图像) ->UPDATE TRANSFORM(计算这一帧的显示) -> UPDATE DRAW。
- 位移如跑酷游戏的计算不要通过帧数来计算,通过时间来计算。
- 使用60的约数作为帧频数。Egret自带Timer,每秒固定振荡60次。
- 对于简单的动画,使用序列帧或者db的急速模式。
- 非动作游戏降低帧率可大幅提高性能。