2013-08-30 33 views
0

我嘗試了Lee Brimlow的blitting教程系列和Rex Van der spuy的「閃光先進遊戲設計」中的技巧的組合AS3 Blitting比Movieclip慢。爲什麼?

我是一名開發人員,負責製作Flash中的網絡虛擬世界。我製作了一個電話應用程序(類似於盜竊汽車遊戲中的手機)。無論如何,當一個信息被髮送時,我們想要播放這個瘋狂的信封動畫,並圍繞它轉動。這是laggy(特別是在舊電腦上),所以我認爲這是一個很好的機會使用blitting。然而,blitting動畫實際上比普通的movieclip播放慢!這裏發生了什麼? blitting只對移動設備更好,而且在計算機上實際上更慢?也許我做錯了什麼。這裏是我的代碼:

//這部分發生在手機吧INITIALIZED

//**     
//---------------- Blitting stuff ---------------------------------- 
// add this bitmap stage to the display list so we can see it 
      _bitmapStage = new BitmapData(550, 400, true, 0xD6D6D6); 


     _phoneItself.addChild(new Bitmap(_bitmapStage)); 

     var _spritesheetClass:Class = getDefinitionByName("ESpritesheet_1") as Class; 
     _spritesheet = new _spritesheetClass() as BitmapData; 

     _envelopeBlit = new BlitSprite(_spritesheet, BlitConfig.envelopeAnimAry , _bitmapStage); 
     _envelopeBlit.x = -100; 
     _envelopeBlit.y = 0; 

     _envelopePlayTimer = new Timer(5, 0); 
     _envelopePlayTimer.addEventListener(TimerEvent.TIMER, onEnterTimerFrame); 
     _envelopeBlit.addEventListener("ENV_ANIM_DONE", onEnvAnimFinished); 

//一個「BlitSprite」是一個類,我做了。它看起來像這樣:

package com.fs.util_j.blit_utils 
{ 
    import flash.display.BitmapData; 
    import flash.events.Event; 
    import flash.events.EventDispatcher; 
    import flash.geom.Point; 
    import flash.geom.Rectangle; 

    public class BlitSprite extends EventDispatcher 
    { 

     private var _fullSpriteSheet:BitmapData; 
     private var _rects:Array; 
     private var _bitmapStage:BitmapData; 

     private var pos:Point = new Point(); 
     public var x:Number = 0; 
     public var y:Number = 0; 

     public var _animIndex: 

int = 0; private var _count:int = 0;

public var animate:Boolean = true; 
    private var _whiteTransparent:BitmapData; 
    private var _envelopeAnimAry:Array; 
    private var _model:Object; 



    public function BlitSprite(fullSpriteSheet:BitmapData, envelopeAnimAry:Array, bitmapStage:BitmapData, model:Object = null) 
    { 
     _fullSpriteSheet = fullSpriteSheet; 
     _envelopeAnimAry = envelopeAnimAry; 
      _bitmapStage = bitmapStage; 
      _model= model; 

      init(); 
     } 

     private function init():void 
     { 
//   _whiteTransparent = new BitmapData(100, 100, true, 0x80FFffFF); 

      this.addEventListener("ENV_ANIM_DONE", onEvnAnimDone); 

     }  

     protected function onEvnAnimDone(event:Event):void 
     { 

     }  

     public function render():void 
     { 

//   pos.x = x - _rects[_animIndex].width*.5; 
//   pos.y = y - _rects[_animIndex].width*.5; 

//   if (_count % 1 == 0 && animate == true) 
//   { 

//    trace("rendering"); 

       if (_animIndex == (_envelopeAnimAry.length - 1)) 
       { 
//     _animIndex = 0; 
        dispatchEvent(new Event("ENV_ANIM_DONE", true)); 
        animate = false; 
//     trace("!!!!animate over " + _model.animOver); 

//     if (_model != null) 
//     { 
//      _model.animOver = true; 
//     } 

//     trace("!!!!animate over " + _model.animOver); 

       } 

       else 
       { 
        _animIndex++; 
       } 


       pos.x = x + _envelopeAnimAry[_animIndex][1]; 
       pos.y = y + _envelopeAnimAry[_animIndex][2]; 


       _bitmapStage.copyPixels(_fullSpriteSheet, _envelopeAnimAry[_animIndex][0], pos, null, null, true); 

     } 



    } 
} 




// THIS PART HAPPENS WHEN PHONE'S SEND BUTTON IS CLICKED 


       _envelopeBlit.animate = true; 
       _envelopeBlit._animIndex = 0; 
       _darkSquare.visible = true; 
       _envelopePlayTimer.addEventListener(TimerEvent.TIMER, onEnterTimerFrame); 
       _envelopePlayTimer.start(); 

該機還採用BlitConfig有關spritesheet吐出由TexturePacker

package com.fs.pack.phone.configuration 
    { 
     import flash.geom.Rectangle; 

     public final class BlitConfig 
     { 




      public static var _sending_message_real_20001:Rectangle = new Rectangle(300,1020,144,102); 
      public static var _sending_message_real_20002:Rectangle = new Rectangle(452,1012,144,102); 
      public static var _sending_message_real_20003:Rectangle = new Rectangle(852,852,146,102); 
      public static var _sending_message_real_20004:Rectangle = new Rectangle(2,1018,146,102); 
      public static var _sending_message_real_20005:Rectangle = new Rectangle(702,822,148,102); 
. 
. 
. 
public static var _sending_message_real_20139:Rectangle = new Rectangle(932,144,1,1); 

    public static var envelopeAnimAry:Array = [ 

       // rectangle, x offset, y offset 
      [ _sending_message_real_20001, 184,155], 
      [ _sending_message_real_20002, 184,155], 
      [ _sending_message_real_20003, 183,155], 
      [ _sending_message_real_20004, 183,155], 
. 
. 
. 
[ _sending_message_real_20139, 0,0] 
     ] 



     public function BlitConfig() 
     { 
     } 


    } 
} 

回答

0

編輯存儲的信息: 知道,這不是手機,我的回答下面是無關緊要的。不過,如果將來有人在移動設備上遇到麻煩,那麼我將保留在那裏。

關於這個特定的問題,你每5ms運行你的計時器。首先,定時器準確的最低範圍大於15ms,因此永遠不會是可行的解決方案。對於任何與在舞臺上顯示有關的定時器,您都應該使用從來沒有做到這一點。 (1000/stage.framerate。對於30fps應用程序〜40ms)

對於blitting,目標是減少計算和渲染。現在你已經設置了這種方式,看起來你每5ms就有一次閃電。這實際上是MovieClip渲染的8倍以上。你應該減少你blit的頻率。只有在變更實際上超出翻譯範圍時纔會這樣做。任何更多的時候這樣做比是矯枉過正和原因,它是如此之慢(再次,創建位圖是緩慢的)


一般情況下,你不希望在移動應用程序的AIR做塊(我假設自從您提到手機正在初始化以來,您正在這樣做)。我不確定是否可以使用其他/本機SDK來執行此操作,但在AIR中避免它。

本質上,它歸結爲blitting如何工作。 Blitting需要屏幕截圖並將其顯示在舞臺上而不是實際的物體上。一般來說,這很好。這意味着您的顯示對象,特別是渲染速度慢的矢量,必須渲染得少得多。動畫效果尤其好,因爲每次以任何方式翻譯對象時都傾向於重新渲染,而不是位圖。

但是,在移動平臺上創建該位圖的速度非常慢。我從來沒有研究過SDK是如何創建Bitmaps的,但它並不能有效地實現它(它經常讓我想知道它是否逐個像素)。在桌面上,這通常很好。有足夠的CPU和大量內存來快速實現這一點。然而,在手機上,那個奢侈品目前還沒有。所以當你blit並創建該位圖時,需要一段時間來運行該過程。

問題在高分辨率屏幕上加劇。今年1月至5月開發的應用程序有選擇地使用blitting在GPU加速環境中使用濾鏡。在iPad 2上,blitting將我的應用程序從30fps提高到〜24fps。沒什麼大不了的,用戶不會注意到的。然而,在具有視網膜顯示器的iPad 3上,它下降到10fps。當你考慮這個問題時,這很有意義,因爲視網膜iPad的像素數量是非視網膜iPad的4倍。

如果你想使用阻擊器在移動,我推薦幾件事情:

  1. 使用GPU渲染模式。沒有它,你就沒有機會。請注意,至少在AIR 3.7之前,GPU模式中不支持濾鏡。我不確定這是否仍然如此。您應該避免在移動設備上使用濾鏡,儘管它們渲染速度很慢
  2. 請確保測試發佈模式應用程序。根據構建設置,調試模式和發佈模式應用程序之間的差異可能很大,特別是在iOS上。我剛剛開發的一款應用程序花費了2-3秒的時間在調試模式下創建一個新的Flex View,以小於一幀(〜40ms)在iPhone 4上以釋放模式進行操作。
  3. 謹慎使用blitting。只有在絕對必要的情況下才能做到這一點
  4. 尋找方法來簡化您的顯示列表。有一個有40個孩子的對象很容易創建一個按鈕。相反,尋找方法將其簡化爲更少的對象和更少的過濾器(即使刪除過濾器也需要添加另一個對象)。我不相信這會有助於實際的blitting過程,但它應該有助於渲染對象。

因此,一般情況下,在移動設備上少量使用blitting,因爲位圖創建速度較慢。

+0

它不在AIR中。這只是將swfs上傳到服務器上以便在瀏覽器中播放,並且是的,它在速度非常快的計算機上速度較慢。 – Fans

+0

然後,你說「當手機初始化時這個部分發生了變化」絕對是欺騙性的。在答案的頂部看到我的編輯 –

+0

是的,對不起。我通常用init()方法啓動每個類。在構造函數的內部,「初始化電話」基本上意味着當它被加載到世界中但在用戶進行任何交互之前所做的所有事情。它確實在說它是一個WEB在線虛擬世界。 – Fans