ActionScript 3.0程式最佳化(一)以及Vector資料類型簡介
譯∕趙英傑
本文摘譯自Armand Niculescu撰寫的AS3 Performance Optimization,筆者再加註一段Vector資料類型的說明。
多數的Flash應用程式都不需要替程式做最佳化(對岸稱為「优化」)處理,所以最好把開發時間花在其他方面。通常只有像下列程式在執行效能上遇到瓶頸時,才需要做最佳化處理:
- 3D動畫
- 複雜的物理運算
- 編碼(encoding)和加密(encryption)
- AI(人工智慧,如:最佳路徑搜尋)
不必太早考量最佳化
不要在著手編寫程式時,就想著如何最佳化程式。這是非常普遍的錯誤,當你開始製作專案時,應該要集中精力解決功能面的問題,而不是最佳化。應該要撰寫清晰的程式碼以及說明文件,並且確保程式能正常運作而非快速執行。大型的應用程式都會在開發期間發現一些問題(bug),而且經常會為了解決程式問題而延長除錯(debug)的時間。
始終設定變數的類型
最佳化的首要技巧就是始終替變數設定資料類型。這對於處理陣列元素的速度提升尤其顯著,因為ActionScript的陣列元素可以儲存任意類型的資料,而Flash內部的AVM(ActionScript虛擬機器)勢必要在處理它們之前做一些確認工作。
以底下的程式片段為例:
var crtPiece:int = movesArray[i].piece;
如果將它改寫成:
var crtMove:Move = movesArray[i]; var crtPiece:int = crtMove.piece;
將能獲得顯著的速度提升。同樣地,底下的程式片段:
var element:int = matrix[i][j];
可以被改寫成:
var row:Array = matrix[i]; var element:int = row[j];
此外,假定用戶採用Flash Player 10,你可以把上面的兩個例子分別用Vector(參閱下文「Vector資料類型簡介」一節說明)改寫成:
var movesArray:Vector.<Move>;
以及:
var matrix:Vector.<Vector.<int>>;
這樣就不需要多寫一行程式了。
附帶說明,假如你已經採用改寫的Array版本,就不需要改成Vector的形式,因為兩者的執行效率差不多。
不要使用常數
這是我從 Adobe 的 Flash Player 工程師那裡得到的技巧。我總認為當編譯器遇到底下的程式碼定義時:
public const NAME:String = "foo";
將會把其中的常數替換成指定的數值。不過,事實並非如此。
常數有助於讓程式碼保持乾淨與可讀性,所以我之前才說只有在絕對必要時,再著手最佳化程式。
在製作棋盤遊戲時,我使用常數來儲存一些數值,例如:WHITE_PAWN,甚至用常數記錄棋格(如:A1或H8)。若直接用資料值取代常數,將會降低程式的可讀性,例如:if (pieceType==3) or if (targetSquare==7) 並不直觀易讀,但是將能顯著地改善運算效能。
降低呼叫函數的次數
這是另一個痛苦的抉擇。我在多年前看過一段C程式碼,不了解為何程式設計師要定義一些複雜的巨集(macro),像是:
#define MIN(a,b) ((a)<(b) ? (a) : (b))
而不寫成函數。
這是因為巨集比較快。如果你需要呼叫一個簡單的函數100,000次,把函數內容直接放在程式內執行,會比較快。尤其是Math類別的函數。你可以把底下的敘述:
var x:int = Math.min(a,b)
改寫成:
var x:int = (a<b) ? a : b;
每當我刪掉了一些執行轉換或者簡單數學運算的簡短函數(1-2行)後,運算速度就增加約 10 – 15%。
同樣地,最好也不要使用Array的方法,像是push(), pop(), shift()或unshift();你可以多寫一點程式碼來換得較好的執行效能。
使用int(整數)類型以及bitwise(位元)運算子
處理整數資料時,請使用int。unit 並不會提升陣列索引的速度,因此,除非你真的需要使用 uint,否則就用 int。
bitwise(位元)運算子比起一般的數學操作運算,快了2到10倍。底下的乘、除運算:
var x:int = a*2; var y:int = b*16; var z:int = c/4;
可改寫成:
var x:int = a << 1; //2^1 = 2; var y:int = b << 4; //2^4 = 16; var z:int = c >> 2; //2^2 = 4;
餘除(modulo,也就是 % 運算子)的運算式:
if (n % x == 0)
可改寫成:
if (n & (x-1) == 0)
預先計算∕暫存結果
Math類別的方法,像sin(), ln(), sqrt()的效能不佳,而且程式可能需要一再使用到這些相同的數值,這個時候,你可以先儲存這些計算結果,讓程式以「查表」的方式取得值。例如,把Math.sin()函數的值存入sine陣列,需要計算Math.sin(25)的值時,只要讀取sine[25]的值即可。
Vector資料類型簡介
簡單的說,Vector(直譯為「向量」)就是具有資料類型設定的陣列(Array),就語法而言,除了宣告變數的指令格式不同之外,Vector提供的方法(method)和陣列是一樣的。從功能面來看,Vector 和陣列的兩個主要不同點在於,Vector 類型可以設定成固定大小;陣列資料允許元素中間有空白的元素,而Vector的每個索引元素都必須要有值(或是 null)。最後,Flash Player 10或更新版本才支援Vector類型資料。
Vector類型資料的宣告語法範例如下,它採用後設資料類型宣告,緊接在Vector類型後面加上一個點(.),再用小於和大於符號標示資料格式(如:int, String,…):
var intVec:Vector.<int> = new Vector.<int>();
上面的敘述宣告了一個叫做 intVec 的Vector類型變數,其元素只能是 int(整數)類型;底下的敘述則宣告了一個長度固定為10的Vector變數:
var intVec:Vector.<int> = new Vector.<int>(10, true);
Vector的操作方式和陣列一樣,例如,在intVec的第0個元素存入100的敘述如下:
intVec[0] = 100;
關於 Vector 變數的其他說明,請參閱 Adobe 的線上說明文件。
一個好的flash程式就是當完成swf檔的時候,檔案小並且執行速度快,老師補上這些解說很實用。謝謝^^
請教老師一個問題為什麼swf匯入GIF動畫圖片都會變成靜止不動的圖片,無論是2.0或3.0的語法都一樣?
雖然flash3.0的功能比較多,但是感覺上flash2.0的程式比3.0好用,例如我將多個影音swf匯入同一個影片片段的時候,先匯入swf1再來匯入swf2的時候,swf1的影像會消失但swf1的聲音卻不會消失,造成影片片段出現swf2的影像和聲音外加swf1的聲音,flash2.0我將同一個影片片段放在多個影格舞台裡,執行載入swf則不會有這個問題?我有使用Loader.unload();這個語法清除載入的資料。
印象中,Flash會在製作階段將匯入的GIF動畫裡的每個畫面轉換成關鍵影格。所以,也許要先將它們匯入之後再包裝成影片片段。
聲音不會消失的問題我好像沒遇過,除非它被後來載入的物件遮蓋。不過,如果只是為了保留背景音效,最好個別載入。
thanks,
jeffrey
不好意思應該說載入GIF圖片到影片片段會出現我上述說的問題。
老師我想學習PHP程式,有比較好入門的書籍嗎?
載入動態GIF圖片,我以前沒有測試過,改天試試看。至於PHP的入門書,我可以推薦我自己寫的「碼上就會–Dreamweaver CS3、 PHP、 My SQL 與 AJAX」嗎(https://swf.com.tw/?p=103)?我看到有經銷商在網拍上賣399。 😉
載入動態GIF圖片這是個很棒的東西,可以用在很多地方,只可惜的是載入後就變靜態圖了= =老師有空試試吧!
老師推薦的書我的居住地屏東找不到一本來翻翻看,如果我的程度看的懂那當然是買老師的書。
網拍賣399…哈!!那老師你620賺粉大呦!!(^(00)^)
請問PHP程式要用什麼軟體寫呢?
你誤會大了…作者大多是領版稅的,書籍出版包括許多開銷,例如:紙張、印刷、裝訂、光碟、美術編排與封面設計、編輯校訂、通路(包含運輸與書店上架)、行銷以及公關、倉儲…等等的費用,作者的版稅只佔其中的一小部分。
PHP程式編輯器挺多的,除了Dreamweaver之外,其他知名的編輯列表,請參閱維基百科的這篇文章:http://en.wikipedia.org/wiki/List_of_PHP_editors
和老師開玩笑的啦
出書本來就很辛苦,又遇上現在景氣不好。
常來麻煩老師感謝您熱心的解答^^:wink:
老師請問flash2.0有這種網頁透明框架的組件http://www.flashextensions.com/products/iflash.php
那flash3.0也有這種網頁透明框架的組件嗎?
如果有該如何取得?
動態文字欄位裡的文字,若要用程式改變顯示的字體該怎麼寫?
例如系統預設字體是(王漢宗細黑體)我要用程式改變成華康方圓體?
我不確定有沒有AS3.0版,不過那個網站有提供原始碼下載。它其實就是把原本放在網頁裡的JavaScript和iframe標籤包在Flash影片裡面。
設定文字欄位的文字格式可透過TextFormat類別,例如:
var textFormat:TextFormat = new TextFormat();
textFormat.font = “Verdana”; // 設定成 Verdana字體
textFormat.color = 0xFF0000; // 指定成紅色
t_txt.setTextFormat(textFormat); // 套用在 t_txt欄位上
不過我記得中文字體的支援程度不好(未曾在Flash Player 10測試過)。另一個方法是透過CSS樣式表來設定。
老師你教我的語法用在AS3.0成功了,不過很奇怪flash軟體好像會挑同屬性的字體程式才能變換,例如文字欄位設定華康童童體W5程式只會挑後面同樣有W5的字體才能變換,如果是像這樣華康童童體W5(p)程式也會挑字體後面有W5(p)的其他字體才會變換?
煩請老師AS2.0的設定文字欄位的文字格式程式寫法,可以也傳授給我嗎?
感激不盡^^
老師flash程式可以控制列表機,我天馬行空想了一下,有可能用來控制像步進馬達、LED這些電子的東西嗎?
如果有可能那真是太棒了。
AS 2.0的文字格式,同樣是透過TextFormat類別控制。
Flash並不能控制印表機,它只是把列印資料和相關訊息傳送給作業系統的印表機驅動程式。
同樣地,Flash無法直接控制其他硬體設備,但是可以當成設備的人機介面,發送訊息給外部的硬體。
例如,你可以製作一個Arduino微電腦控制板,撰寫一些程式來控制LED的開關(這個程式放在Arduino微電腦裡面),並從Flash發出訊息指定要開關哪些LED。
要在swf里播放gif动画,请使用:
GIFPlayer 0.4
可以在google上搜索一下。:razz:
感谢分享!:mrgreen:
非常感謝Y.Boy大大^^
我有下載來看了,原來GIF動圖要載入到stage才不會變成靜態圖片。
但是如果能夠載到影片容器也部會變成靜態圖片,我想在使用上會更棒。