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

畢業論文——J2ME手機游戲開發

編輯:J2ME
一  前  言
1.1 摘要
Java手機網[www.cnjm.Net]J2ME(Java 2 Micro Edition) 是近年來隨著各種不同設備,尤其是移動通信設備的飛速發展而誕生的一項新的開發技術。它定位在消費性電子產品的應用上,對設備的智能化、多樣化,提供了革命性的解決方案,並因其“Write Once, run anywhere”的Java特性而提高開發的效率。
隨著手機的日益普及、Java功能在移動設備上的實現,Java應用程序產生的手機增值服務逐漸體現出其影響力,對豐富人們的生活內容、提供快捷的資訊起著不可忽視的作用。本論文著眼於J2ME技術的應用,開發一款可商用的手機游戲程序——撲克豪斯。本程序的界面和運作方式於台式游戲豪斯,將老少皆宜的經典作品移植到手機上來,為更流行的硬件平台提供應用軟件。
本論文介紹了手機的軟硬件特性、J2ME的相關技術及本程序的結構分析和具體功能的實現。
關鍵字:J2ME,手機游戲, Java,撲克豪斯

ABSTRACT
J2ME is a kind of fast developing technology implemented on various devices especially mobile communication equipments. It focuses on application for consumptive electronic products, providing revolutionary solution to the intelligentization and diversification of the equipment. It improve the efficIEncy of the development process thanks to its “Write Once, run anywhere” nature.
When cell phone is getting ever more popular nowadays, with the implementation of Java technology on mobile equipment, increment of capital on communication service exhibits its force on people’s everyday life, providing them ever fast information just in hand. This dissertation focuses on implementation of J2ME technology and has developed a commercial game suite run on mobile phones—PokerMachine. This application inherits many characters of the old fashioned game Battle City which developed by Nintendo in 1980s. It transports the classical product to mobile phones, offering corresponding software for such more popular hardware platform.
This dissertation introduces the characteristic of Nintendo FC Machine and its software, J2ME and its relative technology as well as this program’s structure and analysis of implementation in details.  
Key Words: J2ME, mobile game, Java, tank, Battle City.

1.2引  言
手機游戲成績斐然,成為IT產業中增長最快的部分之一.縱觀IT產業的歷史,計算機游戲已經成為技術創新背後的動者渴望更加強大的硬件計算能力;渴望不受不同的軟件的限制??無論是將圖形強制在人工智能(AI)上 還是網絡安全性。游戲開發者和玩家常常是前沿計算機技術的最早的采用者。由於他們的創新天性,游戲不再是由大型采購公司控制的技術產品??游戲領域總是有充足的空間給那此
在這方面有天分的單個創新者。隨著技術對游戲經驗的促進,游戲市場持續增長。商業IT革命為我們節省了時間力之一。計算機游戲和金錢,從而提高了我們的工作水平,我們因此花費更多的時間和金錢在游戲上,來改善生活的整體質量。甚至在當今困難的經濟時代,游戲仍保持快速增長,他仍然是盈利行業的組成部分。Java開發者應該注意到這裡蘊藏著的巨大的商機。

1.3手機游戲特征  
Java手機網[www.cnjm.Net]    手機游戲的盈利主要是由於它們的涉及面很廣。手機已經與現代生活方式緊緊地結合在一起。他們是最普遍攜帶的個人用品中僅次於鑰匙和錢包的東西。傳統的台式機游戲將目標鎖定在低級趣味的人和青少年身上,而手機游戲則每個人都可以訪問的到??隨時,隨地。盡管每個手機游戲都不貴,但是巨大的使用量(如:每人每星期一個新游戲)將使得這個市場商機無限並且有利可圖。但是,對於開發者來說,將控制台游戲遷移到手機游戲工程很大因為他們所面向的對象、生活方式和分布式模型都有著極大的區別。讓我們從手機游戲的需求談起吧。  
一個成功的手機游戲大多具有以下特征:
1:易於學習: 既然手機游戲面向的是普通消費者而不是計算機高手,那麼他們不可能深入的學習游戲技巧。消費者不會花幾個小時去研究一個3美元的手動操作的游戲。所以游戲必須是一下載就可以玩的。保持游戲的簡單是最基本的要求。  
2:可中斷性: 多任務處理是手機生活方式的基本特征。手機用戶常常在任務(如等一個電子郵件或者等車)之間有一小段時間。而游戲、日歷管理、通訊和工作數據訪問使用的是同一個設備。所以一個好的手機游戲應該提供短時間的娛樂功能,並且允許用戶在游戲和工作模式之間順利切換。
3:基於訂閱:手機游戲的盈利成功取決於他們巨大的使用量。一開始開發和設計每個游戲都是昂貴的。如果一個手機游戲開發者要賺錢的話,重要的是:同一個游戲引擎,多個標題,基本的故事情節類似。基於訂閱的游戲是不斷產生收入的最好方法。
4:豐富的社會交互: 不管一個游戲設計得多好,只要玩家找到了它的根本模式或者玩完了所有的游戲路徑很快就會厭煩這個游戲。對於一個基於訂閱的游戲,重要的是與別的玩家合作以增強所玩游戲的智力和隨機性。在今天紛繁復雜的多玩家游戲中具有豐富社會交互的游戲證明是成功的。  
Java手機網[www.cnjm.Net]5:利用手機技術的優點: 巨額的手機技術研發費用都花在提高設備和網絡的可用性和可靠性上面。因此,手機設備硬件和網絡協議與桌面/控制台世界(如全球定位系統(GPS)擴展、條形碼掃描儀、和短消息服務(SMS)/多媒體信息服務(MMS)通訊)有著非常大的差別。好的手機游戲應該利用那些更新的設備特征和網絡基礎設備的優點。  
6:無違法內容:既然所有年齡/性別的人群都玩手機游戲並且常常在公共/工作場合,你應該避免明顯的暴力或者色情內容。  
1.4手機游戲的類型  
基於以上標准,最有可能成功的手機游戲就是那些臨時小游戲,它可為廣泛的玩家在所有的社交場合提供娛樂。特別是,下列類型的游戲將是明天最具有殺傷力的游戲:  
Java手機網[www.cnjm.Net]1:多玩家游戲: 這些游戲可以提供手機訪問以便建立在線游戲團體。或者,他們利用手機專有特征如多媒體通訊和基於位置的服務,從而創建完全不同的社會結構。好的游戲設計和管理是這種類型游戲成功的關鍵。  
Java手機網[www.cnjm.Net]2:基於內容的游戲:這些游戲傳送版權的多媒體內容,如名人的圖片、視頻片斷、音頻立體聲、和私人的體育節目,給那些音樂/電影/體育迷們。它成功的關鍵就是提供值得訂閱的高品質的內容流。  
3:高沖擊的視頻游戲:PC 和台式游戲已經從2D 進化到3D。手機游戲也會遵循這種趨勢。現在已經出現手機3D工具箱和聽筒。但是,3D是非常資源集中型的。他們要求開發者和圖形設計者都是專家級的。專業的商店最有可能開發這些游戲。  
在手機游戲的早期,大多數開發者都是想要玩轉設備、學習技巧和快速攻關的狂熱分子。但是,隨著更多的開發者加入這個行業,手機游戲已經進化成涉及到專業設計師、構造師、開發者、產品經銷商、律師、和藝術家在內的主導產品。這是行業走向成熟的必然趨勢。盡管在某人的業余時間內要開發和推銷簡單的游戲更加困難,但是更多的專業商店將為許多人提供更多的就業機會。
1.5 手機軟件現狀
在信息社會中,手機及其他無線設備越來越多的走進普通百姓的工作和生活,隨著信息網絡化的不斷進展,手機及其他無線設備上網絡勢在必行。但是傳統手機存在以下弊端:
1.  傳統手機出廠時均由硬件廠商固化程序,程序不能增加、刪除,有了錯誤也不能更新、修改,若要增加新功能必須另換一部手機。
2.  傳統手機訪問互聯網是通過WAP(Wireless Application Protocal),所有網絡資源必須接通網絡才能在線訪問,非常耗時、費用亦很高。
而Java技術在無線應用方面的優勢非常明顯:
1.  應用程序可按需下載,而不是購買由硬件商提供的套件,可升級空間大。
2.  Java技術提供了一個類庫,它使的應用開發商可以創建更為直覺、豐富的用戶界面(GUI);
Java手機網[www.cnjm.Net]3.  Java技術使網絡帶寬的應用更為有效,因為應用程序可以下載到器件上,並在本地運行,僅僅是在連接到服務器時才會占用網絡帶寬。
Java手機網[www.cnjm.Net]基於以上分析,Java手機將是未來手機的發展方向,是業界的熱點。

