萬盛學電腦網

 萬盛學電腦網 >> 圖文處理 >> Flash教程 >> Flash開發移動設備技巧

Flash開發移動設備技巧

   隨著Adobe Flash技術向iOS, Android, BlackBerry這三大移動平台的進軍,必然將湧現出大量的基於Flash Player和AIR的手機和平板應用。然而移動設備的硬件限制,對Flash的運行效率產生了很大的挑戰,所以如何優化代碼成為Flash移動開發的核心問題。另外、基於觸摸的全新交互方式和移動設備上獨有的系統環境,也讓移動平台上的Flash開發多了許多機會和功能點。今天我就給大家簡單介紹一下我在近期總結的一些經驗和技巧。

    GPU渲染 

  移動設備的CPU和電腦上的CPU相差甚遠,所以要運行大量動畫(尤其是矢量動畫),則最好要使用GPU來渲染。Flash Profession CS5在針對Android或者iOS項目的發布設置中可以選擇是否使用GPU硬件加速。

  不要大量使用位圖緩沖

  很多人認為使用位圖(包括cacheAsBitmap) 要比使用矢量圖要好,實際情況並非如此,一味單純地使用圖片也有弊端。論據之一是位圖在縮放時顯示不佳,我相信大家都有這樣的體會;另外,如果位圖元素被用在了移動、縮放、旋轉等動畫之內,那麼它的運行效率不是提高反而下降了不少。而且在在使用GPU加速情況下,使用位圖緩沖會讓畫面鋸齒增加,遠不如矢量圖的清晰度高。但是如果用GPU渲染內容較多的動態文本,則必須使用位圖緩沖。

  大量文本的渲染

  正如上點所說,GPU對處理動態矢量文本是非常之慢,原因就是GPU對矢量圖采用了鑲嵌渲染(tessellate),所謂鑲嵌渲染就是將矢量圖分為若干個小三角形,根據它們的頂點信息分別繪制再鑲嵌成整體的形狀(如同Molehill的頂點著色器),鑲嵌渲染對矢量圖的裁剪數量是依據其本身的形狀,如果矢量圖的拐點較多,那麼就會裁剪出較多的三角形。因為動態文本含有大量的拐點,所以會產生很多的三角形鑲嵌計算,而如果文本含有大量內容則會帶來災難性的結果。所以對大量文本需要使用位圖緩沖來處理,使用cacheAsBitmap = true,讓GPU按照文本的寬高來均勻地裁剪三角形,這樣會使運行速度非常流暢。在做其他矢量圖形的時候同樣需要注意這一點,盡量避免彎曲而且狹長的圖形,這讓GPU繪制很多三角形從而拉低運行效率。

  (如上圖,"鑲"字的偏旁部分所示的是對矢量圖鑲嵌,"嵌"字示意的是對位圖鑲嵌)

  矢量圖的幀滯後現象

  這是我在制作手機游戲過程中發現的一個現象,前提是使用GPU加速,如果在第二幀要在舞台上首次顯示一個復雜的矢量場景,那麼在第一幀會有一個很明顯的停頓,這也是由於GPU的鑲嵌造成的。在我的例子中,前一個場景在做淡出效果,淡出到M幀應該是純黑的畫面,同時在M幀顯示一個新的場景。由於GPU鑲嵌造成的運算,使得前一個場景在M-1幀停頓了大約0.2-0.5秒,這時候畫面並非純黑,所以很明顯感覺到停頓。我最後的處理方式是將前一個場景的退出和後一個場景的進入改為異步連接,在中間使用一個timer來等待100毫秒,這樣肉眼就絲毫感覺不到停頓地存在。

  不要使用特殊效果

  對移動設備來說,無論使用CPU還是GPU,在某些效果地渲染上都尚未達到理想的結果。比如在動畫上方蓋一個很大的透明漸變層,會導致幀頻極具下降至10以下;如果采用了濾鏡,哪怕只有簡單的模糊濾鏡,都會讓幀頻下降到個位數,GPU下甚至根本就不支持濾鏡的渲染。GPU同樣不支持的還有部分layer,alpha,erase,overlay,hardlight,lighten,darken這些圖形疊加效果以及著色器PixelBender。

  設備鍵盤的使用

  和電腦上獲取鍵盤事件的原理一樣,我們可以給應用程序添加一個偵聽器來捕獲KeyboardEvent,從而定義移動設備上的按鍵事件。從AIR2.5以後,我們可以使用Keyboard裡的一些針對移動設備的key code(如Keyboard.BACK,Keyboard.MENU,Keyboard.SEARCH),如下面的例子:

  stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);function onKeyDown(pEvent:KeyboardEvent):void{ if(pEvent.keyCode == Keyboard.BACK){ //do something here }}

  另外有一點可能比較有用,我們可以利用Event的preventDefault方法來阻止一些鍵盤事件的默認行為。比如如果我們不希望按了返回鍵之後跳出當前應用程序到桌面,我們可以在上面的例子裡加一行代碼:

  stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);function onKeyDown(pEvent:KeyboardEvent):void{ if(pEvent.keyCode == Keyboard.BACK){ pEvent.preventDefault(); //do some checking here }}

  跨平台應用程序的判斷

  對於一個打算發布在多個平台的應用程序,我們當然希望使用相同的代碼,避免為每個平台單獨開發。桌面應用和移動應用在交互方式上是不一樣的,桌面上更多的是采用鼠標操作,而移動上更多的是觸摸和手勢。這兩種方式的API是不一樣的,鼠標使用的是MouseEvent,觸摸和手勢則用TouchEvent和GestureEvent。所以在定義交互的時候我們需要判斷當前運行的平台是什麼樣的交互模式:

  if(Capabilities.touchscreenType == TouchscreenType.FINGER){ //定義觸摸和手勢交互}else{ //定義鼠標交互}

  除了交互方式的不同,移動設備上的AIR與桌面端AIR一樣,有對原生系統的訪問API比如NativeApplication類。舉一個例子,在浏覽器中運行的應用程序不用去考慮關閉應用程序,但是AIR則經常會設計一個自我關閉的功能。這個功能需要用到NativeApplication.exit()方法,可是NativeApplication類只存在於AIR運行時而非Flash Player中,所以如果在跨平台的代碼中直接導入NativeApplication則會在編譯浏覽器版本時報錯,即使使用AIR的發布功能將SWF發布成功,那麼在浏覽器中運行這個SWF也會報未知對象的錯誤。

  我的解決方法是使用反射來解決編譯時的導入問題,而使用Exception來解決運行時的錯誤:

  try{ //AIR版本 var myClass:Class = getDefinitionByName("flash.desktop.NativeApplication") as Class; nativeApplication = myClass.nativeApplication; nativeApplication.addEventListener(Event.DEACTIVATE, deactivateHandler); nativeApplication.addEventListener(Event.ACTIVATE, activateHandler); nativeApplication.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);}catch(e:Error){ //浏覽器版本}

  狀態保存

  Android和iOS平台與電腦平台一樣,支持SharedObject本地存儲功能,所以可以在所有平台使用一樣的代碼來對應用程序狀態(比如游戲進度、應用的偏好設置)進行保存和讀取。如果你對SharedObject的保存和讀取不是很清楚,下面的代碼可以幫助你了解。

  訪問本地SharedObject數據

  //blabla是自定義的字符串,本地存儲文件會以它來命名。var so:SharedObject = SharedObject.getLocal("blabla");//so.data是SharedObject的只讀屬性,可以作為容器存放需要在本地存儲的數據變量,(注意,本地存儲的數據有大小限制,最多為100KB)so.data.savedata = "What a nice function!!";//生成本地存儲文件so.flush();

  如果要清除特定的本地存儲文件,可以用下面的代碼來實現:

  var so:SharedObject = SharedObject.getLocal("blabla");so.clear();

  應用程序狀態判斷

  舉一個例子,如果你正在手機上玩一個有背景音樂的游戲,突然被來電打斷,那麼你當然不希望在通話的時候同時會聽到游戲的背景音樂。或者你按了Back鍵回到了桌面,那麼游戲也是理所應當被靜音的。這就需要對應用程序的運行狀態比如Activated, Deactivated添加偵聽:

  nativeApplication.addEventListener(Event.DEACTIVATE, deactivateHandler);nativeApplication.addEventListener(Event.ACTIVATE, activateHandler);function activateHandler(pEvent:Event):void{}function deactivateHandler(pEvent:Event):void{}

  另外還有一些增加用戶體驗上的經驗,比如如何處理被觸摸控制的物體到達屏幕邊界時的彈性緩沖運動,都可以用基本的ActionScript方法來進行處理和運算,這裡不做詳細介紹。

  補充兩點:

  1.避免使用Timer,

  2.在一些靜態圖片的時候可以降低幀率

 

copyright © 萬盛學電腦網 all rights reserved