A闪的 BLOG 技术与人文
很多人对cacheAsBitmap不理解,或者理解的不够透彻。 其实很多东西都非常简单,只要你能够以全局的角度来看到Egret,那么你就会发现原来很多东西如此简单。
在上一篇文章《Egret性能优化之优化渲染》中,我曾经提到过一个优化的东西叫做cacheAsBitmap的优化技巧。由于篇幅的关心,和我不想啰嗦太多,导致讲解的不够细致。cacheAsBitmap很多时候用处非常大。在大型项目中,带来的性能提升也会非常明显。
首先我需要你回忆一下Egret中的Main Loop。这个东西和cacheAsBitmap息息相关。如果你还不太明白这个东西,请回到《Egret性能优化之优化渲染》重新阅读。
我们先来看一段代码,并且看看运行后的效果。(只贴出了关键的代码片段)
private context:egret.Sprite = new egret.Sprite();
private createGameScene(): void {
egret.Profiler.getInstance().run();
for( var i:number=0; i<12;i++ )
{
for(var t:number=0;t<5;t++)
{
var bit:egret.Bitmap = new egret.Bitmap();
bit.texture = RES.getRes("image_png");
bit.x = 75t+41(i%2);
bit.y = 48*i;
bit.scaleX = 0.5;
bit.scaleY = 0.5;
this.context.addChild(bit);
}
}
this.addChild(this.context);
}
注意,我在代码中创建了60个位图,并且有序的排列。将60个Bitmap放到一个Sprite中。运行后看到的效果如下:
此时你会发现,当前draw的数量为60。也就是说,在Main Loop中,每帧执行60次draw操作(Main Loop第四步)
我现在将代码简单的修改一下。
private context:egret.Sprite = new egret.Sprite();
private createGameScene(): void {
egret.Profiler.getInstance().run();
for( var i:number=0; i<12;i++ )
{
for(var t:number=0;t<5;t++)
{
var bit:egret.Bitmap = new egret.Bitmap();
bit.texture = RES.getRes("image_png");
bit.x = 75t+41(i%2);
bit.y = 48*i;
bit.scaleX = 0.5;
bit.scaleY = 0.5;
this.context.addChild(bit);
}
}
this.addChild(this.context);
this.context.cacheAsBitmap = true;
}
在运行一下,效果如图:
此时,draw变成了1。为什么会这样?到底在哪里会因为我将cacheAsBitmap设置为了true之后,draw变成了1呢?很简单,此时Sprite内部的60个位图被缓存为了1张位图。所以从60变成了1。
这个用法有个需要注意的地方,使用了cacheAsBitmap后,内部的元素将无法进行图形修改,除非你把cacheAsBitmap再设置为false。
为了解释这个问题,我们将代码稍微修改一下。
private context:egret.Sprite = new egret.Sprite();
private createGameScene(): void {
egret.Profiler.getInstance().run();
for( var i:number=0; i<12;i++ )
{
for(var t:number=0;t<5;t++)
{
var bit:egret.Bitmap = new egret.Bitmap();
bit.texture = RES.getRes("image_png");
bit.x = 75t+41(i%2);
bit.y = 48*i;
bit.scaleX = 0.5;
bit.scaleY = 0.5;
this.context.addChild(bit);
}
}
this.addChild(this.context);
this.context.cacheAsBitmap = true;
this.context.width = egret.MainContext.instance.stage.stageWidth;
this.context.height = egret.MainContext.instance.stage.stageHeight;
this.context.touchEnabled = true;
this.context.addEventListener(egret.TouchEvent.TOUCH_BEGIN,this.click,this);
}
private click(evt:egret.TouchEvent):void
{
this.context.getChildAt(0).scaleX = 2;
console.log("click");
this.context.x += 10;
}
当我点击了这个Sprite之后,我希望第一张位图,能够横向拉伸2倍。但是,通过下面的截图你会发现,图像并没有修改。为了方便查看效果,我特意在点击事件中输出了click字符。
这说名了一个问题,cacheAsBitmap被启用后,其内部的可视化对象不在参与第三步与第四步操作。这里所谓的操作是指,当Main Loop遍历显示列表中元素的时候,认为Sprite内部就是一个Bitmap,而非60个。而这一个Bitmap是有引擎为你缓存出来的图像。
我们稍微修改一下代码,把设置cacheAsBitmap这行注释掉。你再来看一下效果。
private context:egret.Sprite = new egret.Sprite();
private createGameScene(): void {
egret.Profiler.getInstance().run();
for( var i:number=0; i<12;i++ )
{
for(var t:number=0;t<5;t++)
{
var bit:egret.Bitmap = new egret.Bitmap();
bit.texture = RES.getRes("image_png");
bit.x = 75t+41(i%2);
bit.y = 48*i;
bit.scaleX = 0.5;
bit.scaleY = 0.5;
this.context.addChild(bit);
}
}
this.addChild(this.context);
//this.context.cacheAsBitmap = true;
this.context.width = egret.MainContext.instance.stage.stageWidth;
this.context.height = egret.MainContext.instance.stage.stageHeight;
this.context.touchEnabled = true;
this.context.addEventListener(egret.TouchEvent.TOUCH_BEGIN,this.click,this);
}
private click(evt:egret.TouchEvent):void
{
this.context.getChildAt(0).scaleX = 2;
console.log("click");
this.context.x += 10;
}
非常明显的区别。
最后留一个问题,如果我像下面这样编写代码,最后看到效果如图,为什么会这样?
private context:egret.Sprite = new egret.Sprite();
private createGameScene(): void {
egret.Profiler.getInstance().run();
for( var i:number=0; i<12;i++ )
{
for(var t:number=0;t<5;t++)
{
var bit:egret.Bitmap = new egret.Bitmap();
bit.texture = RES.getRes("image_png");
bit.x = 75t+41(i%2);
bit.y = 48*i;
bit.scaleX = 0.5;
bit.scaleY = 0.5;
this.context.addChild(bit);
}
}
this.addChild(this.context);
this.context.cacheAsBitmap = true;
this.context.getChildAt(0).scaleX = 2;
console.log("click");
this.context.x += 10;
}
欢迎大家来Egret社区讨论,bbs.egret-labs.org