Java手機遊戲開發簡明教程 (SunJava開發者認證程序員 郎銳)

原文發佈時間爲:2008-07-30 —— 來源於本人的百度文章 [由搬家工具導入]css

Java手機遊戲開發實例簡明教程

(SunJava開發者認證程序員 郎銳)
1、手機遊戲編寫基礎
1.手機遊戲設計的基本原則
  目前,市面上的手機不管在處理能力仍是在存儲容量上都不足與PC機相提並論,但也足以支持一個設計優化的微型遊戲程序的運行。加上它的網絡通訊能力,甚至還能夠支持有聯機對戰能力的網絡遊戲。正是因爲硬件設備的極大差別,才直接致使了手機遊戲開發與傳統遊戲開發的極大差異。
  鑑於手機遊戲與傳統遊戲開發的巨大差異,並考慮到做爲其運行載體的手機的實際侷限性,在進行手機遊戲的設計時也有必須遵循的原則,即有限的遊戲時間;縮短等待時間;精幹的程序;尋求最大的兼容性。
  手機做爲一種典型的MIDP設備,其能量供應是有限度的,在設計遊戲時應當爲用戶提供一個有限的遊戲時間,以避免遊戲時間過長而大量消耗有限的能源。例如,能夠把遊戲時間限定在幾分種以內完成或是將其劃分爲若干階段分次進行。
  鑑於手機遊戲的處理速度不可能太快的客觀事實,爲保持遊戲的順暢進行,就必須儘可能縮短遊戲中的等待時間,尤爲是在設計多人聯機遊戲時必定要注意這個問題。並且因爲存儲空間的限制,也要求設計精幹的程序,不然將致使開發的遊戲因過於臃腫而沒法在手機執行。
  爲手機遊戲尋求最大的兼容性也是有必要的。因爲不一樣型號,不一樣款式的手機不只支持的J2ME SDK(Java 2 Micro Edition SDK)不一樣,屏幕尺寸及按鍵等也都存在差別。一款好的遊戲若是由於底層的不兼容而侷限於某一款機型顯然是一種浪費,其實遊戲的劇本、流程設計等徹底不用更改,只需針對其餘系列的手機更換必要的低層處理就能夠把遊戲的市場拓展到其餘機型。
2.手機遊戲的實現技術
  雖然J2ME對手機遊戲的開發已經成爲主流,但並非說只有J2ME可以開發手機遊戲,除此以外還有嵌入式和短信息等其餘幾種手機遊戲實現技術:
  嵌入式遊戲是指在手機出廠時就已經固化在芯片中的遊戲。早期手機提供的遊戲大可能是這一類遊戲。因爲這種技術不容許用戶自由更新遊戲,因此這類遊戲很快便被淘汰了。
  短信息遊戲是基於手機短信息服務(SMS)的手機遊戲,經過向遊戲服務商的服務器發送簡短的文字信息來獲取從遊戲服務器反饋的結果信息。因爲這種遊戲是純文本交互形式,所以一般較乏味且輸入煩瑣,遊戲成本較高(一般1條短信0.1元)。
  隨着Java技術的發展和Java手機的推廣應用,使手機遊戲進入J2ME時代。這種簡化版本的Java極大地提升了手機對遊戲的支持能力,它擁有比嵌入式和短信息手機遊戲更爲完美的界面,並且容許使用子圖形動畫。J2ME手機程序已經成爲目前最佳的移動遊戲開發環境,本文也正是圍繞着J2ME技術展開對手機遊戲開發過程的介紹。
3.《賽車》遊戲的劇本設計
  本文將向你們介紹一款賽車遊戲的製做過程。這是一款典型的體育競技類遊戲,它以公路做爲賽車場地,選手爲一輛賽車,障礙物爲在公路放置的炸彈。因爲只安排了一輛賽車,因此制定的遊戲規則不以速度取勝,而是按玩家規避障礙物的靈巧程度來積分。這可用玩家安全駕車的時長來度量,由於玩家玩得越熟練,其規避障礙物的手法也就更靈巧,安全駕駛的時間也就越長。
  因爲手機屏幕狹小,表現能力有限,並且在手機上也沒有提供任何軟硬件圖像處理加速,因此在手機遊戲中不可能追求PC機的表現效果。在追求視覺效果的同時,應儘可能作到簡單。
  本遊戲實例採用的是二維圖形表現形式,以筆直無轉彎的公路做爲賽道。玩家將能夠經過手機方向鍵控制賽車的左右移動,以規避隨機佈置在賽道上的炸彈,炸彈在隨機佈置後將再也不移動。若是賽車的任意部分與炸彈相接觸即被斷定爲觸彈爆炸,本局遊戲結束。
2、配置Eclipse開發環境
  在使用任何一種語言進行編程時都離不開開發環境,Java語言也不例外,這裏將向你們介紹一種很是著名的開發環境——Eclipse。
1.Eclipse基礎
  (1)認識Eclipse
  Eclipse是一個開放源代碼的、與NetBeans、Sun ONE Studio和Borland Jbuilder相似的一種基於Java的整合型可擴展開發平臺。就其自己而言,它只是一個框架和一組服務,用於經過插件組件構建開發環境。幸運的是,Eclipse 附帶了一個標準的插件集,包括Java開發工具(JDT)。其將來的目標不只僅是成爲專門開發Java程序的IDE環境,根據Eclipse的體系結構,經過開發插件,它能擴展到任何語言的開發,甚至能成爲圖片繪製的工具。
  難能難得的是,Eclipse是一個開放源代碼的項目,任何人均可如下載Eclipse的源代碼,而且在此基礎上開發本身的功能插件。也就是說將來只要有人須要,就會有創建在Eclipse之上的COBOL、Perl、Python等語言的開發插件出現。同時能夠經過開發新的插件擴展示有插件的功能,例如,爲了進行手機應用程序的開發,本文所涉及到的《賽車》遊戲就是經過J2ME插件的擴展來加以實現的。
  (2)Eclipse的組織結構
  Eclipse是一個開放源代碼的軟件開發項目,它專一於爲高度集成的工具開發提供一個全功能的、具備商業品質的工業平臺。它主要由Eclipse項目、Eclipse工具項目和Eclipse技術項目等組成,具體包括Eclipse Platform、JDT、CDT和PDE等4個部分。JDT支持Java開發、CDT支持C開發、PDE用來支持插件開發,Eclipse Platform則是一個開放的可擴展IDE,提供了一個通用的開發平臺。它提供建造塊和構造並運行集成軟件開發工具的基礎。Eclipse Platform容許工具建造者獨立開發與他人工具無縫集成的工具從而無須分辨一個工具功能在哪裏結束,而另外一個工具功能在哪裏開始。
  Eclipse SDK(軟件開發者包)是Eclipse Platform、JDT和PDE所生產的組件合併,提供了一個具備豐富特性的開發環境,容許開發者有效地建造能夠無縫集成到Eclipse Platform中的工具。Eclipse SDK由Eclipse項目生產的工具和來自其餘開放源代碼的第三方軟件組合而成。Eclipse項目生產的軟件以CPL發佈,第三方組件有各自自身的許可協議。
2.Eclipse的下載與安裝
  經過前面的介紹,咱們瞭解到Eclipse是一款很是出色和著名的開源項目。你只需登錄Eclipse官方網站(www.eclipse.org)就能夠免費得到這款優秀的開發環境。
  進入主頁後單擊「Downloads」連接,將出現鏡像列表頁面,從中選擇較近的鏡像點並進入下載頁面,目前最新版本爲3.0.1)。通常狀況下,Eclipse同時提供了Release、Stable Build、Integration Build和Nightly Build等多個下載版本,建議下載Release或Stable版本。這裏選擇Release版本。
  進入該版本的下載頁面,單擊「eclipse-SDK-3.0.1-win32.zip」連接進行安裝包下載(針對Windows平臺)。同時,單擊「eclipse3.0.1-SDK-win-LanguagePackFeature.zip」連接下載對應的多國語言包插件以實現軟件的本地化。
  安裝Eclipse的步驟很是簡單:你只需將下載的安裝壓縮包按原路徑直接解壓便可。以後將多國語言包解壓縮,並將解壓獲得的「plugins」和「features」文件夾去覆蓋解壓到Eclipse安裝目錄下「eclipse」文件夾下的同名文件夾便可。若是當前操做系統的JRE環境安裝正確無誤,運行Eclipse.exe將進入其默認界面。
  注意:這裏的前提是JRE環境的安裝正確無誤,因爲Eclipse自己是用Java語言編寫的,而下載的安裝壓縮包中並不包含Java運行環境,所以須要用戶本身另行安裝JRE,而且須要在操做系統的環境變量中指明JRE中bin的路徑。若是上述設置不正確,Eclipse將沒法正常運行。另外,因爲Eclipse版本升級較快,若是有更新版本,需先刪除舊版本從新安裝,而不能直接解壓到原來的路徑覆蓋舊版本。
3.一些必要的配置
  (1)配置JRE
  爲了保證Eclipse的正常運行,咱們須要配置JRE。你能夠安裝Sun的JDK或IBM的JDK,推薦使用1.4以上版本。由於只有使用1.4以上版本的JDK才能夠享受到新增的HotSwap功能對於調試帶來的方便。這裏,咱們使用Sun公司的1.5.0版本JDK,你能夠從Sun公司官方網站http://java.sun.com免費下載。
  (2)安裝J2ME SDK
  爲可以保證手機應用程序的開發,你還必須安裝J2ME SDK。Sun公司的J2ME Wireless Toolkit(WTK)即是經常使用的一款J2ME SDK,它提供了運行J2ME應用程序所須要的庫以及模擬器等,經過它能夠進行程序的編譯、校驗、運行。有關WTK的信息可查詢http://java.sun.com/products/j2mewtoolkit
  目前,J2ME Wireless Toolkit共分3個版本:1.0.四、2.0和2.1。其中,1.0.4版只能開發MIDP 1.0程序,2.0版能夠開發MIDP 2.0應用程序,2.1版則能夠同時開發MIDP 1.0、JTWI、自定義等3種環境。須要注意的是,並不是版本越高越好,必須視需求不一樣而選擇適當的版本,才能開發出能夠在真機上運行的MIDP應用程序。這裏選用的是WTK 2.1,你可從Sun公司官方網站免費下載,按默認方式安裝該工具包並記下其安裝路徑以便之後在安裝EclipseMe插件時使用。
  這裏之因此選用Sun公司的J2ME Wireless Toolkit產品,是由於這樣開發出來的手機軟件能夠具備更大的通用性。若是你只是出於爲本身的愛機DIY應用軟件的目的,則徹底能夠根據本身使用手機的型號從相應廠商網站下載與之對應的J2ME SDK,這樣開發出來的手機軟件可以以更優的方式在真機運行。目前一些大的手機廠商開發的特定J2ME SDK主要有:Nokia的Nokia DEveloper's Suite與Nokia各款手機專屬SDK;SonyEricsson的SonyEricsson J2ME SDK;Siemens的Siemens Mobility Toolkits等。
4.J2ME插件EclipseMe的安裝
  經過上面的介紹,你如今應當理解:對手機程序的開發實際也就是等於對J2ME項目的開發。雖然上面咱們對環境進行了配置,使其可以支持J2ME開發,並且Ecilpse使用起來很是方便,但這對J2ME開發的支持仍是遠遠不夠。下面,咱們將經過爲Eclipse安裝一個開發J2ME程序的插件EclipseMe來完善手機應用程序開發的最後一項準備工做。
  目前,EclipseMe的最新版本爲0.5.5(eclipseme.feature_0.5.5_site.zip),你能夠登錄SourceForge網站http://eclipseme.sourceforge.net/免費下載。
  進入SourceForge網站後單擊「Downloads」連接進入產品下載頁面,該頁面列有所有版本的EclipseMe插件及部分版本的源程序代碼。單擊須要下載的eclipseme.feature_0.5.5_site.zip,將出現下載鏡像列表頁面,你能夠從中選取距離較近的鏡像站點進行下載。
  對於EclipseMe 0.5.0版本及更早版本的安裝,能夠下載後直接將其解壓到Eclipse安裝目錄下的「plugin」文件夾下便可很方便地完成對插件的安裝。可是到了0.5.5版本之後,EclipseMe的安裝方式發生了較大變化,再用之前的方法將不能成功安裝插件。下面將給出EclipseMe這一版本插件的具體安裝過程:
  啓動Eclipse,單擊「幫助→軟件更新→查找並安裝……」菜單命令,打開「安裝/更新」對話框,選中「搜索要安裝的新功能部件」選項。單擊「下一步」按鈕。
  在出現的對話框中單擊「新建本地站點……」按鈕,在打開的對話框中指定EclipseMe壓縮包的當前解壓路徑,而後將會在「要包括在搜索中的站點」列表中出現以當前指定目錄爲名稱的站點項目。選中該項目,展開其樹型結構,能夠看見其子項EclipseME也被同時選中。單擊「下一步」按鈕。
  提示:最好將EclipseMe壓縮包解壓到一個路徑名中不包含漢字的文件夾下,例如,E:\EclipsMe\下,不然可能會在安裝過程當中出現一些奇怪現象而妨礙安裝過程的順利的進行。
  在出現的對話框中選中「EclipseME」按鈕。單擊「下一步」按鈕。在出現的對話框中單擊「我接受許可協議中的條款」選項。單擊「下一步」按鈕。在出現的對話框中指定Eclipse插件要安裝到的路徑,你能夠單擊「添加站點」按鈕,在出現的對話框中選擇其餘路徑(最好仍是安裝到Eclipse的安裝目錄下),單擊「肯定」按鈕完成便可。
  爲查看EclipseMe插件是否成功安裝,你能夠在重啓Eclipse後單擊「窗口→首選項」菜單命令,打開「首選項」對話框。在左側窗口看到J2ME項即標明EclipseMe插件已經成功安裝。java


 

在「首選項」對話框中進行配置程序員

5.對EclipseMe插件的配置
  爲了使新安裝的EclipseMe插件可以正常工做,須要對其進行配置。展開J2ME項,選擇「Platform Components」子項,在右側窗口中將同步顯示其詳細配置。右鍵單擊「Wireless Toolkits」選項,選擇「Add Wireless Toolkit」命令,在打開的對話框中單擊「瀏覽」按鈕,在出現的對話框中指定先前安裝的Wireless Toolkit路徑。若是路徑指定正確且Wireless Toolkit也安裝正確,此時EclipseMe將自動檢測出該目錄所安裝的Wireless Toolkit的版本,並顯示在編輯框的下方。單擊「完成」按鈕,在「首選項」對話框右側的配置窗口中將顯示該Wireless Toolkit所支持的一些特性。若是你是針對某一機型的手機進行開發,能夠重複上面的步驟將其餘廠商的無線開發工具包添加其中。
3、搭建遊戲框架
1.建立J2ME項目
  在Eclipse中首先建立J2ME MIDlet Suite項目「Racing」,全部後續的編碼、調試和運行都是在這個工程中進行。
  啓動Eclipse,單擊「文件→新建→項目」菜單命令,在打開的對話框中展開「J2ME」選項,選中「J2ME Midlet Suite」子項後單擊「下一步」按鈕。在出現的對話框中設置項目名稱和項目存放路徑,通常保持默認路徑便可。單擊「下一步」按鈕。
  在出現的對話框中對應用程序所支持的MIDP版本進行指定。若是考慮兼容性能夠選擇「J2ME Wireless Toolkit 2.1 MIDP 1.0 platform」選項。固然,你也能夠選擇「MIDP 2.0」選項。單擊「下一步」按鈕。
  在出現的對話框中對Java構建設置進行定義,一般保持默認值便可。單擊「完成」按鈕,EclipseMe將自動設置好項目的編輯及運行環境。你能夠在導航器視圖中單擊剛纔建立的項目,在右側編輯視圖中將能夠查看EclipseMe生成的項目結構。算法


 

查看建立的項目編程

2.建立J2ME應用程序
  上面建立的MIDlet Suite,通常也稱做MIDlet應用程序套件,它能夠包含一個或多個MIDlet,只是在發佈時是以MIDlet Suite爲單位進行,咱們的一些實質性的工做都是在MIDlet中完成的。所以,須要繼續添加J2ME MIDlet項「RacingMIDlet」到項目中。
  在導航器上單擊鼠標右鍵,選擇「新建→其餘」菜單命令,在打開的對話框中展開「J2ME」選項,選中「J2ME Midlet」子項後單擊「下一步」按鈕。在出現的對話框中指定包(也能夠保持默認值)和名稱,單擊「完成」按鈕後,EclipseMe將自動生成框架代碼,並將新建立的RacingMIDlet類按以下代碼進行編輯:
  public class RacingMIDlet extends MIDlet {
   public Display display;
   public GameCtrl game;
   public RacingMIDlet() {
   super();
  }
   protected void startApp() throws MIDletStateChangeException {
   // 得到Display
   display = Display.getDisplay(this);
   // 得到Displayable
   Displayable current = display.getCurrent();
   if (current == null) {
   // 裝載logo圖像
   Image logo = null;
   try{
   logo = Image.createImage("/logo.png");
   }catch (IOException e) { }
   // 顯示logo
   Alert splashScreen = new Alert(null, "郎銳2005年做\n版權全部(c)\n2005--2006", logo, AlertType.INFO);
   // 延遲4秒
   splashScreen.setTimeout(2000);
   //新建ChooseDemo對象
   game = new GameCtrl(this);
   // 顯示閃屏界面
   display.setCurrent(splashScreen, game);
   }else {
   // 顯示當前界面
   display.setCurrent(current);
   }
   }
   protected void pauseApp() {
  }
   protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
   }
   public void quit() throws MIDletStateChangeException {
   // 退出程序
   destroyApp(false);
   notifyDestroyed();
   }
  }
  這裏經過一個Alert信息框完成對閃屏界面的顯示,所使用的位圖logo.png在開始能夠暫用臨時圖像代替,最後再由美工完成的正式圖像替換。
  由於遊戲主題爲賽車,所以本例使用的logo位圖最好顯示一些賽車的圖標,並輔以具備藝術字效果的遊戲名稱。圖標能夠很方便地下載獲得,而遊戲名稱的藝術字效果一般要由開發人員本身完成。除了可使用專業的設計軟件外,還可以使用兩種不一樣顏色書寫同字體、同大小的遊戲名稱,而後將深色文字置後,淺色文字錯位少量後放置在前臺的方法經過視覺錯覺來實現立體字的效果。最後再與圖標合成到一張PNG格式的位圖,便可完成一個簡單logo位圖的製做。數組


 

Logo製做過程示意安全

  編輯完畢後,Eclipse將提示有多處錯誤存在,這主要是由GameCtrl類尚未添加形成的。接下來,向工程添加從Canvas類繼承的GameCtrl類,並編輯其類爲以下代碼,以保存從RacingMIDlet類傳入的MIDlet對象和對命令按鍵、方向按鍵的添加與響應:
  public class GameCtrl extends Canvas implements CommandListener{
   private final Command startCommand;
   private final Command quitCommand;
   private final RacingMIDlet midlet;
   public GameCtrl(RacingMIDlet midlet) {
   super();
   // 保存MIDlet類對象
   this.midlet = midlet;
   // 添加命令按鍵
   quitCommand = new Command("退出", Command.EXIT, 2);
   addCommand(quitCommand);
   startCommand = new Command("開始", Command.OK, 1);
   addCommand(startCommand);
   // 偵聽按鍵響應
   setCommandListener(this);
   }
   protected void paint(Graphics g) {
   }
   public void commandAction(Command arg0, Displayable arg1) {
   if (arg0 == startCommand){
   // 用戶開始遊戲
   initialize();
   }
   if (arg0 == quitCommand){
   // 用戶退出遊戲
   try{
   midlet.quit();
   }
   catch(MIDletStateChangeException e){}
   }
   }
   private void initialize() {
   }
   protected void keyPressed(int keyCode) {
   // 獲得按鍵動做
   int gameAction = getGameAction(keyCode);
   switch (gameAction) {
   case RIGHT:
   break;
   case LEFT:
   break;
   default:
   break;
   }
   }
  }
  這裏除了新增的keyPressed()方法外,與之前介紹過的程序框架並無太大的差異。這個keyPressed()方法主要用來捕獲用戶的手機按鍵,因爲在賽車駕駛時只需控制其左右移動方向便可,所以這裏只對getGameAction ()方法返回的鍵值與RIGHT和LEFT進行比較。稍後將完成這兩個分支的功能實現。
4、實現遊戲界面
  因爲將賽車遊戲抽象爲場地、選手和障礙物,所以在遊戲的界面實現時也主要圍繞這3箇中心展開。
1.實現場地界面
  因爲這裏的公路是平直無轉彎無路口的,所以展示到二維平面上就是一個矩形。能夠想象,若是隻在手機屏幕顯示一個矩形,不管填充什麼顏色,都很難使人聯想到是一條公路。爲了表現出公路的特徵,不妨在公路中間繪製一條隔離車道用的斑點線。因爲在比賽進行時,賽車與公路之間是相互運動的,而做爲遊戲的主角,賽車必定是不能超出玩家視線的。也就是說,賽車應當始終處於屏幕顯示範圍以內,這樣一來,爲了表現賽車的運動,就必須讓公路動起來。一個簡單的辦法是,在繪製公路中間的斑點線時對同一位置的斑點進行交替繪製。服務器


 

簡單展現公路特徵網絡

  可能從紙面上很難理解這樣簡單的處理怎麼可以產生公路想後移動的效果,不妨將上圖的公路中線看做13段連續的LED燈管,開始時爲奇數的燈管點亮,爲偶數的熄滅。接下來點亮的燈管熄滅,熄滅的點亮,如此反覆,正如街頭的霓虹燈,能夠經過對燈管點亮、熄滅的控制來實現一種移動的視覺錯覺。在代碼實現上可在paint()方法中添加以下代碼來實現對公路中線的繪製:
  // 繪製動態公路中線
  g.setColor(0, 0, 255);
  if (lineMode == true){
  lineMode = false;
  for (int i = 0; i < height; i += 20)
  g.drawLine(width / 2, i, width / 2, i + 10);
  }else{
  lineMode = true;
  for (int i = 10; i < height; i += 20)
  g.drawLine(width / 2, i, width / 2, i + 10);
  }
  其中,經過lineMode變量對虛線的繪製模式進行控制,width和height分別爲屏幕的寬度和高度。在構造函數中分別經過getWidth()和getHeight()方法得到。爲了可以以固定時間間隔週期性地調用paint()函數,可在程序初始化方法initialize()中建立一個定時器,並在定時器的執行方法run()中添加repaint()方法以完成對paint()函數的週期性調用。有關定時器的建立,可先向工程添加一個基於TimerTask類的新類NextFrame,用於週期性定時執行任務。並在GameCtrl類添加其類聲明和另一個Timer類的對象:
  private Timer timer = new Timer();
  private NextFrame nextFrame;
  在須要開啓定時器時,以nextFrame對象爲參數去調用Timer類的schedule ()方法並指定時間間隔便可:
  nextFrame = new NextFrame(this);
  timer.schedule(nextFrame, 300, 300);
2.實現炸彈與賽車界面
  炸彈與賽車的界面實現,能夠經過調用低級類Graphics中的相關繪圖方法來繪製,也能夠經過顯示位圖的方式來實現。前者幾乎不佔用內存,但繪製過程煩瑣,後者的顯示方法相比之下要簡單許多但卻要佔用少許的內存。這裏,咱們選用後者。框架


 

炸彈與賽車示意

  首先準備上圖所示的兩張PNG格式位圖並將其添加到工程中。炸彈和賽車做爲本遊戲的主角,其圖像在遊戲過程當中將被頻繁使用,所以,爲方便使用可將與這兩位圖相關的Image對象定義爲公有型的類成員變量。並在類構造函數中完成對位圖文件的裝載:
  try{
  // 裝載炸彈圖像
  bombImage = Image.createImage("/bomb.png");
  // 裝載賽車圖像
  carImage = Image.createImage("/car.png");
  }catch(Exception e) {}
  對於這種Image對象的繪製,可以使用Graphics類成員函數drawImage()方法,該方法的使用方法在前文已有過詳細介紹。因爲賽車須要左右移動,炸彈也要在被隨機放置後不斷從屏幕滑過,所以在繪製Image對象時,其位置最好能經過公有型的類成員變量來設置。這樣就能夠在一個專門的控制方法中對賽車和炸彈的顯示位置進行調整,而在paint()方法中只負責對圖形進行繪製,從而實現對遊戲功能的模塊化劃分。下面這段賽車和炸彈圖像的繪製代碼將以各自圖像的中心位置爲基準點進行繪製,共完成一輛賽車和四棵炸彈的屏幕繪製:
  // 賽車水平位置
  public int carPos = 0;
  // 炸彈位置
  public int[] bombPosX = {0, 0, 0, 0};
  public int[] bombPosY = {0, 0, 0, 0};
  // 炸彈是否出界
  public boolean[] bombCanUse = {false, false, false, false};
  ……
  // 繪製賽車
  g.drawImage(carImage, carPos, height - carImage.getHeight(), Graphics.HCENTER | Graphics.VCENTER);
  // 繪製炸彈
  for (int i = 0; i < 4; i++){
   if (bombCanUse[i] == true)
   g.drawImage(bombImage, bombPosX[i], bombPosY[i], Graphics.HCENTER | Graphics.VCENTER);
  }
  這裏的bombCanUse數組用來對當前炸彈是否出界予以標識,這裏所說的炸彈出界並非指炸彈當前位置超出屏幕範圍,而是在真實屏幕上方另設一連續的與真實屏幕等大的、可用來隨機放置炸彈的虛擬屏幕。此虛擬屏幕和真實屏幕的並集纔是炸彈的有效區域。凡是落在此區域內的炸彈均不予銷燬,若是有炸彈移出有效區域,則在炸彈放置區從新隨機放置一枚,始終保持炸彈有效區域內的炸彈總數爲4個。


 

炸彈有效區域示意

  最後,必定要記得在paint()方法開始繪製下一場景以前經過下面的清屏語句擦除當前場景的顯示。不然,在遊戲開始後隨着各類角色的移動,屏幕將變成一個「大花臉」。
  // 白色清空畫布
  g.setColor(255, 255, 255);
  g.fillRect(0, 0, width, height);
5、角色移動與碰撞檢測
  前面對遊戲的骨架和界面都已經實現,但此時的遊戲仍然毫無生氣,由於咱們尚未實現其靈魂。接下來將要進行的角色移動與碰撞檢測將可以使遊戲中的主角動起來,並可以經過對當前遊戲狀態的檢測來自行判斷遊戲是否結束。
1.角色移動
  (1)移動賽車
  因爲道路的移動是經過交替繪製公路中線所引發的錯覺來實現的。所以,實際真正須要移動的角色只有炸彈和賽車。本例將以賽車爲基準,它始終處於屏幕下方,玩家能夠經過手機左右方向鍵實現對賽車的左右移動。顯然,對賽車的移動控制所有由玩家掌握,其控制代碼只能在keyPressed()方法對左、右按鍵的分支處理中實現。因爲在先前的設計中實現了顯示與控制的分離,所以在這裏只需對錶示賽車水平位置的carPos變量取值進行修改便可。爲防止賽車移出屏幕,須要添加必要的越界保護代碼:
  // 獲得按鍵動做
  int gameAction = getGameAction(keyCode) switch (gameAction) {
  case RIGHT:
   // 右移賽車
   carPos += 5;
   // 防止越界
   if (carPos > width - carImage.getWidth() / 2)
   carPos = width - carImage.getWidth() / 2;
   break;
  case LEFT:
   // 左移賽車
   carPos -= 5;
   // 防止越界
   if (carPos < carImage.getWidth() / 2)
   carPos = carImage.getWidth() / 2;
   break;
  default:
   break;
  }
  // 重繪屏幕
  repaint();
  (2)移動炸彈
  與賽車不一樣,炸彈的移動控制由手機全權負責。只要遊戲在運行,炸彈就不停的從屏幕上方滑落,對於相似的處理應當交由定時器任務類完成相關操做。NextFrame類成員方法run()將在定時器每次被觸發時調用。
  在處理炸彈移動時,首先對炸彈是否超出有效區域進行檢測。因爲初始運行時屏幕沒有炸彈,因此能夠將其看成超出有效區域進行處理。對於這種狀況,首先經過Random類的nextLong()方法獲得兩個隨機數,而後分別以屏幕寬度和高度爲模進行取模運算,其結果經越界限制後將做爲炸彈的初始設置座標。在每設置一棵炸彈後要及時對該炸彈所對應的bombCanUse元素設置炸彈有效值,以在後續的處理中執行下落顯示。
  與賽車的左右移動相似,炸彈的下落能夠經過不斷增長其縱座標來實現。只是在下落過程當中沒必要進行越界保護處理,若是炸彈越過有效區域就經過bombCanUse將其標記爲無效。將在下必定時週期重複前面的過程:
   for (int i = 0; i < 4; i++){
   // 炸彈沒顯示時設置初始位置,顯示後水平位置固定
   if (gameCtrl.bombCanUse[i] == false){
   // 隨機設置炸彈初始位置
   int x = (int)(rand.nextLong());
   x = (int)(x % gameCtrl.width);
   gameCtrl.bombPosX[i] = x;
   int y = (int)(rand.nextLong());
   y = (int)(y % gameCtrl.height);
   // 將炸彈設置在虛擬屏幕
   gameCtrl.bombPosY[i] = -y;
   // 限制炸彈水平位置
   if (x < bombWidth)
   x = bombWidth;
   if (x > gameCtrl.width - bombWidth)
   x = gameCtrl.width - bombWidth;
   // 標誌第i個炸彈進入可視區
   gameCtrl.bombCanUse[i] = true;
   }else{
   // 炸彈下移
   gameCtrl.bombPosY[i] += 3;
   // 炸彈出界檢測
   if (gameCtrl.bombPosY[i] > gameCtrl.height + bombHeight / 2)
   gameCtrl.bombCanUse[i] = false;
   }
  }
  若是此時運行程序,雖然能夠實現賽車在布有炸彈的公路上行駛的效果,並且玩家也能夠控制賽車的前進方向,但卻存在一個致命的缺陷——當賽車和炸彈相撞時,炸彈依舊下落,賽車依舊行駛,好像什麼都沒有發生同樣。這是因爲沒有爲遊戲添加碰撞檢測代碼所致。
2.碰撞檢測
  碰撞檢測是遊戲中常用的一種重要算法。用於檢測遊戲中的兩物體是否發生表面接觸,例如,子彈是否命中歹徒,炮彈是否擊中目標等等。只有進行了碰撞檢測纔有能在出現上述狀況後實現歹徒被擊斃、目標被摧毀等結果。


 

炸彈與賽車發生碰撞示意

  上圖展現了炸彈與賽車發生碰撞時的全部可能情形。從圖中能夠看出,只要炸彈徹底進入圖中的虛線矩形框就必然與賽車發生了碰撞。對本遊戲而言,發生了碰撞即意味着賽車被炸燬,遊戲結束。因此,在炸彈下落過程當中不難寫出以下碰撞檢測代碼:   // 碰撞檢測   if (gameCtrl.bombPosY[i] + bombHeight / 2 >= gameCtrl.height - carHeight * 3 / 2 && gameCtrl.bombPosY[i] - bombHeight / 2 <= gameCtrl.height - carHeight / 2 && gameCtrl.bombPosX[i] + bombWidth / 2 >= gameCtrl.carPos - carWidth / 2 && gameCtrl.bombPosX[i] - bombWidth / 2 <= gameCtrl.carPos + carWidth / 2){   // 結束遊戲   gameCtrl.isGameOver = true;   // 關閉定時器   cancel();    }  其中,carWidth、carHeight、bombWidth和bombHeight變量分別是經過carImage和bombImage對象調用各自的getWidth()和getHeight()方法而返回獲得的賽車圖像尺寸和炸彈圖像尺寸。若是發生碰撞,將經過公有型的boolean類型變量isGameOver來指示遊戲的結束。同時調用TimerTask類成員方法cancel()關閉先前設置的定時器。  對於非勝負類遊戲,因爲在遊戲結束時並無勝出方,因此通常都是以積分的形式反饋給玩家當前局所取得的分數。對於本例,分數顯然是與安全駕駛時間成正比的,在程序實現時,能夠在定時器每次觸發run()方法時對積分進行累加,並在遊戲結束時經過下述代碼以信息框的形式將當前積分反饋給玩家:  isGameRun = false;  // 顯示logo  Alert result = new Alert("本局積分", String.valueOf(score), null, AlertType.INFO);  // 延遲4秒   result.setTimeout(2000);  // 顯示閃屏界面  midlet.display.setCurrent(result, this);  通過上述辛勤工做,一款真正的J2ME手機遊戲程序已經完成!6、測試與發佈遊戲  單擊「運行→運行」菜單命令,在打開的對話框左側配置窗口中右鍵單擊「Wireless Toolkit Emulator」選項,選擇「新建」命令,在對話框右側將顯示相應的運行配置選項。通常可保持默認設置,也能夠在「Emulation」選項卡中對默認設備進行指定。一般選擇「DefaultClolorPhone」選項便可,其模擬的是在彩屏手機上的運行效果。因爲目前支持Java的手機通常配置都不是很低,絕大多數也都是彩屏配置,所以「DefaultClolorPhone」選項應該是比較大衆。固然,你也能夠設置「DefaultGrayPhone」等其餘選項以模擬在單色或其餘配置的手機上的運行效果。  最後,單擊「運行」按鈕執行咱們建立的賽車遊戲。  固然,本例做爲一款教學性質的遊戲實例,沒有作太多的完善與優化。給你留下了較大的遊戲擴展空間。你能夠在本遊戲基礎上嘗試進一步的擴展和修改,例如,增長先後方向鍵以模擬加大油門和剎車;另外增長一些參賽車輛;根據玩家遊戲進行時間的長短動態調整遊戲難度,包括加快車速、增長障礙物等等。代碼編寫無誤後能夠先在PC上的模擬器中運行調試,並對出現的問題進行修改,一切無誤後再打包發佈。

相關文章
相關標籤/搜索