程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> 開發易於移植的J2ME游戲

開發易於移植的J2ME游戲

編輯:J2ME
J2ME游戲開發中,移植是個問題。各種手機的屏幕大小,按鍵,支持的API和性能各不相同,要想一次開發,到處運行並非易事。本文從幾個方面簡要討論一下開發易於移植的J2ME游戲的方法,每一節分別對應一個具體問題。

一 不大不小的Size問題

1 屏幕尺寸不等?把它看做變量!
  第一個問題,就是屏幕的尺寸問題。不同牌子不同型號的手機,屏幕尺寸大小不一。在渲染時必須考慮到尺寸的變化,即將尺寸看成兩個變量 ScreenWidth和ScreenHeight,將這兩個變量代入到渲染時坐標的計算式中。這樣屏幕尺寸變了,但想要的效果不會變。舉個簡單的例子,現在想居中繪制一個Logo圖,只要設置渲染的坐標為: x=(ScreenWidth-ImageWidth)/2; y=(ScreenHeight-ImageHeight)/2即可。再舉個RPG游戲中繪制地圖的例子,假如Tile大小為16*16,屏幕大小為128*128,則一屏正好顯示8*8個Tile,但是如果直接用8*8次循環繪制這些Tile,那麼程序就寫死了,如果屏幕大小變了(換了一個機型或改成使用全屏)或者Tile大小變了,這些地方就要改動。正確的方法還是將尺寸看做變量,可將Tile的寬和高定義為常量,這樣需要繪制的Tile數目為 ScreenWidth/TileWidth * ScreenHeight/TileHeight。現在你可以在各種大小的屏幕上正確顯示你的地圖了。這樣的例子很多,也不光是屏幕尺寸需要看作變量,凡是有可能改變的數值,將他們定義成變量或常量,那麼可移植性就會提高很多。另外,使用相對坐標也能提高可移植性,比如現在需要繪制超級瑪麗中得到的金幣數,我們需要顯示一個金幣的圖,然後在它後面寫上數字。嗯,將金幣的坐標設為gold_x,那麼數字顯示的起始坐標就是gold_x+金幣圖標寬度+1。我這兒寫了一個1,但這不要緊,我只是想顯示數字的時候和金幣圖標隔開一個象素,這樣寫後,如果我們想將金幣數的顯示從左邊移到右邊,則只要改變gold_x就可以啦。如果我們想讓金幣數目顯示在屏幕的最右邊怎麼辦?只要將gold_x設為 ScreenWidth-金幣圖標寬度-1-StringWidth(String(金幣數目))。嗯,就是這樣,這是一句偽碼,重點在於我們將表示金幣數目的數字的長度也計算了一遍。因為不同機器的字符大小也不同。

2 文字大小不等?還是將它看成變量!
   說到文字,大家可能都會很郁悶,因為中文普遍比較大,做到手機裡面很不美觀。當然也有個別,NokiaS40的小字體看著還不錯。這兒我想起了一件事,我將字體設為Large時,MotorolaV600的真機顯示的是小字體!呵呵,原來設為Small,它倒是大字體。好了,說正題。既然文字大小不等,那我們還是將它看成變量。Font類有兩個方法:getHeight和stringWidth可以幫助我們。如果你的游戲裡只使用一種字體,那麼只要開始時調用一下getHeight,將字體高度記錄下來就可以了。當然要記得在paint裡面setFont啊!stringWidth可以計算出一個字符串的長度,這非常有用,因為手機中的英文字體一般不是等寬的,而且中英文數字混排時字符串的長度就更不能用字符數*字符寬度去計算了。有了這個函數,我們就可以准確知道所繪制的字符串的長度。這裡有個典型的應用是文本顯示的時候換行,通過stringWidth可以計算出文本是否需要換行。再給個小小例子,我寫得一個工具函數,用來顯示左右軟鍵菜單。
public static void drawSoftKeyMenu(Graphics g,String leftKey, String rightKey, int color, int style)
{  
drawString(g,leftKey,0,canvasHeight-mainFontHeight,color,style,GLT) ;
drawString(g,rightKey,canvasWidth-stringWidth(rightKey),canvasHeight-mainFontHeight,color,style,GLT) ;  
}
當然這個函數你不能直接用,裡面用到了好幾個我自己封裝的函數,不過意思很明白。繪制左軟鍵菜單的坐標是(0,canvasHeight-mainFontHeight),繪制右軟鍵菜單的坐標是(canvasWidth-stringWidth(rightKey),canvasHeight-mainFontHeight)
Java手機網[www.cnjm.Net]
Java手機網[www.cnjm.Net]3 虛擬屏幕 - 很好玩也很好用
   第一個問題說了屏幕的大小,我們將它看作變量,就可以解決移植時屏幕不等大的問題了。這兒提供一個高級技巧,其實很簡單:)。就是將屏幕的一部分作為你的游戲屏幕,我稱它為虛擬屏幕。請相信,它是很有意思也很有用的。虛擬屏幕用起來很容易,只要將你的坐標范圍看作: x=0~vsWidth , y=0~vsHeight。按照這個坐標范圍,像原來一樣作所有的事情,只是,在最後渲染的時候,將你的坐標轉換到真實的屏幕坐標。 real_x = x+vsX, real_y = y+vxY 。那麼這個虛擬屏幕有什麼好處呢?第一,你可以用一個屏幕很大的模擬器開發了,只要在它的屏幕上設置一塊虛擬屏幕就可以了。剩於的屏幕怎麼辦?可以用來顯示一些調試信息什麼的。當然最好也定義成虛擬屏幕。就是說你可以定義n個虛擬屏幕。每個屏幕顯示自己的內容,互不影響。除了調試,開發分屏游戲時也用得上。
   上面提到的虛擬屏幕只是簡單的在真是屏幕上挖了一塊。其實,我們可以完全按照自己的想法定義它,可以任意定義它的大小,定義一個1024×1024的屏幕也沒問題。你現在擁有了一個1024*1024的游戲區域了,在裡面可以盡情作所有的東西,只要,在渲染的時候將虛擬屏幕的坐標映射到真實屏幕即可: real_x = x/n + vsX , real_y = y/m + vsY 。這裡的n和m是比例系數。

小結:這一章講了size問題,一句話,將會變的看成變量,這不只是針對size有用,針對游戲開發時的所有量都是有效的。即使你確定它不變,也請使用常量定義,請放心,混淆器會將所有的final static內聯的。

Java手機網[www.cnjm.Net]二 編寫易於移植的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)
Java手機網[www.cnjm.Net]{    
   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,支持在游戲中設置按鍵,這樣就更靈活了。
Java手機網[www.cnjm.Net](4) 封裝庫
   如果想不更改一行代碼就從MotorolaV600移植到Nokia N-Gage,那麼為他們封裝不同的庫吧。我就這樣在1分鐘內完成了移植^-^。我的庫包含了一個游戲框架類(內含游戲循環和渲染函數,鍵盤處理,以及若干跨機型的工具函數),一個圖形組管理類(管理圖片的載入切割旋轉繪制和動畫等,有點像GameAPI中的Sprite)和一個控件類(包含了所有我需要的控件)。這3個類封裝了不同機型的所有差異,我需要為每種機型改寫這三個類,當然大部分代碼是相同的了。此外我還寫了一個工具支持圖形組管理類,所見即所得的編輯動畫和管理圖片-當然這也對移植有幫助。

總結:
以上幾條,總得講來,無非是拆合而以。主要是要將差異性獨立出來,便於更改。但是移植總得來講還是比較郁悶,主要原因是各種機型有各自的bug,這就需要特殊處理啦。各位寫代碼時一定要想好移植的問題啊,就算自己不移植也要為移植的兄弟著想啊————
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved