Bitmappscachning

Använd bitmappscachning när det är möjligt för komplext vektorinnehåll.

Du kan uppnå en bra optimering med hjälp av funktionen för bitmappscachning. Den här funktionen cache-lagrar ett vektorobjekt, återger det som en bitmapp internt och använder sedan bitmappen för återgivningen. Detta kan resultera i en avsevärd prestandaförbättring, men det kan kräva mycket minneskapacitet. Använd funktionen för bitmappscachning när du har komplext vektorinnehåll, såsom avancerade övertoningar eller text.

Att aktivera bitmappscachning för ett animerat objekt som innehåller komplex vektorgrafik (till exempel text eller övertoningar) leder till bättre prestanda. Om bitmappscachning är aktiverat för ett visningsobjekt, t.ex. ett filmklipp med en tidslinje som spelas, får du dock motsatt resultat. För varje bildruta måste körningsmiljön uppdatera den cachelagrade bitmappen och sedan rita om den på skärmen, vilket kräver många processorcykler. Funktionen för bitmappscachning är att föredra endast när den cachelagrade bitmappen kan genereras en gång och sedan användas utan att den behöver uppdateras.

Om du aktiverar bitmappscachning för ett Sprite-objekt kan objektet flyttas utan att den cachelagrade bitmappen behöver genereras om. Om du ändrar egenskaperna x och y för objektet leder detta inte till någon omgenerering. Om du däremot försöker rotera det, skalförändra det eller ändra dess alfavärde omgenereras den cachelagrade bitmappen, vilket resulterar i sämre prestanda.

Obs! Egenskapen DisplayObject.cacheAsBitmapMatrix , som finns i AIR och i Packager for iPhone, har inte den här begränsningen. Om du använder egenskapen cacheAsBitmapMatrix kan du rotera, skala, skeva och ändra alfavärdet för ett visningsobjekt utan att utlösa en omgenerering av bitmappen.

En cache-lagrad bitmapp kan använda mer minne än en vanlig filmklippsinstans. Om exempelvis filmklippet på scenen är 250 x 250 pixlar kommer det när det cache-lagras att uppta cirka 250 kB, i stället för 1 kB om det inte cache-lagras.

I följande exempel används ett Sprite-objekt som innehåller en bild av ett äpple. Följande klass kopplas till äppelsymbolen:

package org.bytearray.bitmap 
{     
    import flash.display.Sprite; 
    import flash.events.Event; 
     
    public class Apple extends Sprite 
    { 
        private var destinationX:Number; 
        private var destinationY:Number; 
         
        public function Apple () 
        { 
            addEventListener(Event.ADDED_TO_STAGE,activation); 
            addEventListener(Event.REMOVED_FROM_STAGE,deactivation);     
        } 
         
        private function activation(e:Event):void  
        { 
            initPos();     
            addEventListener (Event.ENTER_FRAME,handleMovement);     
        } 
         
        private function deactivation(e:Event):void  
        { 
            removeEventListener(Event.ENTER_FRAME,handleMovement);     
        } 
         
        private function initPos():void 
        { 
            destinationX = Math.random()*(stage.stageWidth - (width>>1)); 
            destinationY = Math.random()*(stage.stageHeight - (height>>1)); 
        } 
         
        private function handleMovement(e:Event):void  
        { 
            x -= (x - destinationX)*.5; 
            y -= (y - destinationY)*.5; 
             
            if (Math.abs(x - destinationX) < 1 && Math.abs(y - destinationY) < 1) 
                initPos(); 
        } 
    } 
}

I koden används Sprite-klassen i stället för MovieClip-klass eftersom en tidslinje inte behövs för varje äpple. Du ska för att få bästa prestanda använda det enklast möjliga objektet. Därefter instansieras klassen med följande kod:

import org.bytearray.bitmap.Apple; 
 
stage.addEventListener(MouseEvent.CLICK,createApples); 
stage.addEventListener(KeyboardEvent.KEY_DOWN,cacheApples); 
 
const MAX_NUM:int = 100; 
var apple:Apple; 
var holder:Sprite = new Sprite(); 
 
addChild(holder); 
 
function createApples(e:MouseEvent):void 
{ 
    for (var i:int = 0; i< MAX_NUM; i++) 
    { 
        apple = new Apple(); 
         
        holder.addChild(apple); 
    } 
} 
 
function cacheApples(e:KeyboardEvent):void 
{ 
    if (e.keyCode == 67) 
    { 
        var lng:int = holder.numChildren; 
         
        for (var i:int = 0; i < lng; i++) 
        { 
            apple = holder.getChildAt (i) as Apple; 
             
            apple.cacheAsBitmap = Boolean(!apple.cacheAsBitmap); 
        } 
    } 
}

När användaren klickar med musen kommer äpplena att skapas utan att cache-lagras. När användaren trycker på C-tangenten (tangentkod 67), cache-lagras äppelvektorerna som bitmappar och visas på skärmen. Den här tekniken innebär avsevärda prestandaförbättringar för återgivningen, både på datorer och mobilenheter när processorkapaciteten är låg.

Funktionen för bitmappscachning förbättrar återgivningsprestandan, men den kan snabbt lägga beslag på mycket av minneskapaciteten. Så snart ett objekt har cache-lagrats kommer dess yta att hämtas som en genomskinlig bitmapp och sparas i minnet, vilket visas i följande bild:

Objekt och dess bitmappsyta sparas i minnet.

I Flash Player 10.1 och AIR 2.5 har minnesanvändningen optimerats på samma sätt som beskrivs i Filter och borttagning av dynamiska bitmappar . Om ett cachelagrat visningsobjekt är dolt eller finns utanför skärmen kommer dess bitmapp att släppas från minnet om den inte används på ett tag.

Obs! Om egenskapen opaqueBackground för visningsobjektet har ställts in på en viss färg tolkar körningsmiljön visningsobjektet som ogenomskinligt. När det används med egenskapen cacheAsBitmap skapas en ogenomskinlig 32-bitars bitmapp i minnet. Alfakanalen anges som 0xFF, vilket förbättrar prestandan eftersom ingen genomskinlighet krävs för att rita bitmappen på skärmen. Genom att alfablandningen undviks kommer återgivningen att ske ännu snabbare. Om det aktuella skärmdjupet är begränsat till 16 bitar, kommer bitmappen i minnet att sparas som en 16-bitars bild. Om du använder egenskapen opaqueBackground innebär detta inte direkt att bitmappscachning aktiveras.

Om du vill spara minne ska du använda egenskapen cacheAsBitmap och aktivera den för varje visningsobjekt i stället för i behållaren. Om bitmappscachning aktiveras i behållaren kommer den slutliga bitmappen att bli mycket större i minnet och en genomskinlig bild med måtten 211 x 279 pixlar kommer att skapas. Bilden använder cirka 229 kB av minnet:

Visa grafik i full storlek
Aktivera bitmappscachning för behållare

Dessutom riskerar du genom att cache-lagra behållaren att hela bitmappen uppdateras i minnet om äpplet börjar röra sig i en bildruta. Om du aktiverar bitmappscachning för enskilda instanser kommer sex 7-kB-ytor att cache-lagras i minnet, vilket innebär att endast 42 kB av minnet används:

Visa grafik i full storlek
Aktivera bitmappscachning för instanser

Genom att ha åtkomst till varje äppelinstans genom visningslistan och anropa metoden getChildAt(), kommer referenser att sparas i ett Vector-objekt och ge enklare åtkomst:

import org.bytearray.bitmap.Apple; 
 
stage.addEventListener(KeyboardEvent.KEY_DOWN, cacheApples); 
 
const MAX_NUM:int = 200; 
var apple:Apple; 
var holder:Sprite = new Sprite(); 
 
addChild(holder); 
 
var holderVector:Vector.<Apple> = new Vector.<Apple>(MAX_NUM, true); 
 
for (var i:int = 0; i< MAX_NUM; i++) 
{ 
    apple = new Apple(); 
     
    holder.addChild(apple); 
     
    holderVector[i] = apple; 
} 
 
function cacheApples(e:KeyboardEvent):void 
{ 
    if (e.keyCode == 67) 
    { 
        var lng:int = holderVector.length 
         
        for (var i:int = 0; i < lng; i++) 
        { 
            apple = holderVector[i]; 
             
            apple.cacheAsBitmap = Boolean(!apple.cacheAsBitmap); 
        } 
    } 
}

Tänk på att bitmappscachning förbättrar återgivningen om det cache-lagrade innehållet inte roteras, skalförändras eller ändras i varje bildruta. Emellertid kommer alla omformningar, förutom de som gäller för förflyttningen på x- och y-axlarna, inte att förbättra återgivningen. I dessa fall kommer den cache-lagrade bitmappskopian att uppdateras för varje omformning som inträffar i visningsobjektet. Uppdatering av den cache-lagrade kopian kan resultera i hög processoranvändning, sämre prestanda och hög batteriförbrukning. Även här gäller att egenskapen cacheAsBitmapMatrix , som finns i AIR och Packager for iPhone, inte har denna begränsning.

I följande kod ändras alfavärdet i rörelsemetoden, vilket innebär att opaciteten ändras för äpplet i varje bildruta:

private function handleMovement(e:Event):void  
{ 
        alpha = Math.random(); 
        x -= (x - destinationX)*.5; 
        y -= (y - destinationY)*.5; 
             
        if (Math.abs(x - destinationX) < 1 && Math.abs(y - destinationY) < 1) 
            initPos(); 
}

När du använder bitmappscachning minskas prestandan. Genom att ändra alfavärdet tvingas körningsmiljön att uppdatera den cachelagrade bitmappen i minnet så fort alfavärdet ändras.

Filter förlitar sig på bitmappar som uppdateras när spelhuvudet för ett cache-lagrat filmklipp flyttas. Detta innebär att om du använder ett filter så kommer värdet för egenskapen cacheAsBitmap automatiskt att ställas in som true . I följande bild illustreras ett animerat filmklipp:

Animerat filmklipp

Undvik att använda filter för animerat innehåll eftersom detta kan leda till prestandaförsämringar. I bilden nedan har designern lagt till ett skuggfilter:

Animerat filmklipp med skuggfilter

Detta resulterar bland annat i att bitmappen måste genereras om, om tidslinjen i filmklippet spelas upp. Bitmappen måste även genereras om när innehållet ändras på något annat sätt än genom en enkel x- eller y-omformning. För varje bildruta måste bitmappen ritas om, vilket kräver ytterligare processorresurser, leder till sämre prestanda och förbrukar batterikapacitet.

I följande videofilm visar Paul Trani exempel på hur Flash Professional och ActionScript kan användas för att optimera grafik med bitmappar: