點陣圖快取

適時在複雜的向量內容使用點陣圖快取功能。

使用點陣圖快取功能即可達到最佳化。這項功能會快取向量物件,在內部將它顯示為點陣圖,並且使用該點陣圖進行顯示。結果會大幅改善顯示效能,但是它可能需要大量的記憶體。在複雜的向量內容 (例如複雜的漸層或文字) 使用點陣圖快取功能。

在包含複雜向量圖形 (例如文字或漸層) 的動畫物件開啟點陣圖快取功能以改善效能。不過,如果在顯示物件 (例如具有播放時間軸的影片片段) 上啟用點陣圖快取,會得到相反的結果。在每個影格上,執行階段必須升級快取的點陣圖,然後在螢幕上重新繪製它,這可能需要許多 CPU 週期。點陣圖快取功能只對於產生一次、不需更新就能使用的快取點陣圖才有好處。

如果您為 Sprite 物件開啟點陣圖快取,該物件便可在不需要執行階段重新產生快取點陣圖的情況下移動。變更物件的 x y 屬性不會導致重新產生快取的點陣圖。但是,對物件進行旋轉、縮放或變更 Alpha 值則會導致執行階段重新產生快取的點陣圖,進而影響效能。

備註: 但 AIR 與 Packager for iPhone 中的 DisplayObject.cacheAsBitmapMatrix 屬性則無此限制。透過使用 cacheAsBitmapMatrix 屬性,即可旋轉、縮放、傾斜和變更顯示物件的 Alpha 值,而不必觸發點陣圖重新產生。

快取的點陣圖所使用的記憶體,可能比一般影片片段實體還多。例如,如果在「舞台」上的影片片段為 250 x 250 像素,當快取它時,會使用大約 250 KB,而不是未快取的 1 KB。

下列範例涉及包含蘋果影像的 Sprite 物件。下列類別會附加到 apple 元件:

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(); 
        } 
    } 
}

程式碼會使用 Sprite 類別,而非 MovieClip 類別,因為並非每個蘋果都需要時間軸。為了獲得最佳的效能,請盡可能使用輕量型物件。接下來,會使用下列程式碼將類別實體化:

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); 
        } 
    } 
}

當使用者按一下滑鼠時,會建立蘋果而不會進行快取。當使用者按 C 鍵時 (按鍵碼 67),會將蘋果向量快取為點陣圖,並顯示在螢幕上。此技術可在 CPU 變慢時,大幅改善桌上型電腦與行動裝置上的顯示效能。

不過,雖然使用點陣圖快取功能可改善顯示效能,它有可能會快速地耗用大量的記憶體。只要一快取物件,就會將其表面擷取為透明的點陣圖並儲存在記憶體中,如下圖所示:

儲存在記憶體中的物件及其表面點陣圖

Flash Player 10.1 與 AIR 2.5 採用 濾鏡與動態點陣圖取消載入 中所述的相同方法來最佳化記憶體的使用方式。如果快取的顯示物件是隱藏的或在螢幕外,其點陣圖只要一段時間沒有使用就會從記憶體釋出。

備註: 如果顯示物件的 opaqueBackground 屬性設定為特定顏色,則執行階段會將顯示物件視為不透明。當與 cacheAsBitmap 屬性搭配使用時,執行階段會在記憶體中建立不透明的 32 位元點陣圖。Alpha 色版會設定為 0xFF 以改善效能,因為在螢幕上繪製點陣圖不需要透明效果。避免使用 Alpha 混合效果可加快顯示速度。如果目前的螢幕深度限制為 16 位元,則記憶體中的點陣圖將儲存為 16 位元影像。使用 opaqueBackground 屬性不會以隱含方式啟用點陣圖快取。

若要節省記憶體,請使用 cacheAsBitmap 屬性,並在每個顯示物件 (而非容器) 上啟用它。在容器上啟用點陣圖快取會讓記憶體中的最終點陣圖變大,這是為了建立尺寸為 211 x 279 像素的透明點陣圖。此影像使用大約 229 KB 的記憶體:

在容器上啟用點陣圖快取

此外,快取容器時如果有任何蘋果開始在影格上移動,您將面臨可能在記憶體中更新整個點陣圖的風險。在個別實體上啟用點陣圖快取,會在記憶體中快取六個 7 KB 的表面,這樣只會使用 42 KB 的記憶體:

檢視完整大小的圖形
在實體上啟用點陣圖快取

從顯示清單存取每個蘋果實體並呼叫 getChildAt() 方法,會將參考儲存在 Vector 物件中以便快速存取:

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); 
        } 
    } 
}

請記住,如果不在每個影格上旋轉、縮放或變更快取的內容,則點陣圖快取可改進顯示效能。不過,對不是在 X 與 Y 軸上轉移的任何變形而言,並不會改善顯示效能。在這些情況下,Flash Player 會更新顯示物件上每個變形的快取點陣圖副本。更新快取副本可能會導致高 CPU 使用率、效能變慢以及高電池用量。但 AIR 或 Packager for iPhone 中的 cacheAsBitmapMatrix 屬性則無此限制。

下列程式碼會變更移動方法中的 Alpha 值,它會變更每個影格上蘋果的不透明度:

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(); 
}

使用點陣圖快取會造成效能變慢。變更 Alpha 值會讓執行階段在每當修改 Alpha 值時,強制更新記憶體中快取的點陣圖。

使用濾鏡時必須有點陣圖,而這些點陣圖會在每次快取影片片段播放磁頭移動時隨之更新。因此,使用濾鏡會自動將 cacheAsBitmap 屬性設定為 true 。下圖說明動畫影片片段:

動畫影片片段

避免在動畫內容上使用濾鏡,因為它可能會造成效能問題。在下圖中,設計師加入投影濾鏡:

套用投影濾鏡的動畫影片片段

其結果是,如果播放影片片段中的時間軸,就必須重新產生點陣圖。如果內容不是以簡單 x 或 y 變形的方式進行修改,也必須重新產生點陣圖。每個影格都會強制執行階段重新繪製點陣圖,這將需要更多的 CPU 資源、造成效能變差,以及耗用更多的電池壽命。

在下列訓練影片中,Paul Trani 針對使用 Flash Professional 與 ActionScript 提供的範例會使用點陣圖最佳化圖形: