天天看點

Effective J2ME (3)

本文節選于筆者在數年前開發手機遊戲時總結的一份文檔。一家之言,贻笑大方。

2.2 規模

    通常J2ME裝置對Jar檔案的大小進行了限制,例如Nokia6610允許最大的Jar大小為64K。是以在開發J2ME應用時,應該盡量編寫精簡的代碼,使用具有可以接受效果的最小的圖檔。

2.2.1 編寫精簡的代碼

    很多人都曾提出過在J2ME開發中減小代碼大小的建議,例如減少類和方法的個數、縮短變量和方法名、打破類的繼承關系等等。但是我認為,這在做法都是在犧牲了程式的可讀性、可擴充性的基礎之上的,而且代價高昂。沒有必要為了減少代碼的大小刻意地這樣做,這種代碼通常難以調試和修改。與此相反,好的設計同樣可以有效地減小代碼的大小。代碼備援往往是編寫精簡代碼的最大敵人而不是過長的變量名。唯一例外的是,我認為在J2ME開發中可以使用公共的類成員變量,而不必象在J2SE和J2EE開發中那樣,将類的狀态封裝的那樣完美。這樣做既可以加快程式的速度,又比提供額外的通路方法(get方法和set方法)的做法生成的代碼更小。在我編寫的四款遊戲中,雷鳥号、BomberMan和荒島探寶的代碼規模都控制在2000-2200行左右。叢林武士的代碼在3100行左右。其中用于程式架構部分(這四款遊戲重用的基本的架構代碼)的代碼在800-900左右。

2.2.2 合并圖檔以減小圖檔的總大小

    在J2ME應用中通常使用.png格式的圖檔。由于.png圖檔使用彩色查找表(調色闆)來存儲顔色,是以将在顔色上類似的多個圖檔合并成一張圖檔可以有效地減少圖檔的總大小。例如以下四張圖檔 總大小為649位元組。如果合并為一張圖檔之後 ,大小為191位元組。在使用合并後的圖檔時,可以利用Graphics類的setClip(int sx ,int sy, int width ,int height)來設定實際的繪圖區域。例如要在螢幕上(50,50)這個點上繪出第三把鑰匙的代碼是:(假設每把鑰匙的大小為12×12)

g.setClip(50,50,12,12);
g.drawImage(image,50-12*2,50,20); 
           

2.3 可移植性

    盡管目前我們的開發都是基于MIDP1。0之上的,但是不同的手機廠商往往提供了特定的開發包。例如Nokia提供了DirectGraphics類、 DeviceControl類等;Motorola提供了Game API等。此外,不同型号手機的螢幕尺寸和處理器速度往往也不相同。是以在開發的過程中,應該充分認識到這些不可移植的因素,盡量增強程式的可移植性和自适應能力。

2.3.1 盡量使用标準的類庫

    Motorola 的Game API針對遊戲的開發提供了一些底層支援。但是如果我們在程式中使用了這些API,那麼就意味着這款遊戲将很難移植到Motorola以外的手機上,也無法移植到不支援Game API的Motorola 手機。就我們目前的開發要求而言,這是不明智的。同樣,Nokia提供了DirectGraphics類,支援圖檔的旋轉、對圖檔象素的通路等等。在某些情況下,使用這些API的确可以帶來便利。例如如果使用DirectGraphics的圖檔旋轉功能就可以節省圖檔資源,不必另外在資源中提供旋轉後的圖檔。利用DirectGraphics的對圖檔象素的通路功能就可以利用象素的α通道計算出圖檔可見部分的邊緣。在這種情況下,就要在可移植性和便利性之間做出取舍。就我而言,應該選擇前者。

2.3.2 運作時得到螢幕的大小

    不要在程式中使用寫死的螢幕尺寸。比如語句 g.drawString(“載入中…”,64,100,Canvas.HCENTER);這句代碼明顯是針對128象素寬的螢幕的。不适合移植到具有其它顯示大小的裝置上。如果可能,應該使用類似于g.drawString(“載入中…”,sCanvasWidth/2,sCanvasHeight- 16,Canvas.HCENTER);的語句。對于變量sCanvasWidth,一種做法是将其定義為靜态常量,如public static final int sCanvasWidth=128;這種做法的缺點在于,當程式需要移植到其它裝置上時需要修改變量的初值。我個人推薦的做法是将其定義為靜态變量,同時在程式運作時為其指派一次。比如在顯示閃屏之前(因為這個操作隻需執行一次)利用sCanvasWidth=getWidth();獲得螢幕的尺寸。

2.3.3 将控制遊戲速度的參數儲存在Jad檔案中

    在目前的J2ME遊戲中,通常通過調整遊戲主線程的休眠時間來控制遊戲的速度。對于處理速度較快的機型,可以适當增加休眠的時間;對于處理速度較慢的機型,可以适當減少休眠時間。通過這種方法來消除具有不同處理速度的手機之間的差異。推薦将這個參數儲存在Jad檔案中,而不是将其寫死在程式代碼中。這樣做的優點在于可以在不必重新編譯整個工程的情況下,針對目标機的特點調整遊戲的速度。

2.3.4 使用GameAction來處理按鍵事件

    使用GameAction會增強應用程式的可移植性。MIDP 1.0規範中定義了KeyCode和GameAction之間的轉換規則。Canvas類定義了抽象遊戲動作集,例如UP、DOWN、LEFT、 RIGHT和FIRE等等。通過Canvas類的public int getGameAction(int keyCode)和public int getKeyCode(int gameAction)兩個方法可以實作KeyCode和GameAction之間的轉換。需要注意的是,getKeyCode隻能傳回基于 GameAction的一個KeyCode,即使MIDP 1.0允許超過一個KeyCode被實作到相同的GameAction。另外,GameAction映射對于要求快速鍵盤響應的遊戲來說可能并不适用。不推薦在同一個應用程式中混合使用KeyCode和GameAction