一、編寫易於移植的J2ME代碼
我寫第一個J2ME游戲的時候,根本就沒想過移植的問題。所以那個游戲也就很難移植了。反過來,假如你已經計劃好要移植了,那麼事情就簡單的多。這一節說的是代碼問題。那就想想,不同手機之間在代碼上會有哪些差異。
(1) 屏幕尺寸不同 這兒談的主要問題,是自適應控件。所謂控件,就是菜單、文本框、列表框、進度條等等。這些控件的大小必須可以根據屏幕大小自適應的調整。按照第一篇說的方法,將屏幕大小作為變量參與到控件尺寸的計算即可得到正確的尺寸(自適應後的)。其次就是得到正確尺寸後怎麼把它畫出來。
這要看你的GUI是怎麼畫得了,假如是用線畫的,那就很簡單;假如使用了圖片,那麼就可能要更換圖片了。我的控件使用了圖片平鋪和畫線結合,所以可以很輕易的改變尺寸。假如控件變大了,則繪制時增加平鋪的次數即可。
順便說一下,這些控件我只用了一個類表示,使用參數化的方法區分使用,究竟咱要盡量少用類吧。
(2) 支持的API不同 假如你的游戲只限於使用Midp1.0,那麼移植的時候就不用考慮什麼了。實際上由於我們經常要使用圖片翻轉、象素繪制、全屏等,往往要用到廠商API或Midp2.0。顯然移植的時候要考慮到這些API的差異。
我的辦法是將這些api封裝一層,比如我需要使用創建透明子圖的API,於是封裝了一個函數createSubImg。這是Nokia版本:
public static Image createSubImg(Image img,int []imgRect)
{
Image subImg = DirectUtils.createImage(imgRect[2],imgRect[3],0) ;
subImg.getGraphics().drawImage(img,-imgRect[0],-imgRect[1],20);
return subImg ;
}
這是Midp2.0版本:
public static Image createSubImg(Image img,int []imgRect)
{
return Image.createImage(img,imgRect[0],imgRect[1],imgRect[2],imgRect[3],0) ;
}
對於不同機型,該函數的實現不同,但功能相同,因此使用這個函數的代碼在移植時無需修改。當然這樣做增加了一些間接性,有可能降低性能。
(3) 按鍵代碼不同 我們知道MIDP提供了Game Action,和按鍵代碼無關,但這不夠用啊,我們完全可以定義自己的Game Action,但首先讓我們定義自己的虛擬按鍵碼吧。我使用位記錄每個鍵的狀態,每個位代表一個按鍵,一個int有32個位所以足夠了。
當keyPressed發生時,我記下哪些鍵被按下;同樣當keyReleased時,將那些被松開的鍵使用的位清0。某個鍵,也就是這個鍵盤狀態整數裡的某個位,就是我定義的一個虛擬鍵。當然它的值總是2的n次方了,和key code完全不搭邊,所以需要我們用一個映射函數將key code映射到這些虛擬鍵。
這個函數就是移植的要害,每個機型都要改寫這個映射函數,在裡面填入正確的key code。你可以在虛擬鍵的基礎上再定義Game Action,支持在游戲中設置按鍵,這樣就更靈活了。
(4) 封裝庫 假如想不更改一行代碼就從MotorolaV600移植到Nokia N-Gage,那麼為他們封裝不同的庫吧。我就這樣在1分鐘內完成了移植。我的庫包含了一個游戲框架類(內含游戲循環和渲染函數,鍵盤處理,以及若干跨機型的工具函數),一個圖形組治理類(治理圖片的載入切割旋轉繪制和動畫等,有點像GameAPI中的Sprite)和一個控件類(包含了所有我需要的控件)。
這3個類封裝了不同機型的所有差異,我需要為每種機型改寫這三個類,當然大部分代碼是相同的了。此外我還寫了一個工具支持圖形組治理類,所見即所得的編輯動畫和治理圖片,當然這也對移植有幫助。
總結: 以上幾條,總得講來,無非是拆合而以。主要是要將差異性獨立出來,便於更改。但是移植總得來講還是比較郁悶,主要原因是各種機型有各自的bug,這就需要非凡處理啦。各位寫代碼時一定要想好移植的問題啊!