Java手機網[www.cnjm.Net]1.6 本游戲的未來
看過周潤發主演的《賭神》都知道裡的豪斯是很好玩的,也很有發展前途。一,這個游戲對手機的要求不高;二,這個游戲簡單;三,當這個游戲做成網絡游戲時,可以是各個玩家斗智的平台;要實現這點技術要求並不難。在本設計的基礎上再加上某些技術就可以了:a) 網絡的連接 b) 能讀能存網絡數據庫 c) 牌不再是用隨機產生這麼簡,它應該根據玩家的積分來產生,這樣會更好。
1.7 手機未來的發展方向
手機游戲的盈利主要是由於它們的涉及面很廣。手機已經與現代生活方式緊緊地結合在一起。他們是最普遍攜帶的個人用品中僅次於鑰匙和錢包的東西。傳統的台式機游戲將目標鎖定在低級趣味的人和青少年身上,而手機游戲則每個人都可以訪問的到——隨時,隨地。盡管每個手機游戲都不貴,但是巨大的使用量(如:每人每星期一個新游戲)將使得這個市場商機無限。只要有好的游戲,就會有更廣的使用量。
1.8   游戲業務及J2ME概述
雖然 Java 已經被用到許多企業級軟體上,可是其實骨子裡面還是非常適合用在嵌入式系統之中。Java平台演進到Java2後,Java平台分別針對不同領域的需求被分成四個版本,亦即J2EE、J2SE、J2ME以及JavaCard。其中J2ME定位在消費性電子產品的應用上。這個版本針對資源有限的電子消費產品的需求精簡核心類庫,並提供了模塊化的架構讓不同類型產品能夠隨時增加支持的能力。這個版本的應用層面相當廣泛,會是未來Java平台發展的重點項目。J2ME 在設計其規格的時候,遵循著“對各種不同的裝置而造出一個單一的開發系統是沒有意義的事”這個基本原則。於是 J2ME 先將所有的嵌入式裝置大體上區分為兩種:一種是運算功能有限、電力供應也有限的嵌入式裝置(比方說PDA 、手機);另外一種則是運算能力相對較佳、在電力供應上相對比較充足的嵌入式裝置 (比方說冷氣機、電冰箱、電視機上盒 (set-top box))。因為這兩種型態的嵌入式裝置,所以Java 引入了一個叫做Configuration 的概念,把上述運算功能有限、電力有限的嵌入式裝置定義在Connected Limited Device Configuration(CLDC)規格之中;而另外一種裝置則規范為 Connected Device Configuration(CDC)規格。也就是說, J2ME 先把所有的嵌入式裝置利用Configuration 的概念區隔成兩種抽象的型態。J2ME平台被認為是最傑出的手機游戲平台,它為開發者、設備制造商、網絡通信公司和消費者廣泛接受。它有一些非常重要的特征對所有組織都有益。因為J2ME應用在不同設備上都是便攜式的,他們常常可在網絡上下載和執行。如果沒有正確的防范,它則為用戶和無線通信公司冒著無數個安全的風險。幸運的是,Java被設計成一種安全的語言。所有字節碼應用在執行之前都要校驗;JVM在執行過程中監督應用的安全性和存儲違反問題。MIDP v2 運行時間包括一個完全特征化的、基於域的安全管理員,它在應用的數字簽名者鑒別的基礎上賦予應用API級許可。
縱觀IT產業的歷史,就像軍事的發展時常推動計算機的演化一樣,計算機游戲已經成為技術創新背後的動力之一。計算機游戲者渴望更加強大的硬件計算能力;渴望不受不同的軟件的限制——無論是將圖形強制在人工智能(AI)上 還是網絡安全性。游戲開發者和玩家常常是前沿計算機技術的最早的采用者。由於他們的創新天性,游戲不再是由大型采購公司控制的技術產品——游戲領域總是有充足的空間給那些在這方面有天分的單個創新者。
Java手機網[www.cnjm.Net]手機游戲的盈利主要是由於它們的涉及面很廣。手機已經與現代生活方式緊緊地結合在一起。他們是最普遍攜帶的個人用品中僅次於鑰匙和錢包的東西。傳統的台式機游戲將目標鎖定在低級趣味的人和青少年身上,而手機游戲則每個人都可以訪問的到——隨時,隨地。盡管每個手機游戲都不貴,但是巨大的使用量(如:每人每星期一個新游戲)將使得這個市場商機無限。但是,對於開發者來說,將控制台游戲遷移到手機游戲工程很大。因為他們所面向的對象、生活方式和分布式模型都有著極大的區別。

二  開發環境及相關技術的介紹

2.1 Java語言的特點
1. 平台無關性
Java引進虛擬機原理,並運行於虛擬機,實現不同平台之間的Java接口。使
用Java編寫的程序能在世界范圍內共享。Java的數據類型與機器無關。
2. 安全性
Java手機網[www.cnjm.Net]Java的編程類似C++,但捨棄了C++的指針對存儲器地址的直接操作,程序運
行時,內存由操作系統分配,這樣可以避免病毒通過指針入侵系統。它提供
了安全管理器,防止程序的非法訪問。
3. 面向對象
Java手機網[www.cnjm.Net]Java吸收了C++面向對象的概念,將數據封裝於類中,實現了程序的簡潔性和
便於維護性,使程序代碼可以只需一次編譯就可反復利用。
4. 分布式
Java建立在TCP/IP網絡平台上,提供了用HTTP和FTP協議傳送和接收信息
的庫函數,使用其相關技術可以十分方便的構建分布式應用系統。
5. 健壯性
Java致力與檢查程序在編譯和運行時的錯誤,並自動回收內存,減少了內存出
錯的可能性。Java取消了C語言的結構、指針、#define語句、多重繼承、goto
Java手機網[www.cnjm.Net]語句、操作符、重載等不易被掌握的特性,提供垃圾收集器自動回收不用的內存空間。

2.3  J2ME 是什麼?
據J2ME應用程序調用的API,J2ME應用程序分為標准應用程序和不易移植的應用程序兩種。
據J2ME應用程序調用的API,J2ME應用程序分為標准應用程序和不易移植的應用程序兩種。
術語:
CDC:連接設備配置
CLDC:連接限制設備配置
JRE:Java運行環境
MIDP:Mobile Information Device Profile規范
OTA:Over The Air
非OTA:數據線、藍牙(Bluetooth)、紅外線(IrDA)、多媒體信息服務(MMS)、Email附件
2.3  J2ME智能客戶端  

J2ME平台被認為是最傑出的手機游戲平台,它為開發者、設備制造商、網絡通信公司和消費者廣泛接受。它有一些非常重要的特征對所有組織都有益

2.4 J2ME 總體架構
J2ME 使用配置和簡表定制 Java 運行時環境 (JRE)。作為一個完整的 JRE,J2ME 由配置和簡表組成,配置決定了使用的 JVM,而簡表通過添加特定於域的類來定義應用程序。
配置將基本運行時環境定義為一組核心類和一個運行在特定類型設備上的特定 JVM。我們將在 J2ME 配置一章中詳細討論配置。
簡表定義應用程序;特別地,它向 J2ME 配置中添加特定於域的類,定義設備的某種作用。我們將在 J2ME 簡表一章中深入介紹簡表。
下面的圖表描述了不同的虛擬機、配置和簡表之間的關系。它同時把 J2SE API 和它的 Java 虛擬機進行了比較。雖然 J2SE 虛擬機通常被稱為一種 
 
JVM,但是 J2ME 虛擬機、KVM 和 CVM 都是 JVM 的子集。KVM 和 CVM 均可被看作是一種 Java 虛擬機 -- 它們是J2SE JVM 的壓縮版,並特定於 J2ME。
移動通信的時代即將來臨,通信相關待業變得前景可期,而除了移動通信的主要通信工具——手機,其功能越來越強大之外,有更多的廠商相繼投入移動通信設備的生產與開發,其平台和操作系統的復雜度比目前混亂的PDA有過之而不及,除了SymBian 針對手機推出操作系統 SymBian OS(過去稱做EPOC,)操作系統之外,微軟也針對手機推出操作系統 Smartphone 2002 (Stinger),但是日前市面上的手機仍以使用廠商自行開發的操作系統者居多。
平台的復雜紛亂對一般用戶當然沒什麼影響,但是對於程序開發人員來說,這麼多不同的程序發展平台,光看完頭就昏了。如果每個平台都有自己的程序寫法以及程序庫,那麼光是看上面這些平台至少就要學習五種以上程序的寫法。當然,只專精一種平台當然是很好的事情。可是程序員不禁要說:“如果我們寫出來的軟件可以在不經過修改源代碼的情況下就能夠在這些平台上執行,那不是更完美嗎?“對程序開發人員來說,這樣的投資報酬率當然是最大的。
要在那麼多平台上開發程序,對程序員來說的確是很大的挑戰,如果要把所有的時間和精力放在軟件的可用性上,那麼相對而言很多時候我們根本沒有那麼多時間撰寫各種平台的程序。要解決這個問題,一般來說程序員會選用一個可以跨平台的Framework來達成至少source code level的跨平台。利用Java的“Write once,run anywhere”特性,我們可以真正達到程序只要寫一次,拿到任何平台上都可以執行。

利用Java撰寫手機上的程序當然有其缺點,最廣為人知的可能就是執行效率的問題,Java在執行速度這個議題上一直讓人诟病。不過筆者認為,隨著技術的發達,將會有更快更省電的嵌入系統專用CPU出現,Java One中也傳出將針對J2ME開發專用芯片,讓Java在 手機上的程序可以跑得更快,因此效率上的總是其實是可以忽略的。更何況,當Sun在設計J2ME的時候,也用了很多方式企圖加快Java 在手機上的執行速度。
因此,目前的移動通信設備大廠幾乎采用J2ME平台。搭建J2ME 環境:
2.5  簡單環境的搭建:

1、  下載JDK和J2ME無線工具包(www.sun.com.cn)
安裝SUN JDK:j2sdk-1_4_0_03-Windows=i386
安裝SUN J2ME SDK:J2ME_wireless_toolkit-1_0_3-win

2     關於Wireless Tool Kit
WTK(Wireless Tool Kit)是Sun公司針對J2ME推出的用於手機和Palm等
移動設備的開發包,是除手機廠商的專用開發包外唯一的手機模擬器開發包。
它通用性高,開發出的應用程序可保證能運行在大部分設備上,而不像專用
廠商具有一定的不兼容性。雖然它沒有強大的功能和完善的調試手段,但它
提供運行模擬器的最基本組件,是其他IDE需集成采用的必備元素。

3, 用於手機游戲開發的環境不是只建立一個 java sdk 就可以了,它還需要了一個一個庫類,叫 java toolkit。首先安裝 java sdk 再在原來的目錄下安裝Java toolkit這個新的環境就可以滿足我們的需要了。然後我們編寫一個最簡單的程序用來驗證這個環境是否可以用來編寫我們的手機程序。

編寫以下代碼:
保存成 Hello.Java 文件。

import Javax.microedition.midlet.*;
import Javax.microedition.lcdui.*;
public class Hello extends MIDlet  
{ private Display display;
Java手機網[www.cnjm.Net]public Hello()  
{ display = Display.getDisplay(this); }
public void startApp() {
       TextBox t = new TextBox("Hello MIDlet", "Hello MIDP!", 256, 0);
       display.setCurrent(t);
Java手機網[www.cnjm.Net]   }
public void pauseApp() {
   }
public void destroyApp(boolean unconditional) {
   }
}
啟動Ktoolbar 新建一個工程,取名 Hello 。把以上文件拷到 Hello 文件的目錄編譯。能通過編譯並能運行,說明這個開發環境就能滿足我們的需要了。
2.6 MIDP應用程序:

MIDP應用程序是指遵循由應用程序主體(Jar文件)和應用程序描述文件(Jad文件)組成。按部署方式可分OTA和非OTA兩種。
MIDlet:是Jave一個類,擴展了Javax.microediton.midlet.MIDlet抽象類。MIDlet生命周期分3種狀態:運行狀態,暫停狀態,銷毀狀態等。
2.6 Java Appication Manager
手機中負責調配程序運行資源的管理後台是Java Application Manager。它所使用的傳輸媒體可以是紅外線、網絡、以及其他可用來傳輸的媒體。Java Application Manager 會從網絡上下載代表該Application Suite 的JAR 檔,接著在手機上安裝此MIDlet Suite,
然後在手機開始執行該應用程序。整個詳細的運作流程如圖2-1所示。
Java手機網[www.cnjm.Net] 
Java手機網[www.cnjm.Net]2.7 預先審核:
審核動作一般在PC上執行,速度可以接受。為了是對安全的考慮,任何來自本地或者遠程機器,都必須經過Byte Code審核器的驗證,以防止程序在傳輸途中遭到惡意更改。如圖
 
2.8 J2ME、J2SE 與 J2EE 之間的比較:
下面的圖表描述了支持 J2ME 應用程序的設備,同時說明了 J2ME 適合 Java 平台之處:
 
三   J2ME 手機游戲需求分析
3.1  本程序需解決的有關技術問題
1.  游戲程序是一項精度要求很高的程序系統,因為其代碼利用率很高。一個實時運行的最終作品,每秒都會運行成千上萬行程序,繪圖事件、鍵盤事件都會以極高的頻率在後台等待響應,若有絲毫的差別都將很容易導致程序在運行不久後可能出現嚴重錯誤,甚至死循環。因此,其邏輯設計應當相當嚴謹,需將所有可能發生的事件及意外情況考慮在設計中。

2.  游戲中為了美觀,適用性強,可能需要采用外部文件引入的圖片貼圖,有關貼圖,在MIDP2.0中提供了用於增強游戲功能的game包,使得解決靜態或動態、畫面背景、屏幕刷新的雙緩沖等都有較好的解決方案。
3.  一開始就把牌全部分配好,這樣就可以簡單而有效地避免了牌的重復,也可以大大地簡化了程序代碼的編寫。
4.  牌的轉化可以用一個函數來實現,這樣就可以使代碼更模塊化,利用也就可以更高。
5.牌慢慢移動的實現。牌的移動是用線程來實現的,用Thread.sleep()
這個函數來作時間延遲,讓坐標變量緩慢地變化。然後通過刷新畫圖,就會使人覺得牌是在緩慢地移動。
6.是否是要牌還是放棄(認輸),它通過向右鍵(要牌)和向左鍵(放棄)來操作的。當點擊向右鍵時,發生點擊事伯,變量發生相應的變化,然後觸發畫圖事件。
7.當玩家都跟到5張牌時,就要判斷牌的大小了,它通過多次循環,來確定其大小。
8.  Java是基於虛擬機的半解釋型編譯系統,其執行效率較C++等完全編譯後的程序會低很多,程序如果不進行精簡和優化,將可能導致運行的不流暢。除開發過程中對結構上的控制、變量的使用、算法的優化等優化外,還可以使用混淆器(Obfuscator)進行程序打包後的優化。
以上相關技術細節和整體流程將分別在以下小節闡述。
3.2  程序流程圖
MIDlet suite是MIDP應用程序的最小單位,JAM負責將手機內的MIDlet suite以圖形
v 化的方式呈現,讓用戶能夠選取欲執行的MIDlet suite,一旦選取了某個MIDlet suite,操作系統就會激活KVM執行裡面的MIDlet。MIDlet及相關的支持類組成了MIDP應用程序的實際內容。每個MIDlet都必須繼承Javax.microedition.midlet.MIDlet這個抽象類。在MIDP規格中定義了MIDlet的生命周期,以及可以存在的三種狀態,包括Paused、Active以及Destroyed,每一個MIDlet在任何時刻只可能處於其中的一個狀態這
Java手機網[www.cnjm.Net]v 三種狀態的轉換關系如圖所示:
 
本程序采用面向對象的設計模式,對游戲中的所有物體賦予對象的概念和屬性。運行程序後允許用戶選擇執行選項菜單,在開始游戲後將先從外部文件載入牌的圖文件,對背景的所有物體進行繪圖。在主程序運行的線程中,畫面刷新將以一定的頻率采用雙緩沖技術對屏幕重繪,實時反映整個游戲的進行狀態。用戶控制的牌運行在主線程中,隨屏幕刷新的頻率而移動。牌將在游戲開始時逐漸新增線程,每增加一個牌對象就新增加一條線程,一旦線程數滿到最大值(本程序暫設置最大值為幾千多個),就不允許線程的再增加。這個線程問題就是本設計的一個 bug。
本程序主要的流程如圖3—2所示:
 
流程簡略解釋:
程序一開始執行是先從主類 test.Java 來開始。這個類從 MIDlet 類繼承過
來,在程序的開始函數 startApp() 中我用
Navigator.current = Navigator.MAIN_SCREEN; 這個等式把程序的執行轉到
MainScreen.Java 文件(程序的畫面)來。而這個類繼承 List ,這個 List 類可以更方便地控制程序的選擇。在這個文件中列出一個菜單供用戶去選擇,如下:

開始
設定
版權聲明
離開

當點擊開始時,程序轉到 GameScreen 這個類去。GameScreen 這個類繼承 Canvas,Canvas 專門是用來控制游戲的。裡面包括屏幕的繪圖,一些變量的初始化。
當點擊設定時,程序轉到SetScreen 這個類。這個類用於登錄幫助網站的,當然這個是需要網絡支持的。
當點擊版權聲明時,程序轉到 CopyScreen 這個類,這個類繼承 Alert,它用於描述版權的一些信息。
當點擊離開時,程序退出 test 類。

3.3 繪圖與MIDP2.0新增的GameCanvas包

3.3.1  提供低級繪制的Canvas類
為了能有程序開發人員控制接口的外觀和行為,需要使用大量的初級用戶接口類,尤其在游戲程序中,幾乎完全依賴的就是Canvas抽象類進行繪圖。從程序開發的觀點看,Canvas類可與高級Screen類交互,程序可在需要時在Canvas中摻入高級類的組件。Canvas提供了鍵盤事件、指點桿事件(如果設備支持),並定義了允許將鍵盤按鍵映射為游戲控制鍵的函數。鍵盤事件由鍵代碼指定,但這樣控制游戲會導致缺乏通用性,並不是每個設備的鍵盤布局都適合游戲的操作。應當將鍵代碼轉換為游戲鍵的代碼,以便硬件開發商能定義他們自己的游戲鍵布局。本程序中,操縱用戶坦克運行的按鍵都定義為游戲控制鍵,這樣便能適應所有的機器。

Java手機網[www.cnjm.Net]3.3.2 Graphics類
Graphics類提供了簡單的2D繪圖功能。它具有24位深度色彩的繪制能力,以三原色分別各占一個字節表示其顏色。程序只能在paint()函數中使用Graphics繪制,GameCanvas可調用getGraphics()函數直接繪制在緩沖區上,可以在任何時間請求傳輸到前台。其對象會被傳給Canvas的paint()函數,
以便最終顯示。
3.3.3 PNG格式
PNG(Portable Network Graphics)格式是MIDlet唯一支持的圖象格式,PNG具體格式由PNG Specification,Version 1.0定義的。PNG格式提供透明背景的圖象,這對繪制游戲畫面和被操縱主角極有幫助。坦克之間或與障礙物碰撞時就不會因為背景有特定的顏色,顯示出的效果像貼上的圖片而缺乏真實感,物體之間輕微重疊時最上層圖片也不會覆蓋超過其有效象素外的部分。
PNG格式圖片中包含許多定義其圖片特性的冗余部分(Chunks)。這些代碼包含在每一個單獨的png格式圖象中,然而如果將多個png圖象合並在一張幅面稍大一些的整圖中,多個chunks就可以得到精簡,圖片的大小可以得到控制。使用Image
類中的createImage函數可從整圖中分割出所需要的元素。在Game包中的TiledLayer和Sprite類都整合了這樣的
功能。本程序中的地圖元素都集成在一張tile.png圖片中,實現了方便的管理和程序體積的精簡。

3.3.4 有關繪圖的一些技術
在沒有MIDP2.0前,進行游戲繪圖一般需要手動編程使用雙緩沖。需要在paint()方法內所想要畫的圖形畫在一張預先准備好的背景,等所有繪圖操作都完成後再將背景的數據拷貝到實際的屏幕上。Image類提供了一個建立背景的靜態方法createImage(int width, int height),再利用getGraphics()方法取得屬於這個背景的Graphics對象,所進行的繪圖操作都會作用在背景上,等到全部的繪圖操作完成後,再調用drawImage()方法將背景的數據復制到實際顯示的屏幕上。
這樣的技術在繪制動畫時特別有用。繪制動畫時經常需要不斷地更新畫面,而更新畫面的操作就是先將屏幕以fillRect()的方式清除,再將下一張圖片畫在屏幕上,然而反復的清除及重繪會造成屏幕的閃爍現象(flicker),因此使用雙重緩沖的好處就是在背景進行這個清除及重繪的操作,再將完成的繪圖拷貝到屏幕上,由於用戶看不到清除的操作,因此就不會出現閃爍的現象了。不過在某些MIDP的實現上已經加上了雙重緩沖的支持,因此在處理前應先利用Canvas類的isDoubleBuffer()方法來判斷。

3.7  內存使用的最佳化
通常在MIDP應用程序的手機執行環境中,所牽涉的內存有下列三種:
*應用程序存儲內存
*RecordStore存儲內存
*執行時期內存(Java Heap)
其中前兩種是持久性的內存,關閉電源後還能保持數據的正確性,通常這兩種內存所能存儲的容量是合並計算的,這個上限對每種手機都不一樣,大部分在一兩百KB內。在這樣的情況下需要在不影響原有功能的情況下適當的縮減JAR文件的大小,除了可以克服內存空間的限制外,也能大幅度縮短下載的時間(費用也降低了),勢必會有更多的人願意下載所開發的程序。其方法有:
Java手機網[www.cnjm.Net]第一,就是盡量縮短命名的長度。在應用程序內,對於所建立的類、接口、方法及變量名而言,都需要賦予一個識別的名稱,所命名的名稱每多一個字符就會在類文件內多產生一個字節,對於一個較復雜的應用程序而言就會增加為數不小的數據量。所有這些可以借助混淆器來幫助實現。
第二是減少復雜的程序結構,為一些共同的行為建立一個抽象類(Abstract Class) 來表示繼承的子類的共通性。
第三是減少圖形數據的大小。將PNG格式的小分辨率圖象合並在一張大的高分辨率圖象中,由於減少了chunks,將比合並前的總大小減少許多。
3.6  混淆器(Obfuscator)的使用
Java 語言並沒有完全編譯成二進制可執行文件,編譯出的.class文件是一種介於源程序和二進制之間的一中基於半解釋的字節碼,需要虛擬機來執行。它包括了所有的信息。然而這樣會導致.class很容易被反編譯為源代碼,從而不能保護作者的知識成果。目前流行的如decode,JAD等反編譯工具可以以很快的速度生成源文件。如果不加以施行有效的措施,將造成嚴重的後果。
Java手機網[www.cnjm.Net]

由此引入混淆器的概念。混淆器將代碼中的所有變量、函數、類的名稱變為簡短的英文字母代號,如果缺乏相應的函數名指示和程序注釋,即使被反編譯,也將難以閱讀。
   混淆器的作用不僅僅是保護代碼,它也有精簡編譯後程序大小的作用。由於以上介紹的減少變量、函數的命名長度的關系,編譯後也會從.class文件中減少這些冗余的信息。混淆後,體積大約能減少25%,這對當前費用較貴的無線網絡傳輸是有一定意義的。
為了能與各種IDE集成,就像Java2 SDK一樣,混淆器采用命令行參數的形式,以便可被其調用。目前流行的Obfuscator有RetroGuard等。

3.7  模擬器的相關調試
IDE整合的Wireless Tool Kit提供了許多在運行時監視運行狀態的工具。 包括內存狀況的檢測(手機上的內存空間十分有限,必須時刻關注機載內存是否大於程序所能使用到的最大可能的內存空間),網絡狀況的檢測,運行函數的跟蹤等。如圖3-4,是內存跟蹤測試隨時間變化的調試器。其中,允許強制垃圾回收(Garbage Collection)。由於Java語言中,不像許多其他的如C++語言,不需要指定回收函數中特定不使用的資源,資源回收機制將自動清空無效變量占用的空間。在程序運行中也可以調用System類的gc()函數手動收回廢棄的內存。

四   程序分析和編寫手機代碼

4.1  游戲進入前的選擇
每個MIDlet程序都必須有一個主類,該類必須繼承自MIDlet。它控制著整個程序的運行,並且可以通過相應函數從程序描述文件中獲取相關的信息。該類中擁有可以管理程序的創建、開始、暫停(手機中很可能有正在運行程序卻突然來電的情況,這時應進入暫停狀態。)、結束的函數。
本設計程序進入時,首先載入畫面的不是游戲運行狀態,而是提供選項,當選擇 開始 時正式運行。因此,在 MainScreen的構造函數中分配了List類,即選項畫面的內存空間。在startApp()函數中,隨即調用了Displable的setCurrent()函數將當前屏幕設置為Navigator.MAIN_SCREEN。在 版權聲明 界面前,建造了一個Alert類。Alert對象用於顯示提示、警告,還有版權信息等告之用戶信息的臨時閃現的屏幕,它可作為setCurrent的參數,提前顯示在最終需要顯示的屏幕前。當程序轉到 GameScreen 時,畫面將永久顯示游戲本身,直到用戶點擊相應按鈕手動結束。但是當顯示的畫面元素超過一屏大小時,將自動轉換為永久狀態。
GameScreen 繼承了接口commandListener,這樣,就可以使用高級界面的Command按鈕。繼承了commandListener的類必須擁有commandAction(),以決定對按鍵采取什麼樣的行為。即按鈕事件觸發後需執行的函數。在設置好commandlistener後,需要調用setCommandListener()以將按鈕事件激活。鍵盤事件中,可用getCommandType()返回的Command類型來確定選擇的是什麼按鈕。MainScreen繼承了List類,用於顯示列表選項,使用其append()函數可將選項加入到列表中。getSelectIndex()可檢測到選擇的項目的序號,序號從0開始遞增。其中,當選擇第一項時將載入正式游戲畫面GameScreen類,第二項將顯示轉到設定畫面,第三項用來顯示用戶信息,版權聲明等。第四項是離開游戲選項。

4.2  主游戲邏輯及其涉及到的若干類
4.2.1 程序的菜單選項
Java手機網[www.cnjm.Net]這個寫在 MainScreen.Java 文件中,這個類繼承 List 。同時也繼承了接口commandListener,這樣,就可以使用高級界面的Command按鈕。繼承了commandListener的類必須擁有commandAction(),以決定對按鍵采取什麼樣的行為。即按鈕事件觸發後需執行的函數。在設置好commandlistener後,需要調用setCommandListener()以將按鈕事件激活。用append 方法來加入菜單:
append("開始",null);
append("設定",null);
append("版權聲明",null);
append("離開",null);
setCommandListener(this);
再用 getString(int) 函數來獲得菜單的選項。
MainScreen.Java 文件:

import Javax.microedition.lcdui.*;
public class MainScreen extends List implements CommandListener
{
private static Displayable instance;
synchronized public static Displayable getInstance()
Java手機網[www.cnjm.Net]{
if(instance == null)
Java手機網[www.cnjm.Net]instance = new MainScreen();
return instance;
}
Java手機網[www.cnjm.Net]private MainScreen()
{
super("進入Game",IMPLICIT);
/// 菜單選擇
append("開始",null);
append("設定",null);
append("版權聲明",null);
append("離開",null);
// 事件偵聽
setCommandListener(this);
}
public void commandAction(Command c,Displayable s)
Java手機網[www.cnjm.Net]{
// 事件偵聽
String cmd= getString(getSelectedIndex());
// 把得到的值傳給程序控制器,用程序控制器來決定指引程序的執行。
Java手機網[www.cnjm.Net]Navigator.flow(cmd);
}
}

4.2.2 游戲的設定
這個寫在 SetScreen.Java 文件中,而這個類繼承 Form 類,同時也繼承了接口commandListener,這樣,就可以使用高級界面的TextField按鈕。繼承了commandListener的類必須擁有commandAction(),以決定對 TextFIEld 值獲取采等行為。在設置好commandlistener後,需要調用setCommandListener()函數來把值傳入程序中。
SetScreen.Java 文件:
import Javax.microedition.lcdui.*;
public class SetScreen extends Form

//繼承 CommandListener 接口
implements CommandListener
Java手機網[www.cnjm.Net]{
private static Displayable instance;
synchronized public static Displayable getInstance()
{
if(instance == null)
instance = new SetScreen();
Java手機網[www.cnjm.Net]return instance;
}
// 定義 TextFIEld (文本輸入框)
TextFIEld url;
Gauge volume;
Java手機網[www.cnjm.Net]private SetScreen()
{
super("設定");
url = new TextFIEld("請輸入服務器位置","socket://127.0.0.1:99",40,TextFIEld.URL);
append(url);
volume = new Gauge("音量",true,10,3);
// 軟鍵菜單
addCommand(new Command("輔助說明",Command.HELP,1));
addCommand(new Command("返回",Command.BACK,1));
// 事件偵聽
setCommandListener(this);
}
public void commandAction(Command c,Displayable s)
{
Navigator.flow(c.getLabel());
}
}

4.2.3 游戲中的幫助和程序控制器
首先調用 HelpScreen 類,然後賦一個值:輔助說明給 Navigator 類,當Navigator接收到這個值時,就顯示幫助字符串。
HelpScreen.Java
import Javax.microedition.lcdui.*;
public class HelpScreen extends Form implements CommandListener
{
public HelpScreen(String c)
{
super("輔助說明");
append©;
addCommand(new Command("返回",Command.BACK,1));
setCommandListener(this);
Java手機網[www.cnjm.Net]}
public void commandAction(Command c,Displayable s)
{
Navigator.flow(c.getLabel());
}
}
這個寫在Navigator.Java 裡,它接收 SetScreen.,MainScreen等類傳過來的值。然後根據它觸發的按鈕事件,來調用相對應的事件。
//Navigator.Java
import Javax.microedition.lcdui.*;
import Javax.microedition.midlet.*;
import Java.util.*;
Java手機網[www.cnjm.Net]public class Navigator
{
final public static int MAIN_SCREEN = 1;
final public static int GAME_SCREEN = 2;
final public static int SET_SCREEN  = 3;
final public static int GAME_HELP_SCREEN = 4;
final public static int SET_HELP_SCREEN = 5;
public static MIDlet midlet;
public static Display display;
public static int current;
// 自定義一個類
// 重載函數
public static void show(Object obj)
{
switch(current)
{
case MAIN_SCREEN:
display.setCurrent(MainScreen.getInstance());
break;
case GAME_SCREEN:
display.setCurrent(GameScreen.getInstance());


break;
case SET_SCREEN:
display.setCurrent(SetScreen.getInstance());
break;

case GAME_HELP_SCREEN:
display.setCurrent(new HelpScreen((String)obj));
break;
case SET_HELP_SCREEN:
display.setCurrent(new HelpScreen((String)obj));
break;
}
}
public static void flow(String cmd)
{
Java手機網[www.cnjm.Net]switch(current)
{
Java手機網[www.cnjm.Net]case MAIN_SCREEN :
if(cmd.equals("開始"))
Java手機網[www.cnjm.Net]{
current = GAME_SCREEN ;
show(null);
}
else if(cmd.equals("設定"))
{
current = SET_SCREEN;
show(null);
}
else if(cmd.equals("版權聲明"))
{
display.setCurrent(CopyScreen.getInstance());
}
else if(cmd.equals("離開"))
{
Java手機網[www.cnjm.Net]midlet.notifyDestroyed();
}
break;
case GAME_SCREEN :
if(cmd.equals("輔助說明"))
{
current = GAME_HELP_SCREEN;
show("游戲的操作方式:向右鍵要牌,向左鍵放棄!順子並同花最大,其次四張相同的牌,順子,再次三張相同的牌和兩個到順子,再次到同花.");
}
else if(cmd.equals("返回"))
{
current = MAIN_SCREEN;
Java手機網[www.cnjm.Net]show(null);
}
break;
Java手機網[www.cnjm.Net]
case SET_SCREEN :
if(cmd.equals("輔助說明"))
{
current = SET_HELP_SCREEN;
show("設定方式");
}
else if(cmd.equals("返回"))
{
current = MAIN_SCREEN;
show(null);
}
break;
case GAME_HELP_SCREEN :
if(cmd.equals("返回"))
{
current = MAIN_SCREEN;
Java手機網[www.cnjm.Net]show(null);
}
break;
case SET_HELP_SCREEN:
if(cmd.equals("返回"))
{
current = SET_SCREEN;
show(null);
}
break;
}
}
}
4.2.4 游戲版權聲明
// CopyScreen.Java
import Javax.microedition.lcdui.*;
Java手機網[www.cnjm.Net]public class CopyScreen extends Alert
{
private static Displayable instance;
synchronized public static Displayable getInstance()
{
if(instance == null)
instance = new CopyScreen();
return instance;
Java手機網[www.cnjm.Net]}

private CopyScreen()
{
super("版權聲明");
// 聲明字段
setString("乘風破浪需要勇氣!此程序版權屬阿朗and海波所有");
setType(AlertType.INFO);
setTimeout(Alert.FOREVER);
}
}
4.2.5 游戲的主要程序
// GameScreen.Java
下面根據程序的先後順序對游戲的主程序作簡單的解釋。
Java手機網[www.cnjm.Net]牌是用一個隨機函數來獲得的,在牌的開始前就已經分配好了,當然,這是本設計雞脅的地方。這缺少了變化,也使游戲缺了好玩性,少了人智化,這會在下個版本中改正過來的。在下個版本中,版的分配是在你要牌後才產生,而且它的產生是根本你的總分,你的等級而產生。當你的總分越高你的等級越高,得到你想要的牌的機率就會越高。
下面是本設計中分配牌的隨機函數:
for(int i=0; i < 10; i++) {
//使用隨機數來決定撲克牌(這種方法要改進)
Card[i] = rdm.nextInt() % 51;
//System.out.println(Card[i]);
if(Card[i] < 0)  
{
//當隨機出現負數的時候
Card[i] = Card[i] * (-1);
}
//檢查是否重復
for(int j=0; j < i; j++)
{
if(Card[i] == Card[j])  
{
Java手機網[www.cnjm.Net]//若有相同的撲克牌存在時
//再次隨機抽牌
i--;
break;
}
}
}

Java手機網[www.cnjm.Net]由於對牌的分配是 0到 51 來表示的,所以必需對牌進行轉換:它是用這個數除4取余,得到這個牌的色(紅心,方塊等),除12取余得這具牌的點數:
////// 實現牌的轉換
// Card[i] 開始分配的點數
// Num[] 表示牌的點數
// kind[] 表示牌的色
for(int i = 0;i < 10; i++)
{
if( Card[i]%13 == 0)
{
Num[i] = "2";
}
if( Card[i]%13 == 1)
{
Num[i] = "3";
}
if( Card[i]%13 == 2)
{
Java手機網[www.cnjm.Net]Num[i] = "4";
}
if( Card[i]%13 == 3)
{
Num[i] = "5";
}
if( Card[i]%13 == 4)
Java手機網[www.cnjm.Net]{
Num[i] = "6";
}
if( Card[i]%13 == 5)
{
Num[i] = "7";

}
Java手機網[www.cnjm.Net]if( Card[i]%13 == 6)
Java手機網[www.cnjm.Net]{
Num[i] = "8";
}
if( Card[i]%13 == 7)
{
Java手機網[www.cnjm.Net]Num[i] = "9";
}
Java手機網[www.cnjm.Net]if( Card[i]%13 == 8)
{
Num[i] = "10";
Java手機網[www.cnjm.Net]}
if( Card[i]%13 == 9)
{
Num[i] = "J";
}
if( Card[i]%13 == 10)
{
Java手機網[www.cnjm.Net]Num[i] = "Q";
}
if( Card[i]%13 == 11)
{
Num[i] = "K";
}
if( Card[i]%13 == 12)
{
Num[i] = "A";
}
}
////// 牌的種類
for(int i = 0; i < 10 ; i++)
{
if(Card[i]/13 == 0)
{
///// 黑桃
Kind[i] = 0;
}
if(Card[i]/13 == 3)
{
Java手機網[www.cnjm.Net]///// 黑桃
Kind[i] = 3;
}
if(Card[i]/13 == 2)
{
///// 紅心
Kind[i] = 2;
}
if(Card[i]/13 == 1)
{
///// 梅花
Kind[i] = 1;
}
}

把得到的版繪畫在手機屏幕上:
它是用 paint() 函數來實現的,慢慢移動的鏡頭用線程的完成。這會使這個線程產生多個線程,這是程序要改進的地方。
// bCard1 用於控制程序的運行,當牌已經移動到目標地,就使bCard1= false
Java手機網[www.cnjm.Net]if ( bCard1)
{
//對家

if(x <=12)
{
bCard1 = false;
bCard2 = true;
Java手機網[www.cnjm.Net]b2 = true;
bb1 = true;
}
doThreadStart();
g.setColor(255,255,255);
g.fillRect(x - 2,70,25,40);
g.setColor(0,0,0);
g.drawRect(x - 2,70,25,40);
// 自家
if( Kind[1] == 3)
Java手機網[www.cnjm.Net]{
g.setColor(255,255,255);
g.fillRect(x - 2,120,25,40);
g.setColor(0,0,0);
g.drawString(Num[1],x,120,g.TOP|g.LEFT);
g.drawImage(king1,x - 2,133,g.TOP|g.LEFT);
g.setColor(0,0,0);
g.drawRect(x - 2,120,25,40);
Java手機網[www.cnjm.Net]}
if(Kind[1] == 2)
{
g.setColor(255,255,255);
g.fillRect(x - 2,120,25,40);
g.setColor(255,0,0);
g.drawString(Num[1],x,120,g.TOP|g.LEFT);
g.drawImage(king2,x - 2,133,g.TOP|g.LEFT);
g.setColor(0,0,0);
Java手機網[www.cnjm.Net]g.drawRect(x - 2,120,25,40);
}

if(Kind[1] == 1)
{
g.setColor(255,255,255);
g.fillRect(x - 2,120,25,40);
g.setColor(0,0,0);
Java手機網[www.cnjm.Net]g.drawString(Num[1],x,120,g.TOP|g.LEFT);
Java手機網[www.cnjm.Net]g.drawImage(king3,x - 2,133,g.TOP|g.LEFT);
g.setColor(0,0,0);
g.drawRect(x - 2,120,25,40);
}
if(Kind[1] == 0)
{
Java手機網[www.cnjm.Net]g.setColor(255,255,255);
g.fillRect(x - 2,120,25,40);
g.setColor(255,0,0);
g.drawString(Num[1],x,120,g.TOP|g.LEFT);
g.drawImage(king4,x - 2,133,g.TOP|g.LEFT);
g.setColor(0,0,0);
g.drawRect(x - 2,120,25,40);
}
repaint();
}
// 畫第一張牌:
// 當移動到目標後,用以下來繪出這張牌。
if ( bb1)
{
Java手機網[www.cnjm.Net]g.setColor(255,255,255);
g.fillRect(10,70,25,40);
Java手機網[www.cnjm.Net]// 自家
if( Kind[1] == 3)
{
g.setColor(255,255,255);
g.fillRect(10,120,25,40);
g.setColor(0,0,0);
g.drawString(Num[1],12,120,g.TOP|g.LEFT);
g.drawImage(king1,10,133,g.TOP|g.LEFT);
g.setColor(0,0,0);
g.drawRect(10,120,25,40);
}
if(Kind[1] == 2)
{
g.setColor(255,255,255);
g.fillRect(10,120,25,40);
Java手機網[www.cnjm.Net]g.setColor(255,0,0);
g.drawString(Num[1],12,120,g.TOP|g.LEFT);
g.drawImage(king2,10,133,g.TOP|g.LEFT);
g.setColor(0,0,0);
g.drawRect(10,120,25,40);
}
if(Kind[1] == 1)
{
Java手機網[www.cnjm.Net]g.setColor(255,255,255);
Java手機網[www.cnjm.Net]g.fillRect(10,120,25,40);
g.setColor(0,0,0);
g.drawString(Num[1],12,120,g.TOP|g.LEFT);
g.drawImage(king3,10,133,g.TOP|g.LEFT);
g.setColor(0,0,0);
g.drawRect(10,120,25,40);
}

if(Kind[1] == 0)
Java手機網[www.cnjm.Net]{
g.setColor(255,255,255);
g.fillRect(10,120,25,40);
g.setColor(255,0,0);
g.drawString(Num[1],12,120,g.TOP|g.LEFT);
g.drawImage(king4,10,133,g.TOP|g.LEFT);
g.setColor(0,0,0);
g.drawRect(10,120,25,40);
}
Java手機網[www.cnjm.Net]}
// 以上調用了 drawImage 這個函數,這個函數必須先把圖片加入程序中:
try  
{
king1 = Image.createImage("/spade.png");
king2 = Image.createImage("/heart.png");
king3 = Image.createImage("/clover.png");
king4 = Image.createImage("/dia.png");
}
Java手機網[www.cnjm.Net]catch(Exception e) {}

// 重載線程函數,它通過不斷的調用線程來使程序,改變x 坐標,產生移動的效果。
private void doThreadStart()  
{
new Thread(this).run();
}
public void run()  
{
try
Java手機網[www.cnjm.Net]{
if( x >= 12)
{
x = x - 3;
repaint();
Thread.sleep(1);
}
}
Java手機網[www.cnjm.Net]catch(Exception e)  
{
}
}

// 按鍵函數,它響應你的按鍵。產生按鍵事件。
protected void keyPressed(int keycode)
{ // 向右鍵
if(keycode == getKeyCode(Canvas.RIGHT))
{ /// iClick 響應的是第幾張牌的事件。
iClick = iClick + 1;
if (iClick == 2)
Java手機網[www.cnjm.Net]{
bCard3 = true;
x = getWidth();
}

if (iClick == 3)
{
bCard4 = true;
x = getWidth();
}
if (iClick == 4)
{
Java手機網[www.cnjm.Net]bCard5 = true;
x = getWidth();
}
Java手機網[www.cnjm.Net]}

游戲的重新開始,把各值初始化。
/////////// 響應鍵盤事件
protected void keyPressed(int keycode)
{
if(keycode == getKeyCode(Canvas.RIGHT))
Java手機網[www.cnjm.Net]{
iClick = iClick + 1;
if (iClick == 2)
{
bCard3 = true;
x = getWidth();
}
if (iClick == 3)
{
bCard4 = true;
Java手機網[www.cnjm.Net]x = getWidth();
}
if (iClick == 4)
Java手機網[www.cnjm.Net]{
bCard5 = true;
x = getWidth();
}
}
if(keycode == getKeyCode(Canvas.DOWN))
{
///////////////////////////////////////////////////////
bCard1 = false;
bCard2 = false;
bCard3 = false;
bCard4 = false;
bCard5 = false;
b2 = false;
b3 = false;
b4 = false;
b5 = false;

Java手機網[www.cnjm.Net]// 用來慢鏡後的顯示:
bb1 = false;
bb2 = false;
bb3 = false;
bb4 = false;
bb5 = false;
iClick = 1;
bCard1 = true;
x = getWidth();
}
/// 當一盤牌給束時,比較大小:
它的思想是:當玩家要滿5張牌時,就判斷兩個玩家牌的大小。
牌的大小如下定義的:
1 同花順最大(如:A K Q J 10 並同一色)
Java手機網[www.cnjm.Net]2 然後到四個一樣的牌(如 四個A最大)
3 再到三個一樣的加一個對子。
Java手機網[www.cnjm.Net]4 順子(不要求同色)
5 同色(不要求是順子)
6 兩個對子
Java手機網[www.cnjm.Net]7 一個對子
程序實現:
////比較大小:
int tong1 = 0;
int tong2 = 0;
int se1 = 0;
Java手機網[www.cnjm.Net]int se2 = 0;
for(int m = 0 ;m <=8; m = m + 2)
{
for(int n  = m ; n <=8; n = n +2)
{
Java手機網[www.cnjm.Net]if( Num[m] == Num[n] )
{
Java手機網[www.cnjm.Net]tong1 ++;
se1 = m;
}
}
}
////比較對子
for(int m = 1 ;m <=9; m = m + 2)
{
for(int n  = m ; n <=9; n = n +2)
{
if( Num[m] == Num[n] )
{
tong2 ++;
se2 = m;
}
}
}
if(tong1 == tong2)
{
if(se1 != 0)
{
if(Card[se1]%13 > Card[se2]%13)
Java手機網[www.cnjm.Net]{
g.setColor(0,0,255);
g.drawString("你輸了,點向下鍵繼續!",10,20,g.TOP|g.LEFT);
}
if(Card[se1]%13 < Card[se2]%13)
{
Java手機網[www.cnjm.Net]g.setColor(0,0,255);
g.drawString("你贏了,點向下鍵繼續!",10,20,g.TOP|g.LEFT);
}
Java手機網[www.cnjm.Net]}
}
if(tong1 != tong2)
Java手機網[www.cnjm.Net]{
if(tong1 < tong2)
{
g.setColor(0,0,255);
g.drawString("你贏了,點向下鍵繼續!",10,20,g.TOP|g.LEFT);
}
if(tong1 >tong2)
{
g.setColor(255,0,0);
g.drawString("你輸了,點向下鍵繼續!",10,20,g.TOP|g.LEFT);
} } }

4.2.6 游戲的主程序
/// 手機游戲的主程序都是繼承 MIDlet類的,本游戲是一開頭用代碼:Navigator.current = Navigator.MAIN_SCREEN; 就把程序控制交給了類 Navigator。
import Javax.microedition.midlet.*;
import Javax.microedition.lcdui.*;
public class test extends MIDlet
{
boolean init = true;
public test()
{
Navigator.display = Display.getDisplay(this);

Navigator.midlet = this;
}
public void startApp()
{
Navigator.current = Navigator.MAIN_SCREEN;
Navigator.show(null);
if(init)
{
//Alert splash = new Alert("版頭畫面");
Java手機網[www.cnjm.Net]//splash.setType(AlertType.CONFIRMATION);
//splash.setTimeout(5000);
//Navigator.display.setCurrent(splash);
init = false;
}
}
public void pauseApp()
{
Java手機網[www.cnjm.Net]}
public void destroyApp(boolean uncondition)
{
}
}
五   常見錯誤分析

5.1.1 畫圖錯誤
Java手機網[www.cnjm.Net]在畫圖出現異常,這是因為在程序開始階段沒有采用異常捕獲產生的錯誤。在程序的初始化加異常捕獲就行了,如:
try  
{
king1 = Image.createImage("/spade.png");
Java手機網[www.cnjm.Net]king2 = Image.createImage("/heart.png");
king3 = Image.createImage("/clover.png");
king4 = Image.createImage("/dia.png");
}
catch(Exception e) {}

5.2 變量沒有定義或沒有初始化
這是編程常見的錯誤,在 java 語言中,變量在使用的使用不像C語言中變量沒有初始化時將變量賦為0,面Java 變量使用前是需要的。還有變量的定義,變量的使用周期等定義也常使程序出錯。要減少這種錯誤,除了有經驗外,還必須要細心。
5.3 在 GameScreen 類中不能用線程
線程作為一個獨立的類,它必須給重載過來才能用的。就好像在類 MIDlet中
不能用 Timer 這個 Java 包中類的一樣。所以必須在GameScreen 內重載它。
private void doThreadStart()  
Java手機網[www.cnjm.Net]{
new Thread(this).run();
}
public void run()  
{
try
{
if( x >= 12)
{
x = x - 3;
repaint();
Thread.sleep(1);
}
}
catch(Exception e)  
Java手機網[www.cnjm.Net]{
Java手機網[www.cnjm.Net]} } }
用以上方法雖然能用線程了,也能達到了牌慢慢移動的效果。但,從另一個方面它就轉成另外一個弊端了,線程過多了。
5.4 在玩游戲時出會發出兩張同樣的牌
    在玩游戲時出現兩張同樣的牌,這是一幅牌的游戲所不能允許的,錯誤原因:在分別黑紅梅方的游戲算法中出現了錯誤,把取4的余改成了取13的模,不會再發出兩張同樣的牌:
////// 牌的種類
for(int i = 0; i < 10 ; i++)
{
if(Card[i]/13 == 0)
{
///// 黑桃
Java手機網[www.cnjm.Net]Kind[i] = 0;
}
if(Card[i]/13 == 3)
{
///// 黑桃
Kind[i] = 3;
}
if(Card[i]/13 == 2)
{
///// 紅心
Kind[i] = 2;
}
if(Card[i]/13 == 1)
{
///// 梅花
Kind[i] = 1; }

5.5 錯誤總結
由以上可以知道,錯誤的出現不外有兩種:一,是知識不夠。要解決這種如繪圖時的錯誤,線程的應用等。要徹底解決這種錯誤就必須多看書,多動手做程序,加深對J2ME 手機游戲開發的了解。二,書寫代碼時要細心,這樣才會減少程序的開發周期。如,變量的沒有定義等錯誤。
六   用戶手冊
這個游戲仿自周潤發的《賭神》,它具有很高的可玩性。
Java手機網[www.cnjm.Net]它操作也很方便,玩法也算簡單。
Java手機網[www.cnjm.Net]下面先說一下它的玩法:
它最多只能要五張牌,一開始,第一張牌是處於未開狀態,
第二張打開。然後,根據玩家的牌大小(A最大,K次之)
由牌大的玩家下注(也可以放棄),牌小的玩家決定是否
跟(向右鍵),或是放棄(向左鍵)。就這樣到了玩家都
有了五張牌。最後,是否開第一張牌也是由大小先下注。
牌大小的定義:
1 同花順最大(如:A K Q J 10 並同一色)
2 然後到四個一樣的牌(如 四個A最大)
3 再到三個一樣的加一個對子。
4 順子(不要求同色)
5 同色(不要求是順子)
6 兩個對子
7 一個對子
8 比較單張牌大小,從A K 這樣的次序。
八   參考資料
Java手機網[www.cnjm.Net]1 王森 <Java 手機和 pda 程序設計入門>
2 循序漸進Java2教程(第三版)Rogers Cadenhead著,淡文剛 於紅梅 譯,人民郵電出版社
3 Java 程序設計教程 清華大學出版社 H.M.Deitel,P.J.Deitel 著
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved