2023年全國(guó)碩士研究生考試考研英語一試題真題(含答案詳解+作文范文)_第1頁
已閱讀1頁,還剩40頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、<p>  基于JAVA的游戲設(shè)計(jì)</p><p><b>  摘要</b></p><p>  J2SE(Java 2 Simple Edition) 定位在客戶端,主要用于桌面應(yīng)用軟件的編程,J2SE包含于J2EE中,J2ME包含了J2SE的核心類,但新添加了一些專有類。因其擁有“Write Once, run anywhere”的Java特性而提高開發(fā)

2、的效率。</p><p>  隨著JAVA應(yīng)用的日益普及、Java在各種平臺(tái)上的的實(shí)現(xiàn),Java應(yīng)用程序一次編譯到處運(yùn)行的特點(diǎn)逐漸體現(xiàn)出其影響力,對(duì)減少重復(fù)編程、提供快捷的跨平臺(tái)應(yīng)用起著不可忽視的作用。本論文著眼于JAVA技術(shù)的應(yīng)用,開發(fā)一款可用于各種平臺(tái)之上的游戲程序——坦克大戰(zhàn)。本程序的思路來自于日本任天堂公司在20世紀(jì)80年代開發(fā)的Battle City游戲,將老少皆宜的經(jīng)典作品重新用JAVA進(jìn)行了呈現(xiàn),為

3、更流行的硬件平臺(tái)提供應(yīng)用軟件。</p><p>  關(guān)鍵詞 JAVA;J2SE;游戲;坦克大戰(zhàn)</p><p><b>  Abstract</b></p><p>  J2SE is a kind of fast developing technology implemented on various devices especially

4、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 o

5、f the development process thanks to its “Write Once, run anywhere” nature.</p><p>  When cell phone is getting ever more popular nowadays, with the implementation of Java technology on mobile equipment, incr

6、ement 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 J2SE technology and has developed

7、a commercial game suite run on mobile phones—Tank. This application inherits many characters of the old fashioned game Battle City which developed by Nintend</p><p>  Keywords Java;J2SE;Game;TankWord</p&g

8、t;<p><b>  目錄</b></p><p><b>  摘要I</b></p><p>  AbstractII</p><p><b>  第1章 緒論1</b></p><p>  第2章 開發(fā)環(huán)境及相關(guān)技術(shù)的介紹3</p>&

9、lt;p><b>  2.1開發(fā)環(huán)境3</b></p><p>  2.2 Java語言的特點(diǎn)3</p><p>  2.3關(guān)于ECLIPSE4</p><p>  第3章 程序結(jié)構(gòu)、思想和相關(guān)技術(shù)5</p><p>  3.1 本程序需解決的有關(guān)技術(shù)問題5</p><p>  3

10、.2 程序截圖7</p><p>  3.3 程序流程8</p><p>  3.4 相關(guān)技術(shù)8</p><p>  3.4.1 多態(tài)8</p><p>  3.4.2 單例模式9</p><p>  3.4.3 責(zé)任鏈模式9</p><p>  3.4.4 工廠模式9</p

11、><p>  3.4.5 簡(jiǎn)單工廠模式10</p><p>  3.4.6 抽象工廠模式10</p><p>  3.4.7 策略模式11</p><p>  3.4.8 調(diào)停者模式11</p><p>  3.4.9 門面模式11</p><p>  3.4.10 PNG格式11<

12、;/p><p>  3.4.11 AWT繪制的基本原理12</p><p>  3.4.12 雙緩沖12</p><p>  3.5 程序思路13</p><p>  3.5.1 坦克的控制和敵方的智能運(yùn)行13</p><p>  3.5.2 子彈的運(yùn)行和控制14</p><p>  第4

13、章 程序分析和具體實(shí)現(xiàn)16</p><p>  4.1 主游戲邏輯及其涉及到的若干類16</p><p>  4.2 坦克的共同行為19</p><p>  4.3 玩家坦克的功能屬性19</p><p>  4.4 敵人坦克的功能屬性20</p><p>  4.5 子彈的運(yùn)行和控制24</p>

14、;<p><b>  結(jié)論26</b></p><p><b>  致謝28</b></p><p><b>  參考文獻(xiàn)29</b></p><p><b>  附錄A30</b></p><p><b>  附錄B34

15、</b></p><p><b>  第1章 緒論</b></p><p>  現(xiàn)在流行的游戲似乎都是用C或C++來開發(fā)的。在Java平臺(tái)上幾乎沒有很大型及可玩的流行游戲。由于Java是個(gè)新生語言,他的許多特性還有待大家的發(fā)掘,但是我們不能否認(rèn)Java在游戲編程方面的強(qiáng)大性。本文將帶領(lǐng)大家一步一步學(xué)習(xí)編寫Java游戲。最終打造屬于自己的Java游戲。<

16、;/p><p>  Java是由Sun Microsystems公司于1995年5月推出的Java程序設(shè)計(jì)語言(以下簡(jiǎn)稱Java語言)和Java平臺(tái)的總稱。用Java實(shí)現(xiàn)的Hot Java瀏覽器(支持Java applet)顯示了Java的魅力:跨平臺(tái)、動(dòng)態(tài)的Web、Internet計(jì)算。從此,Java被廣泛接受并推動(dòng)了Web的迅速發(fā)展,常用的瀏覽器現(xiàn)在均支持Java applet。另一方面,Java技術(shù)也不斷更新。

17、</p><p>  Java平臺(tái)由Java虛擬機(jī)(Java Virtual Machine)和Java 應(yīng)用編程接口(Application Programming Interface、簡(jiǎn)稱API)構(gòu)成。Java 應(yīng)用編程接口為Java應(yīng)用提供了一個(gè)獨(dú)立于操作系統(tǒng)的標(biāo)準(zhǔn)接口,可分為基本部分和擴(kuò)展部分。在硬件或操作系統(tǒng)平臺(tái)上安裝一個(gè)Java平臺(tái)之后,Java應(yīng)用程序就可運(yùn)行?,F(xiàn)在Java平臺(tái)已經(jīng)嵌入了幾乎所有的操

18、作系統(tǒng)。這樣Java程序可以只編譯一次,就可以在各種系統(tǒng)中運(yùn)行。Java應(yīng)用編程接口已經(jīng)從1.1x版發(fā)展到1.2版。目前常用的Java平臺(tái)基于Java1.4,最近版本為Java1.7(本文應(yīng)用的JDK1.7版本)。</p><p>  雖然 Java 已經(jīng)被用到許多企業(yè)級(jí)軟體上,可是其實(shí)骨子里面還是非常適合用在嵌入式系統(tǒng)之中。Java平臺(tái)演進(jìn)到Java2后,Java平臺(tái)分別針對(duì)不同領(lǐng)域的需求被分成四個(gè)版本,亦即J

19、2EE、J2SE、J2ME以及Java Card(其結(jié)構(gòu)示意圖見圖1.1)。 </p><p>  圖1.1 Java結(jié)構(gòu)圖</p><p>  J2SE就是Java2的標(biāo)準(zhǔn)版,主要用于桌面應(yīng)用軟件的編程;J2ME主要應(yīng)用于嵌入是系統(tǒng)開發(fā),如手機(jī)和PDA的編程;J2EE是Java2的企業(yè)版,主要用于分布式的網(wǎng)絡(luò)程序的開發(fā),如電子商務(wù)網(wǎng)站和ERP系統(tǒng)。<

20、/p><p>  Standard Edition(標(biāo)準(zhǔn)版) J2SE 包含那些構(gòu)成Java語言核心的類。比如:數(shù)據(jù)庫連接、接口定義、輸入/輸出、網(wǎng)絡(luò)編程。</p><p>  Enterprise Edition(企業(yè)版) J2EE 包含J2SE 中的類,并且還包含用于開發(fā)企業(yè)級(jí)應(yīng)用的類。比如:EJB、Servlet、JSP、XML、事務(wù)控制。</p><p>  M

21、icro Edition(微縮版) J2ME 包含J2SE中一部分類,用于消費(fèi)類電子產(chǎn)品的軟件開發(fā)。比如:呼機(jī)、智能卡、手機(jī)、PDA、機(jī)頂盒。</p><p>  通過本次設(shè)計(jì)可以綜合運(yùn)用J2SE所擁有的API,初步掌握面向?qū)ο缶幊痰幕舅枷耄莆誆clipse開發(fā)J2SE程序的基本方法。掌握Eclipse調(diào)試程序的方法。簡(jiǎn)單的應(yīng)用了設(shè)計(jì)模式等概念。</p><p>  第2章 開發(fā)環(huán)境及

22、相關(guān)技術(shù)的介紹</p><p><b>  2.1開發(fā)環(huán)境</b></p><p>  操作系統(tǒng):Microsoft Windows XP</p><p>  程序語言:Java 2</p><p>  開發(fā)包: Java(TM) 2 Standard Edition (build 1.7.1)Sun Micro.&l

23、t;/p><p>  IDE: Eclipse -SDK-3.4.1</p><p>  2.2 Java語言的特點(diǎn)</p><p><b>  1、 平臺(tái)無關(guān)性</b></p><p>  Java引進(jìn)虛擬機(jī)原理,并運(yùn)行于虛擬機(jī),實(shí)現(xiàn)不同平臺(tái)之間的Java接口。使用Java編寫的程序能在世界范圍內(nèi)共享。Java的

24、數(shù)據(jù)類型與機(jī)器無關(guān)。</p><p><b>  2、 安全性</b></p><p>  Java的編程類似C++,但舍棄了C++的指針對(duì)存儲(chǔ)器地址的直接操作,程序運(yùn)行時(shí),內(nèi)存由操作系統(tǒng)分配,這樣可以避免病毒通過指針入侵系統(tǒng)。它提供了安全管理器,防止程序的非法訪問。</p><p><b>  3、 面向?qū)ο?lt;/b>&l

25、t;/p><p>  Java吸收了C++面向?qū)ο蟮母拍?,將?shù)據(jù)封裝于類中,實(shí)現(xiàn)了程序的簡(jiǎn)潔性和便于維護(hù)性,使程序代碼可以只需一次編譯就可反復(fù)利用。</p><p><b>  4、 分布式</b></p><p>  Java建立在TCP/IP網(wǎng)絡(luò)平臺(tái)上,提供了用HTTP和FTP協(xié)議傳送和接收信息的庫函數(shù),使用其相關(guān)技術(shù)可以十分方便的構(gòu)建分布式應(yīng)

26、用系統(tǒng)。</p><p><b>  5、 健壯性</b></p><p>  Java致力與檢查程序在編譯和運(yùn)行時(shí)的錯(cuò)誤,并自動(dòng)回收內(nèi)存,減少了內(nèi)存出錯(cuò)的可能性。Java取消了C語言的結(jié)構(gòu)、指針、#define語句、多重繼承、goto語句、操作符、重載等不易被掌握的特性,提供垃圾收集器自動(dòng)回收不用的內(nèi)存空間。</p><p>  2.3 關(guān)于

27、ECLIPSE</p><p>  Eclipse 是一個(gè)開放源代碼的、基于 Java 的可擴(kuò)展開發(fā)平臺(tái)。就其本身而言,它只是一個(gè)框架和一組服務(wù),用于通過插件組件構(gòu)建開發(fā)環(huán)境。幸運(yùn)的是,Eclipse 附帶了一個(gè)標(biāo)準(zhǔn)的插件集,包括 Java 開發(fā)工具(Java Development Tools,JDT)。</p><p>  雖然大多數(shù)用戶很樂于將 Eclipse 當(dāng)作 Java IDE

28、 來使用,但 Eclipse 的目標(biāo)不僅限于此。Eclipse 還包括插件開發(fā)環(huán)境(Plug-in Development Environment,PDE),這個(gè)組件主要針對(duì)希望擴(kuò)展 Eclipse 的軟件開發(fā)人員,因?yàn)樗试S他們構(gòu)建與 Eclipse 環(huán)境無縫集成的工具。由于 Eclipse 中的每樣?xùn)|西都是插件,對(duì)于給 Eclipse 提供插件,以及給用戶提供一致和統(tǒng)一的集成開發(fā)環(huán)境而言,所有工具開發(fā)人員都具有同等的發(fā)揮場(chǎng)所。<

29、;/p><p>  這種平等和一致性并不僅限于 Java 開發(fā)工具。盡管 Eclipse 是使用 Java 語言開發(fā)的,但它的用途并不限于 Java 語言;例如,支持諸如 C/C++、COBOL 和 Eiffel 等編程語言的插件已經(jīng)可用,或預(yù)計(jì)會(huì)推出。Eclipse 框架還可用來作為與軟件開發(fā)無關(guān)的其他應(yīng)用程序類型的基礎(chǔ),比如內(nèi)容管理系統(tǒng)。Eclipse 是一個(gè)開放源代碼的、基于 Java 的可擴(kuò)展開發(fā)平臺(tái)。就其本

30、身而言,它只是一個(gè)框架和一組服務(wù),用于通過插件組件構(gòu)建。</p><p>  第3章 程序結(jié)構(gòu)、思想和相關(guān)技術(shù)</p><p>  3.1 本程序需解決的有關(guān)技術(shù)問題</p><p>  1、 游戲程序是一項(xiàng)精度要求很高的程序系統(tǒng),因?yàn)槠浯a利用率很高。一個(gè)實(shí)時(shí)運(yùn)行的最終作品,每秒都會(huì)運(yùn)行成千上萬行程序,繪圖事件、鍵盤事件都會(huì)以極高的頻率在后臺(tái)等待響應(yīng),若有絲毫的

31、差別都將很容易導(dǎo)致程序在運(yùn)行不久后可能出現(xiàn)嚴(yán)重錯(cuò)誤,甚至死循環(huán)。因此,其邏輯設(shè)計(jì)應(yīng)當(dāng)相當(dāng)嚴(yán)謹(jǐn),需將所有可能發(fā)生的事件及意外情況考慮在設(shè)計(jì)中。</p><p>  2、 游戲中為了美觀,適用性強(qiáng),可能需要采用外部文件引入的圖片貼圖,有關(guān)貼圖,在MIDP2.0中提供了用于增強(qiáng)游戲功能的game包,使得解決靜態(tài)或動(dòng)態(tài)、畫面背景、屏幕刷新的雙緩沖等都有較好的解決方案。</p><p>  3、

32、 己方坦克的運(yùn)行可以通過鍵盤響應(yīng)事件控制,但敵方則因?yàn)槭亲詣?dòng)運(yùn)行,就需要有一定其一定的智能性;同時(shí),出現(xiàn)在屏幕上的敵方可能會(huì)有較多的數(shù)量,這需要為每個(gè)敵方開辟一個(gè)線程以便能讓其獨(dú)立運(yùn)行。Java的多線程能力為實(shí)現(xiàn)這樣的游戲提供了可能。敵人坦克的運(yùn)行算法也需要進(jìn)行適當(dāng)?shù)脑O(shè)置,以免游戲過于簡(jiǎn)單,單調(diào)。</p><p>  4、 對(duì)于雙方坦克發(fā)出的子彈的控制也需要對(duì)其跟蹤控制,子彈也需要處在獨(dú)立的線程中。敵方子彈僅需

33、要掃描用戶坦克,而用戶坦克需要在每一步掃描所有的敵方坦克。這需要對(duì)所有的對(duì)象有較好的控制。另外,子彈在運(yùn)行過程中也需要實(shí)時(shí)掃描是否碰撞到了相關(guān)障礙物或屏幕邊界。如此過多的線程同時(shí)在本來效率就不高的KVM虛擬機(jī)上運(yùn)行,也許會(huì)導(dǎo)致程序的緩慢。</p><p>  5、 雙方的坦克在前進(jìn)時(shí)也需要考慮到是否碰撞到相關(guān)物體或?qū)Ψ教箍?,以免重疊運(yùn)行,造成許多物理上不可能的情況,缺乏真實(shí)感。每一次刷新頁面、每前進(jìn)一步都需要將

34、所有的周圍環(huán)境都進(jìn)行掃描。</p><p>  6、 游戲的結(jié)束、開始、動(dòng)態(tài)信息畫面作為構(gòu)成一個(gè)完美程序都是必不可少的重要部分。良好的用戶界面更是吸引用戶的硬指標(biāo),相關(guān)的美術(shù)構(gòu)圖也需要有一定的考慮。</p><p>  7、 游戲的地圖不可能通過繪圖來解決。否則,不僅難于控制和處理過多的元素,也會(huì)因過多的大型圖片而不能限制程序的大小,失去程序的原則和Java的優(yōu)勢(shì)。同時(shí),地圖關(guān)卡不宜保

35、存占用過多的內(nèi)存,而最好采取外部文件的讀入讀出方法。</p><p>  8、 用戶運(yùn)行游戲時(shí)需要有分?jǐn)?shù)記錄的可能。如何采用合理的記分標(biāo)準(zhǔn),需要進(jìn)行適當(dāng)?shù)脑O(shè)計(jì)。記錄分?jǐn)?shù)的存儲(chǔ)方式也需要有較好的解決方案。手機(jī)中由于處理器和內(nèi)存空間、存儲(chǔ)空間都十分有限,其數(shù)據(jù)庫系統(tǒng)與普通PC大相徑庭。其數(shù)據(jù)庫結(jié)構(gòu)較為簡(jiǎn)單,被稱之為RMS系統(tǒng)。</p><p>  9、 本程序應(yīng)用的技術(shù)</p>

36、<p>  多態(tài)Polymorphism;單例模式Singleton;責(zé)任鏈模式Chain of Responsibility;工廠模式Factory Method;簡(jiǎn)單工廠模式Simple Factory;抽象工廠模式Abstract Factory;策略模式Strategy;調(diào)停者模式Mediator;門面模式Facade等概念與技術(shù)并將一些屬性信息抽象了除了以配置文件的方式出現(xiàn),從而方便用戶更改。以上相關(guān)技術(shù)細(xì)節(jié)和整

37、體流程將分別在以下小節(jié)闡述。</p><p><b>  3.2 程序截圖</b></p><p><b>  圖3.1 程序截圖</b></p><p><b>  3.3 程序流程</b></p><p>  本程序采用面向?qū)ο蟮脑O(shè)計(jì)模式,對(duì)游戲中的所有物體賦予對(duì)象的概念和

38、屬性。運(yùn)行程序后允許用戶選擇執(zhí)行選項(xiàng)菜單,在開始游戲后將先從外部文件載入地圖文件,對(duì)背景的所有物體進(jìn)行繪圖。在主程序運(yùn)行的線程中,畫面刷新將以一定的頻率采用雙緩沖技術(shù)對(duì)屏幕重繪,實(shí)時(shí)反映整個(gè)游戲的進(jìn)行狀態(tài)。用戶控制的坦克運(yùn)行在主線程中,隨屏幕刷新的頻率而步進(jìn)。敵方坦克將在游戲開始時(shí)逐漸新增線程,每增加一個(gè)敵方對(duì)象就新增加一條線程,一旦線程數(shù)滿到最大值,就不允許敵人再繼續(xù)出現(xiàn)。用戶坦克自誕生之時(shí)起將擁有一發(fā)子彈,子彈雖然開在單獨(dú)的線程中,

39、但運(yùn)行結(jié)束后(比如撞到相關(guān)物體或敵方坦克時(shí))并不結(jié)束子彈對(duì)象,只是將其線程終止。用戶再次發(fā)射子彈時(shí)只是將終止的線程再次激活。在屏幕重繪的主程序中,將在每次的循環(huán)中判斷若干事件。如:用戶坦克的生命是否已完全用盡,敵方坦克數(shù)是否已經(jīng)為零,屏幕上的坦克數(shù)量是否少于仍剩下的坦克數(shù)量等。以便程序進(jìn)入相關(guān)的分支執(zhí)行相關(guān)的反應(yīng)代碼,結(jié)束游戲或統(tǒng)計(jì)分?jǐn)?shù)等。主程序流程如圖3.2所示。</p><p><b>  3.4

40、相關(guān)技術(shù)</b></p><p><b>  3.4.1 多態(tài)</b></p><p>  多態(tài)性是繼數(shù)據(jù)抽象和繼承后,面向?qū)ο笳Z言的第三個(gè)特征。Java的多態(tài)性它的突出優(yōu)點(diǎn)是使程序具有良好的擴(kuò)展性。它通過繼承,可以派生出任意多個(gè)新類型,或向基類增加更多方法時(shí),無須修改原有對(duì)基礎(chǔ)類進(jìn)行處理的相關(guān)程序。就是擴(kuò)展性好。</p><p>

41、  3.4.2 單例模式</p><p>  作為對(duì)象的創(chuàng)建模式[GOF95], 單例模式確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。這個(gè)類稱為單例類。</p><p>  圖3.3 單例模式圖</p><p>  顯然單例模式的要點(diǎn)有三個(gè);一是某各類只能有一個(gè)實(shí)例;二是它必須自行創(chuàng)建這個(gè)實(shí)例;三是它必須自行向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。在下面的對(duì)象

42、圖中,有一個(gè)"單例對(duì)象",而"客戶甲"、"客戶乙" 和"客戶丙"是單例對(duì)象的三個(gè)客戶對(duì)象??梢钥吹剑械目蛻魧?duì)象共享一個(gè)單例對(duì)象。而且從單例對(duì)象到自身的連接線可以看出,單例對(duì)象持有對(duì)自己的引用。如圖3.3所示。</p><p>  3.4.3 責(zé)任鏈模式</p><p>  多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免

43、請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它為止。</p><p><b>  適用范圍:</b></p><p>  1、 有多個(gè)的對(duì)象可以處理一個(gè)請(qǐng)求,哪個(gè)對(duì)象處理該請(qǐng)求運(yùn)行時(shí)刻自動(dòng)確定。</p><p>  2、 你想在不明確指定接收者的情況下,向多個(gè)對(duì)象中的一個(gè)提交一個(gè)請(qǐng)求。

44、 </p><p>  3、 可處理一個(gè)請(qǐng)求的對(duì)象集合應(yīng)被動(dòng)態(tài)指定。com.cz.tank包下的ColliderChain類用責(zé)任鏈模式遍歷所有游戲物體 做碰撞檢測(cè)。</p><p>  3.4.4 工廠模式</p><p>  工廠模式為系統(tǒng)結(jié)構(gòu)提供了靈活的動(dòng)態(tài)擴(kuò)展機(jī)制,減少工作量方便維護(hù),方便維護(hù)。com.cz.tank 類 GameFactoryMgr應(yīng)用了

45、工廠模式。</p><p>  3.4.5 簡(jiǎn)單工廠模式</p><p>  專門定義一個(gè)類來負(fù)責(zé)創(chuàng)建其他類的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的父類。它又稱為靜態(tài)工廠方法模式,屬于類的創(chuàng)建型模式。簡(jiǎn)單工廠模式的UML類圖如圖3.4所示:</p><p>  圖3.4 簡(jiǎn)單工廠模式</p><p>  簡(jiǎn)單工廠模式的實(shí)質(zhì)是由一個(gè)工廠類根據(jù)傳入的

46、參數(shù),動(dòng)態(tài)決定應(yīng)該創(chuàng)建哪一個(gè)產(chǎn)品類(這些產(chǎn)品類繼承自一個(gè)父類或接口)的實(shí)例。該模式中包含的角色及其職責(zé)。用戶在使用時(shí)可以直接根據(jù)工廠類去創(chuàng)建所需的實(shí)例,而無需了解這些對(duì)象是如何創(chuàng)建以及如何組織的。有利于整個(gè)軟件體系結(jié)構(gòu)的優(yōu)化。</p><p>  3.4.6 抽象工廠模式</p><p>  抽象工廠模式可以向客戶端提供一個(gè)接口,使得客戶端在不必指定產(chǎn)品具體類型的情況下,創(chuàng)建多個(gè)產(chǎn)品族中的

47、產(chǎn)品對(duì)象。這就是抽象工廠模式的用意。</p><p>  每個(gè)模式都是針對(duì)一定問題的解決方案。抽象工廠模式面對(duì)的問題是多產(chǎn)品等級(jí)結(jié)構(gòu)的系統(tǒng)設(shè)計(jì)。</p><p>  3.4.7 策略模式</p><p>  策略模式定義了一系列的算法,并將每一個(gè)算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變化。本程序的坦克外觀使用了策略模式。com

48、.cz.tank.strategies的DrawTankStrategy類。</p><p>  3.4.8 調(diào)停者模式</p><p>  用一個(gè)中介對(duì)象來封裝一系列的對(duì)象交互。中介者使各對(duì)象不需要顯式地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互。com.cz.tank 類 Game Mediator使用了調(diào)停者模式。</p><p>  3.4

49、.9 門面模式</p><p>  外部與一個(gè)子系統(tǒng)的通信必須通過一個(gè)統(tǒng)一的門面(Facade)對(duì)象進(jìn)行,這就是門面模式。</p><p>  3.4.10 PNG格式</p><p>  PNG具體格式由PNG Specification Version 1.0定義的。PNG格式提供透明背景的圖像,這對(duì)繪制游戲畫面和被操縱主角極有幫助。坦克之間或與障礙物碰撞時(shí)就不

50、會(huì)因?yàn)楸尘坝刑囟ǖ念伾?,顯示出的效果像貼上的圖片而缺乏真實(shí)感,物體之間輕微重疊時(shí)最上層圖片也不會(huì)覆蓋超過其有效象素外的部分。</p><p>  PNG格式圖片中包含許多定義其圖片特性的冗余部分(Chunks)。這些代碼包含在每一個(gè)單獨(dú)的PNG格式圖像中,然而如果將多個(gè)PNG圖像合并在一張幅面稍大一些的整圖中,多個(gè)chunks就可以得到精簡(jiǎn),圖片的大小可以得到控制。使用Image類中的create Image函數(shù)

51、可從整圖中分割出所需要的元素。在Game包中的Tiled Layer和Sprite類都整合了這樣的功能。本程序中的地圖元素都集成在一張MAP.png圖片中,實(shí)現(xiàn)了方便的管理和程序體積的精簡(jiǎn)。</p><p>  3.4.11 AWT繪制的基本原理</p><p>  AWT的繪制與界面更新使用了一個(gè)單獨(dú)的線程,稱為AWT線程。paint、repaint、update 三個(gè)方法關(guān)系如圖3.5

52、所示 :</p><p>  圖3.5 雙緩沖原理示意圖</p><p>  3.4.12 雙緩沖</p><p>  進(jìn)行游戲繪圖一般需要手動(dòng)編程使用雙緩沖。需要在paint()方法內(nèi)所想要畫的圖形畫在一張預(yù)先準(zhǔn)備好的背景,等所有繪圖操作都完成后再將背景的數(shù)據(jù)拷貝到實(shí)際的屏幕上。Image類提供了一個(gè)建立背景的靜態(tài)方法createImage(int width,

53、int height),再利用getGraphics()方法取得屬于這個(gè)背景的Graphics對(duì)象,所進(jìn)行的</p><p>  繪圖操作都會(huì)作用在背景上,等到全部的繪圖操作完成后,再調(diào)用paint()方法將背景的數(shù)據(jù)復(fù)制到實(shí)際顯示的屏幕上。</p><p>  這樣的技術(shù)在繪制動(dòng)畫時(shí)特別有用。繪制動(dòng)畫時(shí)經(jīng)常需要不斷地更新畫面,而更新畫面的操作就是先將屏幕以fillRect()的方式清除,

54、再將下一張圖片畫在屏幕上,然而反復(fù)的清除及重繪會(huì)造成屏幕的閃爍現(xiàn)象(flicker),因此使用雙重緩沖的好處就是在背景進(jìn)行這個(gè)清除及重繪的操作,再將完成的繪圖拷貝到屏幕上,由于用戶看不到清除的操作,因此就不會(huì)出現(xiàn)閃爍的現(xiàn)象了。</p><p><b>  3.5 程序思路</b></p><p>  3.5.1 坦克的控制和敵方的智能運(yùn)行</p><

55、;p>  GameCanvas中提供了與以往不同的鍵盤采樣功能。GameMediator類中采取響應(yīng)鍵盤事件的方法,每次執(zhí)行周期時(shí)會(huì)讀取keyPressed函數(shù)中需執(zhí)行的代碼。這樣的機(jī)制并不適合某些游戲場(chǎng)合。在某些不支持keyRepeat功能的設(shè)備上,反復(fù)執(zhí)行的按鍵,比如發(fā)射子彈,將不能因?yàn)殚L(zhǎng)時(shí)間按壓而自動(dòng)重復(fù),這樣就需要用戶高頻率的手動(dòng)擊鍵,這在操縱空間非常有限的移動(dòng)設(shè)備上是非常困難的。同時(shí),事件的執(zhí)行周期也并不一定適合游戲的場(chǎng)

56、合,也許需要更高頻率執(zhí)行的按鍵卻只能在指定的周期內(nèi)規(guī)律的響應(yīng)。對(duì)此,針對(duì)游戲的開發(fā),Game包提供的鍵盤狀態(tài)功能將顯得十分有效。</p><p>  GameCanvas提供getKeyStates函數(shù)可獲取當(dāng)前鍵盤上的信息。將以位的形式返回鍵盤上所有鍵的按與釋放的狀態(tài),當(dāng)bit為1時(shí),鍵就是被按下的狀態(tài),為0時(shí)則為釋放狀態(tài)。只需要此一個(gè)函數(shù)的返回值就可以返回所有鍵的狀態(tài)。這保證了快速的按鍵和釋放也會(huì)被循環(huán)所捕捉

57、。同時(shí),這樣的機(jī)制也可檢測(cè)到幾個(gè)鍵同時(shí)按下的狀態(tài),從而提供斜向運(yùn)行等相應(yīng)功能。</p><p>  敵方按照規(guī)則不能和用戶坦克重合,則它每行走一步就需要把用戶坦克掃描一次,判斷其是否碰撞到了用戶的坦克。Sprite類中提供了collidesWith函數(shù),用于判斷是否與某個(gè)TiledLayer、Sprite、Image的對(duì)象有圖象上的重合(即游戲中的碰撞)。然而不能僅僅將用戶坦克作為其Sprite參數(shù)傳遞給敵人的類

58、進(jìn)行判斷。因?yàn)槿绻l(fā)生碰撞,collidesWith成立,則兩輛坦克已經(jīng)發(fā)生了圖象重合,違反了規(guī)則,甚至若再進(jìn)行collidesWith判斷的話,其結(jié)果將永為真。為了提前預(yù)知碰撞,可以將所有坦克的碰撞范圍設(shè)定為一個(gè)比坦克圖片稍大一些的矩形,此矩形僅在坦克前方比坦克圖形多出一個(gè)象素。在多出的11個(gè)象素中,按照每個(gè)象素依次檢查此象素是否于外界發(fā)生碰撞,如果不是按照象素檢查,則當(dāng)坦克與障礙物錯(cuò)位并同時(shí)與兩種物體接觸時(shí)將有可能忽略檢測(cè)其中的一樣

59、物體。這樣,就可以提前一步判斷。如果發(fā)生碰撞,則坦克應(yīng)當(dāng)選擇掉轉(zhuǎn)方向,此時(shí),兩輛碰撞的坦克又因?yàn)槠渚匦螀^(qū)域不重合而不符合collidesWith的條件,就可以繼續(xù)正常運(yùn)行了。</p><p>  敵方坦克由于需要具有一定的智能性,以便對(duì)玩家攻擊,使之具有一定的可玩性。敵人可以自動(dòng)行走,但是應(yīng)當(dāng)在以下適當(dāng)?shù)那闆r下轉(zhuǎn)向:首先是是否超出界面的邊界,其次是是否與地圖障礙物發(fā)生了碰撞,再次是是否與用戶坦克發(fā)生了碰撞。需要指

60、出的是,當(dāng)發(fā)生阻礙不能在不變方向的情況下繼續(xù)行走時(shí),并不一定立即需要采取轉(zhuǎn)向的對(duì)策。如果一定發(fā)生轉(zhuǎn)向,試想,當(dāng)敵方碰到玩家時(shí),如果它立即轉(zhuǎn)向,將不會(huì)對(duì)玩家發(fā)射射向他的子彈,就不構(gòu)成任何威脅,當(dāng)然,也不能永遠(yuǎn)不轉(zhuǎn)向。本程序設(shè)置為:當(dāng)碰撞到障礙物或邊界時(shí)立即轉(zhuǎn)向,但碰到玩家坦克時(shí)需要有一個(gè)等待的時(shí)間,這個(gè)時(shí)間由碰撞前隨機(jī)取得的在某方向上的持續(xù)行走步數(shù)決定,當(dāng)發(fā)生坦克間碰撞時(shí),此隨機(jī)數(shù)將在下一次循環(huán)前減少為原來的2/3,這樣就實(shí)現(xiàn)了加快轉(zhuǎn)向的

61、時(shí)間,避免死鎖在一個(gè)方向上靜止的停留過長(zhǎng)的時(shí)間。另外,坦克的發(fā)炮間隔和轉(zhuǎn)后的具體方向都由隨機(jī)數(shù)決定。坦克之間由以上道理也不會(huì)發(fā)生重疊,但當(dāng)某坦克正從上方生成而正巧有另一輛阻礙在其生成點(diǎn)處,這將導(dǎo)致不可避免的重合。這是允許的,但需要對(duì)他們標(biāo)注狀態(tài),即當(dāng)坦克剛出現(xiàn)時(shí)暫時(shí)允許重合,一旦在某個(gè)時(shí)間他們脫離了重合狀態(tài),就不能在允許重合,如果不設(shè)置這</p><p>  3.5.2 子彈的運(yùn)行和控制</p>&

62、lt;p>  每一個(gè)坦克都有他自己的一顆子彈,這顆子彈在任何一輛坦克被構(gòu)造時(shí)就一直存在,直至此坦克生命的結(jié)束,子彈的再次只是將屏幕上暫時(shí)掩蓋的圖象重新置于坦克炮筒才恰當(dāng)位置,并使其顯示出來,這與現(xiàn)實(shí)中每個(gè)子彈都是單獨(dú)的個(gè)體有所不同。</p><p>  子彈所需要完成的任務(wù)有:</p><p>  它是一個(gè)繼承了Runnable虛類的可運(yùn)行單獨(dú)線程的對(duì)象。在其出現(xiàn)在屏幕上的運(yùn)行周期中

63、,每一步都需要循環(huán)檢測(cè)以下條件:</p><p>  是否與某坦克發(fā)生了碰撞,即擊中了這輛坦克。子彈使用的是象素級(jí)的碰撞檢測(cè),因?yàn)樽訌椀膱D片形狀不規(guī)則,如果使用矩形碰撞檢測(cè),將有可能在子彈尚未接觸到物體時(shí)就已返回碰撞的真值。分為兩種情況,如果此子彈來自于敵方,將只檢測(cè)玩家坦克,因?yàn)閿撤街g的子彈必須允許可以透明的穿過,以保證不會(huì)在敵人之間發(fā)生子彈的消減。如果來自玩家,則每一步需掃描所有的敵方坦克,檢查是否發(fā)生碰撞

64、,這可能會(huì)花費(fèi)不少的CPU時(shí)間。</p><p>  其次,子彈之間需要檢測(cè)是否碰撞。敵人之間顯然,如上已經(jīng)提過,不需要檢測(cè),但敵人與玩家之間應(yīng)當(dāng)可以互相消除子彈,以便在狹窄的路口中仍有存活的機(jī)會(huì)。玩家的子彈需要在每一步檢測(cè)所有敵人的子彈的運(yùn)行狀態(tài)。這樣較多的運(yùn)算也將不可避免的耗費(fèi)大量CPU時(shí)間。</p><p>  子彈對(duì)不同障礙物將有不同的反映。對(duì)磚墻將有能力將其擊毀,使之在畫面上消失

65、;對(duì)水泥鋼筋將不能發(fā)生作用,子彈也不能通過;對(duì)于河流,坦克不可以通過,但子彈可以;對(duì)于草叢,子彈和坦克都可以通過。</p><p>  第4章 程序分析和具體實(shí)現(xiàn)</p><p>  4.1 主游戲邏輯及其涉及到的若干類</p><p>  TankClient主管著所有類之間的協(xié)調(diào),決定何時(shí)死亡,何時(shí)分配新的敵人,及控制敵人出現(xiàn)處的閃光圖標(biāo)、游戲結(jié)束后的動(dòng)態(tài)Gam

66、e over字樣。它運(yùn)行在獨(dú)立的線程中,以恒定的頻率刷新畫面。刷新速度需大于30/秒才能使畫面顯示因人眼的暫時(shí)停留效應(yīng)流暢運(yùn)行。本程序設(shè)置為20毫秒。其主邏輯如圖4.1所示。</p><p>  程序中建立了另外的兩個(gè)包,分別表述了敵人坦克和玩家坦克的功能。它們分別為:EnemySprite和UserSprite。這兩個(gè)類均在TankClient中建立了對(duì)象,以便進(jìn)行統(tǒng)一調(diào)度。BattleCanvas包括了Lay

67、erManager,這樣所有靜態(tài)和動(dòng)態(tài)的圖象都不需要手動(dòng)刷新,只需要在LayerManager中加入所有的需控制的元素,再統(tǒng)一由LayerManager刷新即可。因此,有必要在其中創(chuàng)立一個(gè)LayerManager的對(duì)象。</p><p>  其他,如Sprite類的gameover字樣、記分統(tǒng)計(jì)畫面也都需在此主邏輯中建立相應(yīng)對(duì)象。還需保存的變量有,游戲開始時(shí)間、結(jié)束時(shí)間(用于統(tǒng)計(jì)分?jǐn)?shù))、敵人的總數(shù)、屏幕上敵人的數(shù)

68、量、下一個(gè)敵人需要出現(xiàn)的位置(總共允許在三個(gè)不同的位置出現(xiàn),分別位于屏幕的左、中、右方)、游戲是否已成功結(jié)束或是否已死亡。</p><p>  構(gòu)造函數(shù)中,需初始化地圖。地圖實(shí)際即為TiledLayer的一個(gè)對(duì)象,可調(diào)用setCell設(shè)置其具體的圖象格內(nèi)容。地圖由外部文件讀入。外部文件分別命名為level*.png,利用MIDP中唯一獲取外部文件為程序內(nèi)資源的getResourceAsStream()函數(shù)將地圖文

69、件讀入程序。在創(chuàng)建了InputStream類的map對(duì)象后,使用read()函數(shù)可將流中的下一個(gè)字節(jié)讀出,并返回此字節(jié)代表的整數(shù)。每個(gè)整數(shù)代表一種障礙物。用二維循環(huán)將讀出的每個(gè)整數(shù),通過setCell()將整幅地圖畫出即可。地圖文件可用十六進(jìn)制的文本編輯器生成,如本程序使用的Ultraedit。</p><p>  繪出地圖后,可用LayerManager的append()將地圖放置在第一層。這是很有必要的。因?yàn)?/p>

70、地圖上的障礙物之一——草,在坦克運(yùn)行中時(shí)是必須處于坦克的上層的,否則將失去真實(shí)性。為此,地圖必須首先載入。</p><p>  由于敵人將依次出現(xiàn)在屏幕上,同時(shí)出現(xiàn)的數(shù)量應(yīng)當(dāng)受到控制。本程序設(shè)置為6。所以在構(gòu)造函數(shù)中,也應(yīng)當(dāng)分配6個(gè)EnemySprite對(duì)象的內(nèi)存空間。構(gòu)造坦克時(shí),將把坦克的png圖片作為參數(shù)傳遞給EnemySprite和UserSprite,BattleCanvas中創(chuàng)建坦克僅調(diào)用createE

71、nemy()和createUser()實(shí)現(xiàn)。</p><p>  在構(gòu)造函數(shù)自己調(diào)用了線程的start后,程序?qū)㈤_始循環(huán)運(yùn)行,直至跳出while的循環(huán)。每次循環(huán)中將檢測(cè)是否死亡,屏幕上坦克的數(shù)量,是否該過關(guān)統(tǒng)計(jì)分?jǐn)?shù),檢測(cè)用戶輸入的按鍵、重繪整個(gè)屏幕及回收垃圾內(nèi)存(Garbage Collection)。</p><p>  當(dāng)敵人坦克完全死亡時(shí)(enemyNum為0),需調(diào)用System類

72、的currentTimeMillis()賦值給結(jié)果的時(shí)間。接著調(diào)用setCurrent()顯示統(tǒng)計(jì)分?jǐn)?shù)的畫面,為了進(jìn)入下一關(guān),統(tǒng)計(jì)畫面只是停留四秒,就重新轉(zhuǎn)回BattleCanvas畫面。當(dāng)然,如果當(dāng)前已是最后一關(guān),就不會(huì)再轉(zhuǎn)回。進(jìn)入下一關(guān)時(shí),許多變量需要重新被初始化,如地圖的繪制、敵人出現(xiàn)位置的重置、敵人的數(shù)量、玩家坦克的當(dāng)前位置。</p><p>  如果游戲未結(jié)束,則需判斷屏上坦克是否已小于還剩坦克的總數(shù),

73、如果是這樣,就需要再提供一輛坦克。提供新坦克之前,在屏幕上設(shè)置了一個(gè)專用指示的閃光符號(hào),它繼承了Sprite,運(yùn)行在單獨(dú)的線程中。以在兩秒鐘內(nèi)反復(fù)閃現(xiàn)兩次為一個(gè)生命周期。當(dāng)它閃光完畢后,敵人就會(huì)從閃光位置出現(xiàn)。這樣可提示玩家具體敵人將在什么時(shí)刻出現(xiàn),以便做好準(zhǔn)備。閃光位置設(shè)置了三處坐標(biāo),由于敵人不能同時(shí)出現(xiàn),便設(shè)置了enemyOutDelay的倒數(shù)計(jì)時(shí),每次屏幕刷新會(huì)減少一次計(jì)數(shù),直到為0時(shí)就準(zhǔn)備一輛坦克。本程序設(shè)置的兩次坦克出現(xiàn)的最小

74、間隔為2秒。</p><p>  如果玩家已經(jīng)死亡,就需要使用LayerManager的insert()將gameover字樣插入到最上層,以免被其他物體覆蓋。</p><p>  在檢測(cè)用戶輸入的input()函數(shù)中,當(dāng)按方向鍵時(shí),玩家坦克就將向不同的方向運(yùn)行,這調(diào)用了UserSprite的go()函數(shù);當(dāng)開炮時(shí),就調(diào)用其fire()函數(shù),作出相應(yīng)的行為。</p><

75、;p>  在出現(xiàn)正式畫面前設(shè)置了一個(gè)loading state*字樣的單獨(dú)屏幕,調(diào)用了loadinglevel()函數(shù),并停滯了1500毫秒,提示用戶做好準(zhǔn)備。</p><p>  在繪圖的render()過程中,除了要重繪坦克、地圖、子彈外,還會(huì)在右邊空白處繪出一個(gè)生命統(tǒng)計(jì)欄。并反復(fù)使用Graphics的drawLine()、drawImage()繪畫出一個(gè)三維的效果,增強(qiáng)視覺感。該三維欄的上方為白色,下

76、方為黑色,就創(chuàng)造了立體感。在每次刷新繪圖頁面時(shí),應(yīng)使用GameCanvas的flushGraphics()將屏幕后臺(tái)的緩沖區(qū)內(nèi)的圖象刷新到前臺(tái)來。</p><p>  在允許敵人出現(xiàn)前,需要檢測(cè)給即將出現(xiàn)的敵人分配一個(gè)數(shù)組序號(hào)。在程序中調(diào)用了getNullEnemyIndex()進(jìn)行測(cè)試,當(dāng)返回為-1時(shí)說明沒有序號(hào)可以分配,否則,將返回空的序號(hào)。</p><p>  4.2 坦克的共同行為

77、</p><p>  在TankSprite中定義了所有坦克(包括敵方坦克和玩家坦克)的共同行為和屬性。EnemeySprite和UserSprite都繼承了該類以簡(jiǎn)化結(jié)構(gòu)。在transformDirection[]中定義了坦克四個(gè)方向分別應(yīng)將原始圖片旋轉(zhuǎn)的角度,分別為TRANS_NONE,TRANS_ROT90,TRANS_ROT180,TRANS_ROT270,以便在后來的setTransform()中將這些

78、常量代入。構(gòu)造函數(shù)中創(chuàng)建了每個(gè)坦克必須擁有的一顆子彈,這些子彈就將只跟隨自己的坦克調(diào)動(dòng)。</p><p>  為了能提前預(yù)測(cè)碰撞,調(diào)用了defineCollisionRectangle(0,-1,11,12)將碰撞矩形向前設(shè)置了一個(gè)象素,具體原理見第二章。</p><p>  在setBulletDirection()中,將根據(jù)坦克當(dāng)前的方向確定子彈出膛后的方向,其中setRefPixel

79、Position()將子彈的參考點(diǎn)設(shè)置在其未變形狀態(tài)的底部,setXY()將其放置到炮口的位置,setTransform()將其圖片方向轉(zhuǎn)到需要使用的位置。</p><p>  canPass()函數(shù)將返回坦克是否能夠向前前進(jìn),考慮到的因素有邊界、障礙物。它返回一個(gè)boolean值,提供給go()函數(shù),做進(jìn)一步的判斷。getTileIndex()將檢測(cè)傳遞來的象素處是什么類型的障礙物,它將象素除以8(即障礙物的象

80、素寬度),取整,再通過getCell()得到。在得到障礙物屬性后,判斷其序號(hào)是否與草相同,或是否為空(序號(hào)為0)。因?yàn)樗械恼系K物中只有草不會(huì)阻礙坦克的向前運(yùn)行。</p><p>  4.3 玩家坦克的功能屬性</p><p>  構(gòu)造函數(shù)中需要將坦克方向設(shè)置為向上,因?yàn)閯偝霈F(xiàn)時(shí)就是這樣的狀態(tài)。當(dāng)開炮時(shí),調(diào)用BulletSprite的setLayerManager()將子彈與layerMa

81、nager聯(lián)系起來。需要聯(lián)系的還有自身坦克、地圖。這些都由坦克傳遞給子彈。因?yàn)樽訌検菍儆谔箍说?,它的屬性需要跟?dāng)前的坦克保持一致。接著使用append()將子彈貼到layerManager上顯示出來。最終調(diào)用其start()開始子彈自己的線程。子彈一旦開始運(yùn)行,就脫離了當(dāng)前坦克的控制,直到其生命周期終止。</p><p>  無論子彈是屬于敵人還是玩家的,它都必須記錄自己的來源和攻擊的對(duì)象。在玩家坦克發(fā)射的子彈中

82、,就必須將攻擊對(duì)象設(shè)置為所有的敵人。這樣,它才能有掃描的目標(biāo)。在setShootCheck()的參數(shù)中,傳給子彈的是敵人的數(shù)組,子彈的對(duì)象就被確定了。</p><p>  die()、resetPosition()、getLife()都是很簡(jiǎn)短的函數(shù),但卻提供必不可少的功能。他們可被外部調(diào)用,以取得生命值、死亡記數(shù)、重置位置。</p><p>  在go()函數(shù),每個(gè)方向在走前都須用if

83、(canPass(UP)&&!collidesEnemy())</p><p>  檢測(cè)是否可以行走。canPass()檢測(cè)是否有障礙物及是否到邊界。collidesEnenmy檢測(cè)是否前方有坦克阻礙行動(dòng)。當(dāng)可以行走時(shí),就在當(dāng)前方向的坐標(biāo)上增加或減少一個(gè)象素。</p><p>  在collidesEnemy()函數(shù)中,將有一個(gè)for循環(huán)按照敵人數(shù)組的序號(hào)依次檢測(cè)6次。有一

84、點(diǎn)非常重要:在檢測(cè)前,需要將敵人的檢測(cè)矩形區(qū)域設(shè)置為與原來圖片一樣大小。否則,當(dāng)玩家向上走,而有敵人從左方向右走,并且已經(jīng)碰撞到玩家坦克時(shí),玩家坦克會(huì)因?yàn)楸慌卸ㄒ雅c敵人發(fā)生碰撞而不允許前進(jìn)。事實(shí)上,敵人坦克此時(shí)并沒有阻礙玩家前進(jìn)。這樣的判斷必須排除在考慮范圍外。當(dāng)然,在設(shè)置完成后,必須將將檢測(cè)區(qū)域設(shè)置回原先的狀態(tài),否則敵人在往后自己的檢測(cè)中將發(fā)生錯(cuò)誤。</p><p>  4.4 敵人坦克的功能屬性</p&

85、gt;<p>  由于和UserSrite同屬于一個(gè)TankSprite的繼承類,其功能就與UserSprite有很大的相似之處,但也有其自身的特別屬性。其主要功能流程圖如圖4.2所示。</p><p>  首先,EnemySprite繼承了Runable接口。因?yàn)閿橙说倪\(yùn)行是自動(dòng)的,需要有設(shè)定的程序讓它可自己控制,而不像UserSprite完全通過每次輸入的鍵盤信號(hào)來做出反映。因此,它可以運(yùn)行在單

86、獨(dú)的線程中。</p><p>  setEnemyShootCheck()函數(shù)與UserSprite中的一樣,設(shè)置了攻擊的對(duì)象,并且此函數(shù)將繼續(xù)把參數(shù)傳遞給自身的子彈,以便子彈可以識(shí)別攻擊對(duì)象。此函數(shù)由BattleCanvas調(diào)用。</p><p>  getRandomDirection()以當(dāng)前系統(tǒng)時(shí)間作為種子,調(diào)用了Random類的nextInt()產(chǎn)生一個(gè)隨機(jī)的整數(shù),此整數(shù)取除4的

87、余數(shù)的絕對(duì)值作為隨機(jī)的方向。</p><p>  Random random=new Random(System.currentTimeMillis());</p><p>  return Math.abs(random.nextInt())%4+1;</p><p>  此時(shí)返回的值的范圍就確定在1~4之間,正好對(duì)應(yīng)四個(gè)方向。將他們代入需要使用方向的函數(shù)中就可以

88、使用了。</p><p>  getRandomStep()的原理類似:</p><p>  Random random=new Random(System.currentTimeMillis());</p><p>  return (Math.abs(random.nextInt())%4)*50;</p><p>  只是需要乘以每秒會(huì)

89、刷新的屏幕的次數(shù)。這樣就相當(dāng)于允許在某一個(gè)方向運(yùn)行0~3秒鐘的時(shí)間。</p><p>  每個(gè)敵人還需要擁有一個(gè)內(nèi)部的所有敵人的數(shù)組元素。這樣,它們才可以自動(dòng)檢測(cè)自己是否與同伴發(fā)生了碰撞,以便采取躲避、轉(zhuǎn)向等行動(dòng)。 </p><p>  collidesWithOtherTank()將檢測(cè)是否與其他坦克(包括敵人和玩家)。一個(gè)循環(huán)將依據(jù)敵人的序號(hào)查找5次。if(i==number)brea

90、k ;語句將避免檢測(cè)到自己,永遠(yuǎn)返回真。</p><p>  collidesInOtherTank()雖與上面的函數(shù)很相似,但仍有一些細(xì)微不同,那就是不需要在檢測(cè)前設(shè)置被檢測(cè)方的矩形區(qū)域。因?yàn)椴恍枰M(jìn)行預(yù)先檢測(cè)。此函數(shù)用來檢測(cè)是否在剛出現(xiàn)時(shí)就與其他坦克發(fā)生碰撞的。如果一出現(xiàn),出口就被堵死,顯然,不能永遠(yuǎn)不出現(xiàn),那就應(yīng)采取其他的辦法,否則兩輛坦克將因?yàn)槎继幵谂鲎矤顟B(tài)中而無法移出。</p><p

91、>  在運(yùn)行的線程中,需在每前進(jìn)的一步驟中循環(huán)做下列事件:</p><p>  如果坦克已死亡,立刻退出。(由boolean值destroyed決定)。</p><p>  如果不是剛出現(xiàn)(由isBeginner決定),判斷是否與將其他坦克發(fā)生碰撞,就向當(dāng)前方向前進(jìn)一步驟,否則,將需要循環(huán)檢測(cè)的當(dāng)前隨機(jī)步數(shù)減少為原先的2/3(為了加速離開的時(shí)間)。如果剛出現(xiàn),就直接走一步,具體如何行

92、走將在go()函數(shù)中決定,并且此go()與UserSprite中的有所區(qū)別。</p><p>  當(dāng)隨機(jī)發(fā)炮數(shù)減少到0時(shí),就進(jìn)行發(fā)炮的動(dòng)作。發(fā)炮后應(yīng)立即重新賦值給隨機(jī)發(fā)炮數(shù),以便重新倒數(shù)計(jì)算。</p><p>  當(dāng)所有的步驟走完后,因?yàn)樾枰D(zhuǎn)動(dòng)方向,于是,調(diào)用一次隨機(jī)取得方向的函數(shù)再次獲值。其他的隨機(jī)值也應(yīng)當(dāng)重置。</p><p>  在go()函數(shù)中首先檢測(cè)是否

93、正處于碰撞狀態(tài)中,如果不是,就需要取消Beginner的狀態(tài),因?yàn)椴恍枰狟eginner這樣的特殊身份,讓別的坦克不檢測(cè)了。</p><p>  在運(yùn)行在某個(gè)方向上,當(dāng)確定為canPass時(shí),應(yīng)再檢測(cè)是否為Beginner。如果是,就不應(yīng)該受到其他坦克的影響而直接改變坐標(biāo),但若不是,就應(yīng)當(dāng)遠(yuǎn)地不動(dòng)。</p><p>  4.5 子彈的運(yùn)行和控制</p><p>  

94、子彈繼承了Runnable,運(yùn)行在獨(dú)立的線程中。它擁有一個(gè)很重要的變量,isFromEnemy。它標(biāo)識(shí)了該子彈是屬于玩家的,還是敵人的,這樣可以控制子彈在脫離坦克管束后的運(yùn)行狀態(tài)中的行為。其主要功能流程圖如圖4.3所示。</p><p>  checkHit(int x,int y)調(diào)用了getTileIndex(x,y)獲取當(dāng)前子彈擊中的是什么障礙物,如果返回了false就表示沒有擊中任何東西。當(dāng)擊中了需要作出

95、反映的物體時(shí),就分別采取措施:擊中草時(shí),由于沒有定義相關(guān)函數(shù),就不會(huì)有任何反映,會(huì)重合在草上正常通過;擊中磚塊時(shí),將產(chǎn)生爆炸,調(diào)用setCell將當(dāng)前塊置為空,并產(chǎn)生爆炸效果。爆炸效果由tileExplode(x,y)根據(jù)需要爆炸的坐標(biāo)點(diǎn)生成,其中將一個(gè)Sprite圖片在界面上閃現(xiàn)150毫秒。爆炸效果需要將圖片insert進(jìn)第0層,這樣才不至于被其他景物所覆蓋,爆炸結(jié)束后layerManager會(huì)自動(dòng)相應(yīng)調(diào)整。擊中鋼筋時(shí),將只產(chǎn)生爆炸效

96、果。</p><p>  setShootCheck(EnemySprite enemySprite[]);setUserSprite(UserSprite userSprite);</p><p>  setEnemySprite(EnemySprite enemySprite)都是將相關(guān)的坦克傳入到子彈類里來,以便確認(rèn)來源或攻擊目標(biāo)。</p><p>  在線程

97、的循環(huán)中while ( (x < 155) && (x >=5) && (y >=5) && (y < 171))作為循環(huán)的條件可以控制子彈出界的范圍。這幾項(xiàng)參數(shù)在編寫時(shí)很容易出錯(cuò)。它們反映了象素級(jí)處理的技巧。如果程序在子彈已經(jīng)到達(dá)X軸的155坐標(biāo)時(shí)仍允許子彈繼續(xù)運(yùn)行,子彈將一次性向右運(yùn)行2個(gè)象素,到達(dá)157點(diǎn)。在隨后的checkHit(RIGHT)調(diào)用中,它將檢測(cè)

98、它是否在x+3點(diǎn),即160點(diǎn)擊中了某個(gè)障礙物,但是160/8=20。地圖的tiledLayer對(duì)象中并不存在序號(hào)為20的塊,最大只為19。此時(shí)ArrayOutOfBoundException異常就會(huì)拋出,程序終止運(yùn)行。</p><p>  子彈運(yùn)行中,將用collidesWith(tiledLayer,true)測(cè)試是否碰撞上了地圖。如果為真,就繼續(xù)檢測(cè)碰撞上了什么樣的物體。這將針對(duì)四個(gè)不同的方向分別以象素級(jí)檢測(cè)

99、。如果擊中了某樣物體,那么checkHit自然會(huì)處理,子彈的生命周期結(jié)束,以break退出循環(huán)。</p><p>  如果沒有擊中物體,就繼續(xù)檢測(cè)是否擊中了某輛坦克。這根據(jù)子彈的來源分為兩種情況。當(dāng)來自玩家時(shí),將首先檢測(cè)所有的敵人發(fā)出的子彈,當(dāng)發(fā)生子彈間的碰撞時(shí),用戶的子彈將被移除,雖然按照道理敵人的子彈同時(shí)也應(yīng)被移除,但敵人子彈是運(yùn)行在另一線程中的,應(yīng)當(dāng)由它自己來控制為好,用戶的子彈只需要管理好自己的狀態(tài)就可以

100、了。如果沒有和子彈發(fā)生碰撞,就檢測(cè)是否與敵人碰撞,發(fā)生碰撞時(shí),將敵人從layerManager中移除,并置為null,產(chǎn)生爆炸效果,敵人數(shù)量減少一位,敵人屏幕上數(shù)量減少一位。</p><p>  如果是來自敵人的子彈,將同樣檢測(cè)與玩家子彈的碰撞,及與玩家坦克的碰撞如有碰撞,玩家生命數(shù)減少一位,位置重置。如果玩家生命已死亡殆盡,就需要在進(jìn)行以上操作的同時(shí)將玩家坦克的位置放置到屏幕外的部分。因?yàn)閘ayerManage

101、r的remove函數(shù)并不會(huì)真正將層移除。只是用戶看不見而已。如果不放置到屏外,敵人坦克仍會(huì)被阻擋,子彈仍會(huì)再次擊中用戶坦克。這將會(huì)是很荒唐的場(chǎng)面。</p><p>  為了能控制一輛坦克在同一時(shí)間只能發(fā)射一發(fā)子彈,在子彈生命運(yùn)行結(jié)束時(shí)候,將調(diào)用userSprite.enableShoot()恢復(fù)坦克繼續(xù)發(fā)炮的能力。因?yàn)樵诎l(fā)炮期間,坦克的再次發(fā)炮的功能是被鎖定的。</p><p><b

102、>  結(jié)論</b></p><p>  本程序設(shè)計(jì)實(shí)現(xiàn)使用J2SE為工具的坦克大戰(zhàn)游戲的開發(fā),采用從外部文件讀取配置文件、自動(dòng)控制敵人坦克運(yùn)行的方式進(jìn)行控制,具有一定的可玩性和復(fù)雜性。經(jīng)過了細(xì)心的調(diào)試和排錯(cuò)解決了絕大部分的問題。</p><p>  但幾乎每一個(gè)計(jì)算機(jī)程序都會(huì)有這樣那樣的不足,尤其是未經(jīng)過精心維護(hù)的非商業(yè)軟件。即使是作為操作系統(tǒng)的各種版本的Windows也

103、時(shí)常會(huì)發(fā)生許多類型的錯(cuò)誤和漏洞。本游戲程序?qū)τ诔跎娲祟I(lǐng)域的畢業(yè)設(shè)計(jì)課題來說,尤其在開始初期,感覺邏輯復(fù)雜,難以控制,因此至今還有一些未能解決的bug。</p><p>  目前發(fā)現(xiàn)的bug和未完善的功能列表如下:</p><p>  1、敵人的人工智能變化較少,不夠理想。</p><p>  2、子彈和敵人經(jīng)常會(huì)與畫面的刷新的線程不同步,造成畫面閃爍。</p&

104、gt;<p>  3、 由于每次子彈發(fā)射和每次坦克的移動(dòng)的一個(gè)像素都會(huì)對(duì)所有坦克和所有子彈進(jìn)行一次循環(huán)檢查,并由于同時(shí)開的線程比較多,使得本來運(yùn)行效率就不高的JVM運(yùn)行異常緩慢。即使刷屏沒有間隔也不會(huì)提高速度。尤其在坦克比較多,炮彈比較多情況下尤為明顯。</p><p>  4、有的時(shí)候開始LOGO不能正常顯示。</p><p>  已經(jīng)解決的重要bug:</p>

105、<p>  1、當(dāng)發(fā)出子彈到達(dá)邊界并同時(shí)還在草叢中時(shí)會(huì)拋出數(shù)組邊界異常。</p><p>  2、有時(shí)會(huì)莫名其妙的死機(jī)。 </p><p>  本科期間做過很多課程設(shè)計(jì),大多規(guī)模很小。在各種應(yīng)用軟件和游戲中,我仍覺得對(duì)游戲的設(shè)計(jì)有極大的熱情。因?yàn)槠涓鱾€(gè)模塊間的聯(lián)系十分緊密,代碼重復(fù)執(zhí)行率高,當(dāng)經(jīng)過無數(shù)次的調(diào)試、修改后,能最終看到成品,有無比自豪的心情。大學(xué)期間做過銀行取款機(jī)

106、、圖書館管理程序等簡(jiǎn)單的數(shù)據(jù)庫管理系統(tǒng)的課程設(shè)計(jì),思想大致相似,變化范圍有限,沒有太多自己可發(fā)揮的余地。大家作品的最終結(jié)果都離不開同一個(gè)模式。相比一些數(shù)據(jù)庫軟件,游戲的設(shè)計(jì)有很多人情色彩和藝術(shù)思想的發(fā)揮,正式商業(yè)的軟件的人性化界面和各個(gè)游戲間迥異的結(jié)構(gòu)每每會(huì)讓人有去開發(fā)的沖動(dòng)。</p><p>  游戲程序最大限度的利用了硬件條件,因此展現(xiàn)出的畫面往往多彩絢麗、效果驚人。成功的游戲融合了三維運(yùn)算、人工智能、音效處

107、理等計(jì)算機(jī)多媒體的精華部分。本畢業(yè)設(shè)計(jì)建立在Java平臺(tái)上,是本人以前未曾接觸過的領(lǐng)域。憑著探索新知識(shí)的熱情,我選擇了該設(shè)計(jì)題目。</p><p>  學(xué)習(xí)該平臺(tái)背景和功能的時(shí)間遠(yuǎn)遠(yuǎn)超出了我想象的時(shí)間。在設(shè)計(jì)初期,為了畫出一個(gè)簡(jiǎn)單的圖形,需要花費(fèi)一天的時(shí)間,為了使圖形產(chǎn)生動(dòng)態(tài)效果又會(huì)花費(fèi)幾天的努力。很多相關(guān)的技術(shù),如需要使用到的線程、設(shè)計(jì)模式、Game包的新功能、高級(jí)、低級(jí)圖形界面的使用、時(shí)鐘的控制、貼圖,每一項(xiàng)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論