日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

手机游戏毕业设计论文

發布時間:2023/12/15 编程问答 64 豆豆
生活随笔 收集整理的這篇文章主要介紹了 手机游戏毕业设计论文 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1? 緒論

1.1 手機軟件現狀

在信息社會中,手機及其他無線設備越來越多的走進普通百姓的工作和生活,隨著信息網絡化的不斷進展,手機及其他無線設備上網絡勢在必行。但是傳統手機存在以下弊端:

1.? 傳統手機出廠時均由硬件廠商固化程序,程序不能增加、刪除,有了錯誤也不能更新、修改,若要增加新功能必須另換一部手機。

2.? 傳統手機訪問互聯網是通過WAP(Wireless Application Protocal),所有網絡資源必須接通網絡才能在線訪問,非常耗時、費用亦很高。

而Java技術在無線應用方面的優勢非常明顯:

1.? 應用程序可按需下載,而不是購買由硬件商提供的套件,可升級空間大。

2.? Java技術提供了一個類庫,它使的應用開發商可以創建更為直覺、豐富的用戶界面(GUI);

3.? Java技術使網絡帶寬的應用更為有效,因為應用程序可以下載到器件上,并在本地運行,僅僅是在連接到服務器時才會占用網絡帶寬。

基于以上分析,Java手機將是未來手機的發展方向,是業界的熱點。

1.2 J2ME介紹

雖然 Java 已經被用到許多企業級軟體上,可是其實骨子里面還是非常適合用在嵌入式系統之中。Java平臺演進到Java2后,Java平臺分別針對不同領域的需求被分成四個版本,亦即J2EE、J2SE、J2ME以及JavaCard。其中J2ME定位在消費性電子產品的應用上。這個版本針對資源有限的電子消費產品的需求精簡核心類庫,并提供了模塊化的架構讓不同類型產品能夠隨時增加支持的能力。這個版本的應用層面相當廣泛,會是未來Java平臺發展的重點項目。

J2ME在1999年的JavaOne開發人員大會上初次亮相,它的目標是面向智能無線設備和小型計算機設備的開發人員。J2ME的一個關鍵優點是,J2ME與所有支持Java的設備都是兼容的。支持Java的設備就是任何運行Java虛擬機器的計算機。Motorola、Nokia等生產廠商都生產支持Java的設備。、

J2ME平臺是由配置(Configuration)和簡表(Profile)構成的。配置是提供給最大范圍設備使用的最小類庫集合,在配置中同時包含Java虛擬機。簡表是針對一系列設備

提供的開發包集合。在J2ME中還有一個重要的概念是可選包(Optional Package),它是針對特定設備提供的類庫,比如某些設備是支持藍牙的,針對此功能J2ME中制定了JSR82(Bluetooth API)提供了對藍牙的支持。

目前,J2ME中有兩個最主要的配置,分別是Connected Limited Devices Configuration(CLDC)和Connected Devices Configuration(CDC)。

作為第一個面對小型設備的Java應用開發規范,CLDC是由包括Nokia,Motorola和Siemens在內的18家全球知名公司共同協商完成的。CLDC是J2ME核心配置中的一個,可以支持一個或多個profile。其目標主要面向小型的、網絡連接速度慢、能源有限(主要是電池供電)且資源有限的設備,如手機、PDA等。

而CDC則是主要用于運算能力相對較佳、在電力供應上相對比較充足的嵌入式裝置 (比方說冷氣機、電冰箱、電視機機頂盒 (set-top box))

1.3 手機游戲應具有的特征

??? 一個手機游戲應該具有以下特征:

易于學習: 既然手機游戲面向的是普通消費者而不是計算機專家,那么他們不可能深入的學習游戲技巧。消費者不會花幾個小時去研究一個3元的手動操作的游戲。保持游戲的簡單是最基本的要求。

可中斷性: 多任務處理是手機生活方式的基本特征。手機用戶常常在任務(如等一個電子郵件或者等車)之間有一小段時間。而游戲、日歷管理、通訊和工作數據訪問使用的是同一個設備。所以一個好的手機游戲應該提供短時間的娛樂功能,并且允許用戶在游戲和工作模式之間順利切換。

基于訂閱:手機游戲的盈利成功取決于他們巨大的使用量。一開始開發和設計每個游戲都是昂貴的。如果一個手機游戲開發者要贏利的話,重要的是:同一個游戲引擎,多個標題,基本的故事情節類似。基于訂閱的游戲是不斷產生收入的最好方法。

豐富的社會交互: 不管一個游戲設計得多好,只要玩家找到了它的根本模式或者玩完了所有的游戲路徑很快就會厭煩這個游戲。對于一個基于訂閱的游戲,重要的是與別的玩家合作以增強所玩游戲的智力和隨機性。在今天紛繁復雜的多玩家游戲中具有豐富社會交互的游戲證明是成功的。

利用手機技術的優點: 巨額的手機技術研發費用都花在提高設備和網絡的可用性和可靠性上面。因此,手機設備硬件和網絡協議與桌面/控制臺世界(如全球定位系統(GPS)擴展、條形碼掃描儀、和短消息服務(SMS)/多媒體信息服務(MMS)通訊)有著非常大的差別。好的手機游戲應該利用那些更新的設備特征和網絡基礎設備的優點。

1.4 本游戲背景介紹

在抗戰中,由國民政府領導的中國空軍是所有國民黨軍隊中抗戰最為徹底,也最為英勇的部隊,雖然開戰之初力量懸殊,但是面對窮兇極惡的日本侵略者,他們毫不畏懼,視死如歸,全力以赴投身到民族救亡的偉業中去,用自己的鮮血和生命譜寫了中華民族最為豪邁的詩篇。自一九三二年二月五日“一·二八”事件始,至一九四五年八月十四日止,抗戰期間,共出動飛機一千一百二十八批,八千八百四十七架次,擊落敵機五百二十九架,擊傷敵機一百一十架,炸毀敵機二百二十七架。同時,中國空軍空戰中一共犧牲空勤人員六百六十一名。

我至今仍然清楚的記得,在抗日戰爭即世界反法西斯戰爭勝利50周年的時候,我在一本描述抗戰空軍的書里第一次看到閻海文烈士那年青的面孔時所帶來的震撼,第一次看到高志航、沈崇海等空軍烈士的事跡時所帶來的感動,第一次聽說碧山空戰時的無奈。

時至今日,已經很少有人能夠記得在中國的天空獻身的抗日英雄們,我只能引用下面這句話來表達我的心情:“你們的名字無人知曉,你們的業績與世長存! ”

我的這款游戲取名為《覽橋風光》,以紀念從覽橋中央航校走出的英雄們。

1.5 本章小結

引言和第一章中介紹了手機在無線應用方向的當今概況,J2ME的相關內容,分析了J2ME在手機軟件開發中起的重要作用,描述了本論文的相關背景。

?

?

?

?

?

?

?

?

?

?

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

2.1? 開發環境

操作系統:Microsoft Windows XP

程序語言:Java 2

開 發 包:Java(TM) 2 Standard Edition (5.0)

??????? Sun Micro. J2ME?? Wireless Tool Kit 2.2

IDE:??? Eclipse 3.01

2.2? Java語言特點

1. 平臺無關性

Java引進虛擬機原理,并運行于虛擬機,實現不同平臺之間的Java接口。Java的數據類型與機器無關。

2. 安全性

Java的編程類似C++,但舍棄了C++的指針對存儲器地址的直接操作,程序運行時,內存由操作系統分配,這樣可以避免病毒通過指針入侵系統。它提供了安全管理器,防止程序的非法訪問。

3. 面向對象

??? Java吸收了C++面向對象的概念,將數據封裝于類中,實現了程序的簡潔性和便于維護性,使程序代碼可以只需一次編譯就可反復利用。

4. 分布式

Java建立在TCP/IP網絡平臺上,提供了用HTTP和FTP協議傳送和接收信息的庫函數,使用其相關技術可以十分方便的構建分布式應用系統。

5. 健壯性

Java致力與檢查程序在編譯和運行時的錯誤,并自動回收內存,減少了內存出錯的可能性。Java取消了C語言的結構、指針、#define語句、多重繼承、goto語句、操作符、重載等不易被掌握的特性,提供垃圾收集器自動回收不用的內存空間。

2.3? 關于ECLIPSE

??? Eclipse 是一個開放源代碼的、基于 Java 的可擴展開發平臺。就其本身而言,它只是一個框架和一組服務,用于通過插件組件構建開發環境。幸運的是,Eclipse 附帶了一個標準的插件集,包括 Java 開發工具(Java Development Tools,JDT)。

雖然大多數用戶很樂于將 Eclipse 當作 Java IDE 來使用,但 Eclipse 的目標不僅限于此。Eclipse 還包括插件開發環境(Plug-in Development Environment,PDE),這個組件主要針對希望擴展 Eclipse 的軟件開發人員,因為它允許他們構建與 Eclipse 環境無縫集成的工具。由于 Eclipse 中的每樣東西都是插件,對于給 Eclipse 提供插件,以及給用戶提供一致和統一的集成開發環境而言,所有工具開發人員都具有同等的發揮場所。

這種平等和一致性并不僅限于 Java 開發工具。盡管 Eclipse 是使用 Java 語言開發的,但它的用途并不限于 Java 語言;例如,支持諸如 C/C++、COBOL 和 Eiffel 等編程語言的插件已經可用,或預計會推出。Eclipse 框架還可用來作為與軟件開發無關的其他應用程序類型的基礎,比如內容管理系統。Eclipse 是一個開放源代碼的、基于 Java 的可擴展開發平臺。就其本身而言,它只是一個框架和一組服務,用于通過插件組件構建開發環境。

2.4 關于Wireless Tool Kit

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

2.5 Java Appication Manager

手機中負責調配程序運行資源的管理后臺是Java Application Manager。它所使用的傳輸媒體可以是紅外線、網絡、以及其他可用來傳輸的媒體。Java Application Manager 會從網絡上下載代表該Application Suite 的JAR 檔,接著在手機上安裝此MIDlet Suite,然后在手機開始執行該應用程序。

2.6 本章小結:

第二章介紹了Java語言的特點、本程序的開發環境及其相關工具的原理和使用。

?

3? 程序結構、思想和相關技術

3.1 本程序需要解決的主要技術問題

1.? 游戲程序是一項精度要求很高的程序系統,因為其代碼利用率很高。一個實時運行的最終作品,每秒都會運行成千上萬行程序,繪圖事件、鍵盤事件都會以極高的頻率在后臺等待響應,若有絲毫的差別都將很容易導致程序在運行不久后可能出現嚴重錯誤,甚至死循環。因此,其邏輯設計應當相當嚴謹,需將所有可能發生的事件及意外情況考慮在設計中。

2.? 游戲中為了美觀,適用性強,可能需要采用外部文件引入的圖片貼圖,有關貼圖,在MIDP2.0中提供了用于增強游戲功能的game包,使得解決靜態或動態、畫面背景、屏幕刷新的雙緩沖等都有較好的解決方案。

3. 玩家飛機的運行可以通過鍵盤響應事件控制,但敵方則因為是自動運行,就需要有一定的智能性;敵人飛機的運行算法也要進行相關的設置,已免游戲過于簡單。

4.對于雙方發射的子彈應該賦予不同的速度,同時,程序應該設定敵人飛機的子彈不與敵人的飛機進行碰撞檢測,已增加游戲的可玩性。

5. 雙方的飛機在前進時也需要考慮到是否碰撞到對方飛機,以免重疊運行,造成許多物理上不可能的情況,缺乏真實感。每一次刷新頁面、每前進一步都需要進行相關的碰撞檢測。

6.為了增加界面的美觀,在程序中添加了白云。由于手機屏幕大小有限,所以白云的數量和出現的位置要經過相關的設置,才能實現白云不規則出現的效果。

7.? 游戲的地圖不可能通過繪圖來解決。否則,不僅難于控制和處理過多的元素,也會因過多的大型圖片而不能限制程序的大小,失去手機上程序的原則和Java的優勢。

8.? Java是基于虛擬機的半解釋型編譯系統,其執行效率較C++等完全編譯后的程序會低很多,程序如果不進行精簡和優化,將可能導致運行的不流暢。除開發過程中對結構上的控制、變量的使用、算法的優化等優化外,還可以使用混淆器(Obfuscator)進行程序打包后的優化。

9.? 游戲的結束、開始、動態信息畫面作為構成一個程序都是必不可少的重要部分。良好的用戶界面更是吸引用戶的硬指標,相關的美術構圖和人性化設置也需要有一定的考慮。

以上相關技術細節和整體流程將分別在以下小節闡述。

3.2? 程序流程

消減狀態

(Destroyed)

停止狀態

(Paused)

運行狀態

(Active)

StartApp()

DestroyApp()

呼叫MIDlet的構造函數

DestroyApp()

PauseApp()

圖3-1? MIDlet的流程

MIDlet suite是MIDP應用程序的最小單位,JAM負責將手機內的MIDlet suite以圖形化的方式呈現,讓用戶能夠選取欲執行的MIDlet suite,一旦選取了某個MIDlet suite,操作系統就會激活KVM執行里面的MIDlet。MIDlet及相關的支持類組成了MIDP應用程序的實際內容。而

每個MIDlet都必須繼承javax.microedition.midlet.MIDlet這個抽象類。在MIDP規范中定義了MIDlet的生命周期,以及可以存在的三種狀態,包括Paused、Active以及Destroyed,每一個MIDlet在任何時刻只可能處于其中的一個狀態。這三種狀態的轉換關系如圖3-1所示:MIDlet有三個狀態,分別是pause、active和destroyed。在啟動一個MIDlet的時

候,應用管理軟件會首先創建一個MIDlet實例并使得他處于pause狀態,當startApp()方法被調用的時候MIDlet進入active狀態,也就是所說的運行狀態。在active狀態調用destroyApp(boolean unconditional)或者pauseApp()方法可以使得MIDlet進入destroyed或者pause狀態。值得一提的是destroyApp(boolean unconditional)方法,事實上,當destroyApp()方法被調用的時候,AMS通知MIDlet進入destroyed狀態。在destroyed狀態的MIDlet必須釋放了所有的資源,并且保存了數據。如果unconditional為false的時候,MIDlet可以在接到通知后拋出MIDletStateChangeException而保持在當前狀態,如果設置為true的話,則必須立即進入destroyed狀態。

本程序采用面向對象的設計模式,對游戲中的所有物體賦予對象的概念和屬性。運行程序后允許用戶選擇執行選項菜單,在開始游戲后將先從外部文件載入地圖文件,對背景的所有物體進行繪圖。在主程序運行的線程中,畫面刷新將以一定的頻率采用雙緩沖技術對屏幕重繪,實時反映整個游戲的進行狀態。

游戲開始后先繪制地圖,并將各個對象實例化。在主程序運行的線程中,游戲中所有的對象都應該運行在同一個線程下。當敵人或者用戶的子彈達到射程范圍后,并不刪除子彈對象,而是使用setVisable(false)使其不能顯示,當用戶或敵人在次發射子彈時,只需使用setVisable(true)設置成可以顯示即可。在屏幕重繪的主程序中,將在每次的循環中判斷若干事件,以便程序進入相關的分支執行相關的反應代碼。如:玩家剩余飛機數是為0、敵人、玩家飛機是否被擊中、屏幕上相關信息的繪制等。

程序為需要完成獨立功能的模塊設置了單獨的類。lzhhdm類繼承自Midlet,gameScrenn類、MenuScreen類繼承自GameCanvas,mybullets繼承自Sprite類。載入程序后首先啟動的是程序介紹的信息畫面。點擊ok后調用MenuScreen類實現菜單。

如果選擇進入游戲,則調用gameScreen類,并且中止MenuScreen類中的線程運行,已提高運行速度。

Mybullets類為玩家子彈類。

3.3 Canvas類

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

3.4 Graphics類

Graphics類提供了簡單的2D繪圖功能。它具有24位深度色彩的繪制能力,以三原色分別各占一個字節表示其顏色。程序只能在paint()函數中使用Graphics繪制,GameCanvas可調用getGraphics()函數直接繪制在緩沖區上,可以在任何時間請求傳輸到前臺。其對象會被傳給Canvas的paint()函數,以便最終顯示。

3.5 MIDP1.0技術下的繪制背景技術

在沒有MIDP2.0前,進行游戲繪圖一般需要手動編程使用雙緩沖。需要在paint()方法內將所想要畫的圖形畫在一張預先準備好的背景上,等所有繪圖操作都完成后再將背景的數據拷貝到實際的屏幕上。Image類提供了一個建立背景的靜態方法createImage(int width, int height),再利用getGraphics()方法取得屬于這個背景的Graphics對象,所進行的繪圖操作都會作用在背景上,等到全部的繪圖操作完成后,再調用drawImage()方法將背景的數據復制到實際顯示的屏幕上。

這樣的技術在繪制動畫時特別有用。繪制動畫時經常需要不斷地更新畫面,而更新畫面的操作就是先將屏幕以fillRect()的方式清除,再將下一張圖片畫在屏幕上,然而反復的清除及重繪會造成屏幕的閃爍現象(flicker),因此使用雙重緩沖的好處就是在背景進行這個清除及重繪的操作,再將完成的繪圖拷貝到屏幕上,由于用戶看不到清除的操作,因此就不會出現閃爍的現象了。不過在某些MIDP的實現上已經加上了雙重緩沖的支持,因此在處理前應先利用Canvas類的isDoubleBuffer()方法來判斷。

3.6 MIDP2.0新增的GameCanvas包

??? J2ME的流行促進幾個運營商和制造商開發了一些支持游戲的類,但是,這卻造成了游戲缺乏可移植性的問題,例如,很難將使用Siemens的Sprite類的游戲移植到Nokia上。

??? 在MIDP2.0版本發布后,這些游戲移植性問題初步得到了解決。MIDP2.0新加入了

GameCanvas、Sprite、Layer、LayerManager、TiledLayer五個與游戲開發相關的類。其中 Layer類一般不會直接用到。

??? Game類的出現不僅降低了錯誤出現的幾率,也使游戲代碼變的更小,因為開發者不需要自己編寫象Sprite這種例子。下面將簡要介紹Game類。

?? ?GameCanvas類繼承自Canvas,所以具有Canvas所具有的功能,還額外增加了一些便于游戲設計的功能。比如: GameCanvas類直接提供了getKeyStates(),使程序員可以在同一個線程自己偵測按鍵的狀態。GameCanvas類提供了flushGraphics()的功能,實現了雙緩沖技術。

??? 所謂的Sprite,就是畫面上獨立移動的圖形。

Sprite類是繼承自Layer的用于存儲多楨的基本可視元素。不同的frame可交相顯示,構成動態的效果。圖片可翻轉、顛倒、由一個主角圖片就可以方便的得到所有方向的顯示狀態,相比原先只能使用Canvas繪圖,需要將所有方向的主角圖象都繪制在png圖象中簡化了許多。Sprite也可以從整合的圖象中讀圖,讀圖時將把大圖分解為若干等寬等高的小圖。每個小圖按照其排列順序有相應的序號,在程序中調用其序號,就可以繪制出相應的圖片。本程序中的雙方飛機、子彈、白云都由Sprite繼承得到。

LayerManager提供控制整體畫面層的控制。它包括了一系列自動獲取了代號和位置的層,簡化了各層加入游戲畫面的過程,提供了自動排序和繪制的能力。

LayerManager存儲了一個層的列表,新的層可以用函數附加、刪除和插入。層的序號相當于坐標的Z軸,0層表示最接近用戶視覺,層數越高,離用戶越遠。層號總是連續的,即使有中間的層被移除,其他層的序號會作相應的調整以保持整體的完整性。LM中的View Window控制著與LM相對坐標的可視區域。改變View Window的位置可以制造出滾動屏幕的效果。

TiledLayer是有一組圖象格元素組成的整塊虛擬圖象。該類使不需要高分辨率的圖象就能創建大幅圖面成為可能。這項技術通常應用在2D游戲平臺的滾動背景的繪圖。一塊整圖可被分割成等大小的圖象格,每塊格有其對應的序號,按照行列遞增。多塊小格可由大塊同時替換組合而模擬動態的背景,這不需要逐塊替換所有的靜態圖象格而顯得非常方便。

3.7 PNG圖片格式

PNG(Portable Network Graphics)格式是MIDlet唯一支持的圖象格式,PNG具體格式由PNG Specification,Version 1.0定義的。PNG格式提供透明背景的圖象,這對繪制游戲畫面和被操縱主角極有幫助。飛機之間或與白云碰撞時就不會因為背景有特定的顏色,顯示出的效果像貼上的圖片而缺乏真實感,物體之間輕微重疊時最上層圖片也不會覆蓋超過其有效象素外的部分。

PNG格式圖片中包含許多定義其圖片特性的冗余部分(Chunks)。這些代碼包含在每一個單獨的png格式圖象中,然而如果將多個png圖象合并在一張幅面稍大一些的整圖中,多個chunks就可以得到精簡,圖片的大小可以得到控制。使用Image類中的createImage函數可從整圖中分割出所需要的元素。在Game包中的TiledLayer和Sprite類都整合了這樣的功能。本程序中的地圖元素都集成在一張beijing.png圖片中,實現了方便的管理和程序體積的精簡。

3.8 玩家飛機的控制方式和敵人方的智能運行

??? GameCanvas提供getKeyStates函數可獲取當前鍵盤上的信息。將以位的形式返回鍵盤上所有鍵的按與釋放的狀態,當bit為1時,按鍵就是被按下的狀態,為0時則為釋放狀態。只需要此一個函數的返回值就可以返回所有鍵的狀態。這保證了快速的按鍵和釋放也會被循環所捕捉。同時,這樣的機制也可檢測到幾個鍵同時按下的狀態,從而提供斜向運行等相應功能(本程序沒有實現斜上運行功能)。

??? 程序運行時應該對玩家飛機是否飛出屏幕的范圍進行檢測,如果飛出屏幕,就應該重新設定玩家飛機的位置。

??? 玩家飛機被擊中后,為了平衡游戲的可玩性,玩家飛機將有短暫時間無敵,即不進行碰撞檢測,同時在屏幕右上角顯示無敵時間。

??? 根據游戲設定,敵人飛機。不能與玩家飛機重合,則他每走一步都需要檢測一下是否與玩家飛機碰撞。Sprite類中提供了collidesWith函數,用于判斷是否與某個Sprite、TiledLayer、Image的對象有圖象上的重合(即游戲中的碰撞)。同理,還需要檢測玩家子彈與敵機、敵機與玩家子彈是否碰撞。如果發生碰撞,將相關精靈圖片替換為爆炸圖片。

敵人飛機需要具有一定的智能性,以便對玩家攻擊,使游戲具有一定的可玩性。敵人可以在適當時候轉向或者開炮火,同時,程序應該檢測敵機是否飛出了界外。

在普通敵機中,有一組敵機的其中一架具有跟蹤功能,其原理為:當其進入屏幕后,根據玩家飛機的X、Y坐標不斷調整自己的X、Y坐標,已達成跟蹤的效果。由于線程的關系,敵機器的改變方向有時并不是實時的,這就可以使玩家有躲開撞擊的可能,增強了游戲的可玩性。

在游戲進行中出現的大型飛機,由于其不可能立即被擊落,所以應該設置其的運行方法,理論上講還是根據玩家飛機的坐標,但是,在此設置一個標志位,使得敵人在取的玩家位置后即開始玩家方向運動,這期間,將不執行取得玩家飛機位置重設飛行方向的步驟。這樣做,即防止了大飛機變成跟蹤飛機,又使得大飛機的運行具有不確定性。

在關尾出現的BOSS,其在屏幕上方左右移動并發射子彈。實際上,此時BOSS應該通過玩家在游戲運行中的習慣性的運行方向,使用遺傳算法,來動態判斷玩家下一步的運行方向,并且指揮普通飛機出現在預測的位置上。可惜由于時間關系沒有實現。

3.9 子彈的運行和控制

??? 玩家的子彈是個精靈數組,有9個元素,表示玩家一次最多可以發射3組9發子彈,對于一個完整的游戲來講,應該根據關卡的不同而給予玩家不同的飛機,飛機性能的差別在于子彈的射程不同。由于本游戲僅有一關,所以子彈速度設定的差別沒有體現出來。

??? 當玩家一次發射了3組子彈,而這3組子彈并沒有消失時,玩家將無法發射子彈。

??? 使用每組子彈的第一發作為與敵人進行碰撞檢測的精靈,同時相關的標志位也設在第一發子彈中。如果玩家子彈與敵機相撞,則敵機消失時,子彈精靈的圖片替換為爆炸圖片,直到第二次發射該組子彈時,才將圖片替換為子彈圖片。

3.10 內存的優化

手機內存空間小,所以在程序設計時應該注意以下幾點,以盡量減少內存的使用:

??? (1)盡量縮短命名的長度。在應用程序內,對于所建立的類、接口、方法及變量名而言,都需要賦予一個識別的名稱,所命名的名稱每多一個字符就會在類文件內多產生一個字節,對于一個較復雜的應用程序而言就會增加為數不小的數據量。所有這些可以借助混淆器來幫助實現

??? (2)所有代碼寫為一個類。

??? (3)只使用一個線程。

??? (4)盡量不使用靜態變量。

??? (5)將PNG圖片合并成一張,減少圖形數據的大小。

將PNG格式的小分辨率圖象合并在一張大的高分辨率圖象中,由于減少了頭文件的大小,將比合并前的總大小減少許多。

3.11 內存檢測器

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

3.12 關于混淆器

Java 語言并沒有完全編譯成二進制可執行文件,編譯出的.class文件是一種介于源程序和二進制之間的一中基于半解釋的字節碼,需要虛擬機來執行。它包括了所有的信息。然而這樣會導致.class很容易被反編譯為源代碼,從而不能保護作者的知識成果。目前流行的如decode,JAD等反編譯工具可以以很快的速度生成源文件。如果不加以施行有效的措施,將造成嚴重的后果。

由此引入混淆器的概念。混淆器將代碼中的所有變量、函數、類的名稱變為簡短的英文字母代號,如果缺乏相應的函數名指示和程序注釋,即使被反編譯,也將難以閱讀。

??? 混淆器的作用不僅僅是保護代碼,它也有精簡編譯后程序大小的作用。由于以上介紹的減少變量、函數的命名長度的關系,編譯后也會從.class文件中減少這些冗余的信息。混淆后,體積大約能減少25%,這對當前費用較貴的無線網絡傳輸是有一定意義的。

3.13 本章小結

第三章中介紹了程序的流程、相關技術的思想及其在本程序中的應用。對游戲基本算法等做了詳細敘述。具體算法的代碼實現和詳細流程將在下章介紹。

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

4? 程序分析和具體實現

4.1 游戲進入前的選擇

每個MIDlet程序都必須有一個主類,該類必須繼承自MIDlet。它控制著整個程序的運行,并且可以通過相應函數從程序描述文件中獲取相關的信息。該類中擁有可以管理程序的創建、開始、暫停(手機中很可能有正在運行程序卻突然來電的情況,這時應進入暫停狀態。)、結束的函數。本程序主類為lzhhdm,并實現接口CommandLIstener。

首先顯示的是游戲的背景介紹(圖4-1),為此,在類lzhhdm定義Form類對象a,在startApp()函數中判斷isSplash是否為真,如果為真的話,將創建Form類的實例a,并且調用append()方法在表單上放置StringItem類的實例以顯示游戲背景信息。使用語句ok=new ?Command("ok",Command.OK,1);實例化Command類對象ok。調用addCommand()命令建立ok命令與Form之間的關聯,調用setCommandListener()命令使Form與CommandListener建立關聯。調用Displayable的

圖4-1游戲背景介紹??????????????????

?? seturrent()函數顯示背景介紹窗口。

???? 當玩家點擊ok后將調用display.setCurrent(menuscreen)??

以顯示游戲菜單menuscreen(圖4-2)。?

??? 類menuscreen繼承自Canvas類,并實現接口Runnable

和CommandListener。在類menuscreen中定義了lowColor和

highColor、highBGColor三個整型變量及布爾型變量co。其

中lowColor賦值為0x000000FF,代表蘭色,higColor賦值為

0x00FF0000,代表紅色,highBGColor賦值為0x00CCCCCC,代表

圖4-2 游戲的菜單

蘭灰色,即背景條。當玩家按住上或下鍵時,在函數keyPressed

(int code)中的整型變量menuIndex相應的減1或加1,相應的,在paint()函數中會根據menuIndex繪制選項是否被選中。在函數run()中,如果co為真,則不停的repaint(),設置co的意義在于,當進入游戲主畫面后,co賦值為false,以終止繪制選項的repaint(),提高游戲速度。???????????????????????????????????? ?????

??? 當移動選項條到某項,并點擊ok時,在commandAction()方法中根據 menuIndex??????????????????????????????????????????????????????????

進入游戲

y1>-1550

pzbzover==0

?

顯示敵人

玩家被擊落了嗎 ?

玩家是否還有機會?

繼續游戲

是否過關

返回主界面

Y

Y

N

?

Y

Y

N

圖4-4 gameScreen類主要關系流程圖

N

的值判斷選擇了哪個選項,列如當選擇“關于”時,將調用lzhhdm類中的renwuShow()方法以顯示”關于”界面(圖4-3),在renwuShow()方法中,Form類對象a=null,表示清空Form,并重新調用用append()方法在表單上放置StringItem類的實例以顯示游戲關于信息,“幫助“界面的顯示與”關于“界面相同,只不過調用的是helpShow()方法。

???????????

????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

????

?

???????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

?

??

?

圖4-3關于界面

?


4.2 mybullets類??

在介紹游戲主類gameScreen類之前,應該先簡要說明一下玩家子彈類mybullets類,實際上,mybullets類是應該刪除的,其要實現的功能應該放在gameScreen類中,但是由于設計游戲的過程也是一個學習的過程,而在當時,我并沒有意識到這一點。???????????????????????????????????????????

???? Mybullets類繼承自Sprite類,以實現玩家子彈的相關功能。首先,創建子彈狀態數組private int[][] bullets,其中,[i][0]代表子彈的X坐標,[i][1]代表子彈的Y坐標,[i][2]代表子彈Y方向速度,[i][3]代表子彈存活狀態(由于此類是在早期設計的,而之后子彈存活狀態使用了子彈射程作為標志位,所以其并沒有起到作用)。類中定義的方法setfirstposition()起到定義玩家子彈發射坐標的作用(此方法在設計時起到的作用是消除每按一次開火玩家子彈位置就重新定位這個BUG,但是,這個BUG完全可以用設置標志位的方法消除)。方法newposition()實現的功能為更新玩家的子彈位置,并且檢測玩家子彈與普通敵人的碰撞及記錄玩家戰果(更新子彈位置的功能可以由使用move()加設置標志位的方法取代;由于設計這個類的時候并沒有考慮到添加BOSS等,所以在此檢測碰撞,但添加BOOS等功能后,此處的檢測完全可以和飛機對飛機等的碰撞檢測封裝在同一個方法中)。

mybullets類在gameScreen中建立了對象數組huokebullet[9],代表玩家所能發射的9發子彈。

4.3 游戲邏輯及gameScreen類

??? gameScreen類是游戲的主類,決定著敵人何時出現,控制著敵人出現的方法,判斷敵人及玩家是否被擊中等。它運行在獨立的線程中,以恒定的頻率刷新畫面。本程序設置為1/20秒。其主邏輯如圖4-4所示。?????

4.3.1 gameScreen類所實現的功能

gameScreen類要實現地圖的滾動、敵人飛機的相關屬性、玩家的相關屬性等功能。

gameScreen類包括了LayerManager,這樣所有靜態和動態的圖象都不需要手動刷新,只需要在LayerManager中加入所有的需要控制的精靈,在統一由LayerManager刷新即可, 因此,在gameScreen中創建LayerManager的對象lm,并在構造函數中實例子化。

其他精靈類的對象如敵人飛機、玩家飛機、玩家飛機的子彈、敵人的子彈、BOSS及BOSS所屬的子彈都需在gameScreen()類中建立相應的對象,并在構造喊數中實例化,且由lm.appned()方法添加到LayerManager類對象lm中。

4.3.2 地圖的創建

?? 由于手機存儲空間的限制,不可能將整張地圖完整地存儲在手機中,為了節約空間,往往提出地圖中相同的圖片組成一張PNG格式的圖片,然后象拼圖一樣拼出地圖來,專業的游戲設計者往往自己寫一個地圖編輯器,以使拼圖過程不是那么痛苦。

創建地圖就需要使用TiledLayer。TiledLayer指的是由一塊一塊類似用瓷磚拼湊起來的畫面。地圖實際即為TiledLayer的一個對象。先利用TiledLayer的構造函數建立TiledLayer,根據構造函數的參數可以給定Cell數組 的大小,并且地圖圖片切割成等尺寸的畫面,并調用setCell()設置具體的圖象格內容。地圖

圖4-5 地圖

圖片如圖4-5所示。

??? 因此,創建一個返回TtiledLayer的方法createBackGround(),以便在gameScreen()的構造函數中調用。在方法中,定義整型數組map1[]以存儲Cell的索引值。并使用tiledLayer.setCell(column,row,map1[i])設定TtiledLayer的內容,以形成地圖。其中i的值由循環for(int i=0;i<map1.length;i++)取得,column由語句column=i%15取得、行由row=(i-column)/15取得。

??? 畫出地圖后,由lm.append()將地圖添加到LayerManager類對象lm中。由于地圖位于Layer的最低層,即離用戶視線最遠的層,所以Tiledlayer最后一個被添加到lm中。

4.3.3地圖的移動??

?? ?根據游戲的設定,游戲中地圖是向下移動的,實現此功能的方法如下:

??? 首先,在使用createBackGround()函數創建地圖數組時,用(row+1)*16-getHeight()??????????????????????????? ????????????????????????

語句對整型變量row2賦值,其中row+1代表地圖有多少列,16為地圖片的高度,而減去getHeight()是因為要留出一個屏幕的可視區域,由于J2ME規定坐標系中下方向為正,所以使用語句y1=-row2將row2的數值變為負數。

??????

? (0,y1)

?????????????????? ??????y1=y1+1;

?????????????????? View Window????????????

??????????????????? 向下移動??????????????

? (0,0)??? ???????????????????????????????????????????????????????????????????????

?

????????

圖4-6?

?????????

??? ????????圖4-6?

?

?????????????????????? ?????????????????????????????????????????????

??? 其次,render()函數中,使用lm.setViewWindow(0,0,getWidth(),getHeight()+10000)設定可視區域的范圍,(0,0)表示View Window的起始坐標,(getWidth() ,getHeight()+10000)?

使用lm.paint(g,0,y1)決定

View? Window從屏幕的哪里畫起。

在run()函數中的while(conti)中,

屏幕

使用語句y1=y1+1使得每次繪圖都使

地圖下移1個象素。(參考圖4-6)

4.3.4 gameScreen類的構造函數

gameScreen類的構造函數要將游戲中出現的所有精靈都實例化,實際上,這種方法

嚴重的占用了內存,但在當時,我并沒有意識到這一點。

由于敵人要求不停的出現,但是不可能設置過多的精靈,解決的辦法是設定6個Sprite類對象j0、j1、j2及jbullet1、jbullet1、jbullet2,分別代表三架敵機及其配屬的子彈。所以在gameScreen類的構造函數分配這6個Sprite類的存儲空間,并且使用new Sprite(Image img, int width,int height)實例化這6個類變量。同關尾cboss與游戲進行中的大飛機其他的Sprite類對象都需要使用相同的方法實例化。同樣處于節約內存的考慮,sboss與cboss同用3個Sprite類對象bossbullet0,1,2。

??? 在構造函數中,定義boolean型變量conti=true。conti的作用在于控制是否進行游戲畫面的重繪及其他需要在畫面重繪前進行的運算。

??? 在構造函數中,將mybullets類里的no和score初始化,現在看來no的初始化沒有必要,但是score的初始化是必須的,因為這個變量存儲著玩家每次游戲的成績,如果不在此進行初始化,則玩家重新開始游戲后score并不歸0。

4.3.5 關于commandAction()方法

每個創建Command實例的J2ME的應用程序也必須創建實現CommandListener接口的實例。每當用戶通過commandAction()方法的方式與命令進行交互的時候,就會通過CommandLIstener.所以實現CommandListener的類必須實現commandAction()方法。

在commandAction()方法中,使用getabel()方法獲取命令的標簽。如果getLabel()=“暫停”時,表示玩家點擊了暫停鍵,此時,conti賦值為false,游戲畫面的繪制及游戲相關的運算暫停,并且,使用removeCommand(c)語句將“暫停”移除,使用addCommand(new Command("繼續",Command.OK,2));將”繼續“按紐”添加進來。當玩家點擊“繼續“時,conti賦值為true,并且,一定要調用start()方法,否則繼續功能不可用。必須調用start()方法的原因是:J2ME的線程已stop()方法拿掉,如果想停止線程的運做,就必須依靠一個旗標(flag),在本程序中,flag就是boolean型變量conti。所以一旦此標識變量被設為false,那么while(conti)循環就會結束,線程也會跟著結束。當用戶按下“繼續”的時候,start()將重新產生一個線程繼續執行相關的運算和畫面繪制。

當玩家通關時或者任務失敗時,將顯示相應信息,并使用上面的方法將“暫停”鍵變為“返回”鍵盤,當點擊“返回”鍵時,將返回主菜單選項,調用類lzhhdm里的方法menuscreensecond(),在此方法中,實例化一個MenuScreen類對象,并且使選項“新游戲”改變為”重新開始“(圖4-7)。完成此項功能的語句子為MenuScreen.mainmenu[0]=”重新開始”。當選擇”重新開始“時,使用gamescreen=new gameScreen(this)將使所有變量重新被初始化,如地圖的繪制、敵人出現位置的重置、敵人的數量、玩家飛機的當前位置等。使用gamescreen.start()重新開始程序的循環。

4.3.6 Sprite類對象的碰撞檢測及相關屬性

??? 游戲進行中,即在while(conti){ }中,需要進行玩家飛

機、子彈與敵機及敵機子彈與玩家飛機的碰撞檢測,即使用函

數collidesWith(Sprite,boolean)。由于設計的問題,玩家發

射的子彈與普通敵機的碰撞檢測被寫在了mybullets類中,并

且只檢測第一發子彈是否與敵人相碰撞,如果碰撞為真時,則

使用setVisible(false)函數將敵機隱藏,使用setImage()函

數將子彈精靈的三張圖片置換為爆炸圖片( 圖4-8 )。當敵人剩

圖4-7

余飛機消失后,即所有的敵人都飛出了屏幕后,使用函數

setVisible(true)將敵機重新設置為可見。在按“開火”鍵時,使用setImage()函數將huokebullets重新設定為子彈圖片(每次擊落敵機后屏幕上的爆炸效果有3團,并且按“開火”后爆炸圖片就消失了,實際上setVisavle(false)的應該是子彈數組,而對敵人精靈使用setImage(),這樣效果會好一些)。

敵機與玩家的碰撞檢測原理同上,都是使用的collidesWith()函數,遺憾的是,我在寫這段代碼的時候,并沒有考慮設置玩家有4次機會,所以對敵人飛機setVisable(fasle)了,而將玩家的飛機換成了爆炸圖片,之后,添加了玩家4次機會這個功能,由于玩家被擊落后會重新從屏幕下方進入屏幕,所以爆炸的圖片一閃而過,效果不是很好。

4.3.7 玩家4次游戲機會的實現方法????????

?? ?根據游戲設置,玩家在每關中有共四次機會,當玩家飛機被擊中或撞擊爆炸后,程序首先檢測整型變量playerno的值,并根據playerno的值決定屏幕右上角所畫玩家飛機標志的數量(參考圖4-8),playerno的初始值設為3,因為碰撞后才減1,所以玩家共有4次機會,當playerno<0時,游戲結束,同時將變量pver賦值為1,render()或renderboss()函數中,over=1代表在屏幕上GAMEOVER等相關信息,同時,將整型變量inputno賦植為1,以使手機的方向鍵失效,以消除玩家可以控制爆炸圖像移動這個BUG。同時整型變量pzbz賦植為1,以消除玩家爆炸圖像繼續與敵人進行碰撞檢測這個BUG。

??? 當playerno>0時,碰撞后,將變量planert賦值為1,在之后的if(planert==1)判斷語句中,重新設定玩家飛機的圖片和可視狀態,同時使用setPosition()函數設定玩家非的位置在屏幕下方。設定pzbz=1,即不檢測碰撞,玩家有短暫時間無敵,無敵時間由屏幕右上角進度條表示。設定inputno=1,即飛入屏幕的過程中手機鍵盤是不可以用的。設置planert=2,即以上這些設置只執行一便。

???? 在if(planert==2)判斷語句中,使用語句move(

0,-2)使飛機自己向上運動,使用if(c1.getY()<(

planepo-24))判斷飛機是否到達屏幕最下方(planepo

是屏幕下邊緣的坐標),如條件為真,則將inputno

設置為1,表示鍵盤可用,將planert賦值為3,使

其不再執行以上各步。

4.3.8 input()

?input()函數的作用是檢測用戶的輸入。

首先使用if(inputno==0)判斷用戶的輸入是否

被禁止,如為真,則用戶輸入不被禁止。

圖4-8 游戲界面

其次,調用getKeyStates()查詢按鍵的狀態。

當玩家按方向鍵時,玩家飛機就向不同的方向運行,這需要使用c1.move(int x,int y)函數,當玩家控制飛機向左或右飛時,需要使c1.setFrame()函數改變飛機的圖形(參見圖4-7,此時飛機右飛)。同時,還需要判斷飛機是否飛出屏幕,如,當飛機右飛時,用if(c1.getX()>(getWidth()-c1.getWidth()))

語句判斷(getWith()為屏幕的寬度,c1.getWidth()為玩家飛機c1的寬度),如果條件為真,則使用c1.setPosition((getWidth()-c1.getWidth()),c1.getY())語句將飛機設置在緊靠屏幕右邊的位置。上、下、左的設置原理同上。

??? 語句if((keystate&LEFT_PRESSED)==0)的作用是消除左、右飛后在上、下飛時飛機的形態不變的BUG。如果為真,則執行語句c1.setFrame(0),表示只要左鍵松開飛機的形態都是平飛。

根據游戲設定,玩家一次最多只能發三組子彈,并且子彈有射程限制(在類mybullets中使用整型變量no表示),而當玩家按下“開火“鍵時,即if((keystate&FIRE_PRESSED)!=0)中判斷條件為真時,首先執行循環語句for(int i=0;i<=6;i=i+3),即檢測3組子彈中每組的第一發,即0,3,6。其次,檢測huokebullet[i].no是否等于1,當等于1時使用語句for( int z=i;z<i+3;z++)初始化該組子彈中的3發子彈,而設置子彈位置的函數應該在if(huokebullet[i].no==1)語句外設置,因為當初設計的時候mybullets類里的函數寫成了一次設置三組子彈的形式。

huokebullet[z].no=huokebullet[z].bulletheight賦予子彈射程。當程序循環運行時no--,當一次發射了三組子彈后,只有某一組子彈消失,即no等于1后才能繼續發射子彈。

現在看來,玩家發射子彈的設置是完全失敗的,降低了效率。

4.3.9 render()和renderboss()

在方法render()過程中,除了要重繪飛機、地圖、子彈外還要在上方繪制關卡信息、戰果、玩家飛機數、及無敵狀態時的無敵時間、大飛機生命條等。

首先使用lm.setViewWindow()和lm.paint()設定可視范圍ViewWindow和從哪里畫起(見4.3.3)。

其次,使用g.drawString()繪制屏幕上方的關卡信息、戰績、玩家剩余生命標志。

drawString()中使用String.valueOf(huokebullet[0].rscore()+huokebullet[3].

rscore()+huokebullet[6].rscore())返回玩家成績score的字符串表示。

其中根據playerno的值繪出玩家的飛機標志數(應該有更好方法,但是沒有想到 )當每次刷新繪圖頁面時,應使用GameCanvas的flushGraphics()將屏幕后臺的緩沖區內的圖像刷新到前臺來(flushGraphics()應該寫在render(){ }的最后)。

renderboss()方法重繪的是關尾的精靈cboss、相關信息等,與render()的區別在與于函數lm.paint(g,0,0),起始坐標是不可變的,即,關尾的地圖背景是不可變的。實際上,renderboss()是完全不需要的,只要在render()函數中設置相關標志位就可以解決關尾的繪圖問題。

玩家飛機的生命標志使用drawImage()就可以繪制在屏幕上了。

4.4 游戲中的獎勵及相關飛機的行為

? ??根據游戲設定,當y1=-1000時,會出現如圖4-8

所示的飛機(sboss),當玩家擊落他后,屏幕會顯示“

援軍到達“,并且玩家剩余飛機數加1。

??? 使用 if((y1==-1000)&&(sbz==0)){ }設定sboss的

初始位置,根據游戲設定,sboos從屏幕上方倒飛入屏幕,

所以sboss設定的初始位置(50,planepoup-65),其中

planepoup為屏幕上邊緣的標志位。

圖4-9

最后,要將sbz賦值為1,消除sboos不停設置初始位置的BUG。

??? 當sboss飛入屏幕后,將sbz賦值為2,以執行下面

的if(sbz==2)語句。

圖4-10

? ??在判斷語句if(sbz==2)里,將根據玩家的位置自動飛

行。首先,根據玩家飛機的位置對sbmove賦值,當c1在sboos的上、下、左、右時,其對應的值為1、2、3、4在這4個if語句中,要設置標志位(smovebz==0)。設置這個

標志位的目的是防止sboos根據c1的位置不停的改變運行狀態,即防止sboos成為跟蹤飛機。當sboos根據c1的位置改變一次運行方向后,smovebz賦值為1,即不檢測c1

的位置。只有sboss運行到屏幕的邊緣時,才將smovebz重新賦值為0,使其可以再次通過c1的位置決定sboos的運行方向。

當玩家子彈擊中sboss后,使用sboss.setFrame(1),此時飛機變紅,在本次repaint結束前,使用sboss.setFrame(0)使飛機變為本來顏色,而程序設定每1/20秒畫一次,由此得到飛機被擊中后變色的效果。(參見圖4-10)。

??? sboos會根據玩家飛機的位置發射子彈,根據游戲設置,當玩家在其上方、左方、右方時,sboss一次發射1發子彈,而玩家飛機在其下方時,sboss一次發射3發子彈。????????????????????????

??? sboss與cboss共用3發子彈,因為當sboss出現時,離關尾還遠,所以,為了提高效率,采用這種方法。

??? 如果sboos被擊落后,使用函數setVisable(false)將bossbullet0、bossbullet1、bossbullet2設置為不見,使用sboss.setImage()函數將sboos的圖片設置為爆炸圖片。同時,玩家生命標志playerno加1,sbz賦值為-1,使得sboos無法發射子彈,sbpzbz賦值為1,使得玩家的子彈不與sboos進行碰撞檢測。

??? 同時在屏幕中使用drawString()繪制“援軍到達”四個字,隨著屏幕的運動,爆炸圖片逐漸進入屏幕下方,當sboos.getY()>palnepo,通過改變標志位的值使得drawSteing()不在執行,四字消失。

??? 如果玩家被擊落后并沒有點“返回“,而此時,背景會一直運動到關尾,考慮到其與關尾BOSS共用3發子彈,如sboos不消失,將會出現子彈亂飛的情況。所以,如果判斷語句if((sboss.getY()==getHeight()))為真,則表示離地圖的終點只有一個屏幕的距離時,sbz賦值為-1、sbpzbz賦值為1(含義上面已經說明)。同時調用sboss.move(0,-3),使sboos快速飛出屏幕,直到判斷語句if(sboss.getY()<-65)為真時,調用下面的函數setVisable(false),使得sboos不可見。

4.5 普通敵人相關屬性

?? ?普通敵人是指游戲中不斷出現的蘭色飛機。

??? 首先在程序中首先定義了aik、aip兩個Random()類對象,ai和aipp兩個整型變量。程序中使用switch(ai)語句判斷下一次的飛機出現情況,為了達到不重復出現的效果,使用語句ai=aik.nextInt()%4(同樣應該在構造函數中放置此語句和aipp=aip.nextInt() % 5,以使每次游戲開始的時候敵人飛機的出現順序是不固定的),以隨機出現0,1,2,3四個整數(代表著飛機的四種出現情況)。

? ??情況1:使用 aipp=aip.nextInt()%5取得隨機數aipp,根據下面三條語句設置飛機的出現位置:j0.setPosition(100-aipp*30,planepoup+24);

?? ???????j1.setPosition(100,planepoup);

?? ???????j2.setPosition(100+aipp*30,planepoup-24);;

將getHeight()/8賦給整型變量kkk,每次循環kkk-1,當kkk<=1時飛機轉向,當aipp>0時,飛機向左下方運行,使用語句setFrame(0)、move(-3,3)達成向左下方運動的效果。當aipp<0時,向右下方運動,實現方法同上。

??? 情況2:初始位置設置方法同情況1。當kkk〈0時,飛機掉頭向上飛,其中setFrame(3),

move(-4,0)。

??? 情況3:初始位置設置方法同情況1。當kkk〈0時,飛機只向左轉。設置情況3的原因是在更多的隨機位置出現敵機。

??? 情況4:初始位置設置方法同情況1。但其中的飛機j1具有跟蹤能力,其實現方法如下:使用2個if語句if(j1.getX()<c1.getX())、if(j1.getX()>c1.getX())判斷J1在c1的左或右側,并且實時根據判斷情況使用setFrame()和move()改變飛機的形態,使用語句

if((j1.getX()<c1.getX())&&((j1.getX()+48)>c1.getX())&&(j1.getY()<c1.getY()))判斷c1是否在j1的下方,當c1在j1的下方時,發射子彈jbullet1。

???? 以上四種情況的最后,都將使用函數nextInt()產生ai,aipp的值。

???? 設置整型數組jb[4],對應著4種出現情況的標志位。

???? 如,執行情況1,首先執行判斷語句if(jb[0]==1),在此語句中,首先使用setVisable (true)函數將敵人飛機設置為可見的,并根據上次運行的qipp的值設置敵人飛機的初始位置最后,jb[0]賦值為2。

??? 接著執行判斷語句if(jb[0]==2),在此語句中,首先使用move()函數使飛機向下運動,同時kkk減1,當kkk<=0時,飛機轉向,此時,根據aipp的正負判斷飛機向哪邊轉向。當飛機飛出屏幕時,jb[0]賦值為3。

??? 需要注意的一點是,當取得ai的數值時,一定要寫上這條語句:jb[ai]=1;因為當4種情況都出現一便的時候,標志位jb[]里的數值都將變為3,如果不將其重新賦值為1,敵人飛機將只能出現4次。

??? 其他3種情況也大致如此。

??? 普通敵人是否發射子彈由以下語句if(((j1.getX()<=c1.getX()-18)||((j2.getX() -6)>=c1.getX()))&(jbz==0)),即c1在j1左側18象素范圍內或j2左側6象素范圍時,j0、j1、j2一起發射子彈,jbz=1,表示在這組子彈消失前敵人不發射子彈。

?? ?如果jpb的值為0,則判斷語句if(jpb==0)里的move()語句將一直執行下去。

??? 之后,還需要對每發子彈于玩家飛機進行碰撞檢測,如果碰撞,則將碰撞的這發子彈設置為不可見。

4.6 白云的實現原理

???為了游戲界面更加美觀,程序中設定了精靈數組cloud[i]來表示白云,由于白云應該在所有飛機的上方,即cloud[i]應該最早被append()到LayerManager中,或者使用insert (cloud[],0)在索引數值0處插入Layer,本程序采用了第一種方法,即在gameScreen類的構造函數中按游戲設置的順序使用lm.append()加入到LayerManager之中。

??? 程序中設定白云數為5。首先設置白云的初始位置,其語句如下:

cloud[0].setPosition(25,planepoup-(65));

cloud[1].setPosition(80,planepoup-(140));

cloud[2].setPosition(112,planepoup-(90));

cloud[3].setPosition(175,planepoup-(200));

cloud[4].setPosition(223,planepoup-(70));

其原理為:將屏幕的X數軸和Y數軸各分成5份,即在X軸的5個范圍內每個范圍出現一朵白云,Y軸的每個范圍內也只能出現一朵。所以的白云的起始位置在每次游戲開始時是固定的。

白云位置設定后,使用move(0,1)使白云移動,由于白云初始位置設定在屏幕的不同區域內,故其移動出屏幕的先后順序是不同的,使用if(cloud[].getY()>planepo)判斷白云是否飛出屏幕。如果為真則使用cloud[].setPosition(cloudposition*40,planepoup)設置白云的位置,其中,cloudposition=aicloud.nextInt()%5,aicloud為Random()類對象。乘以40表示其在X軸出現的范圍是多少,cloud[0]、cloud[1]、cloud[2]、cloud[3]、 cloud[4]乘以的值分別為40,30、55、15、22。以達成白云的隨機出現效果。

4.7 關尾BOSS及相關屬性

??? 關尾處飛機在屏幕上方橫向移動,而背景地圖不動,所以使用renderboss()重繪屏幕,其中,paint(g,0,0)表示屏幕繪制點在坐標軸(0,0)處。BOSS生命進度條由以下語句繪制:

g.setColor(255,0,0);

?????????? ???????? g.fillRect(2,2,60,5);//生命進度條背靜紅

?????????? ???????? g.setColor(255,255,255);

?????????? ???????? g.fillRect(2,2,bosslife,5);//生命進度條前景白

其中bosslife記錄著BOSS的生命值,其初始值為0,當玩家每擊中一次BOSS,其值加5,,即化出白色進度條,當bosslife==60時,表示過關,除玩家飛機與子彈外的其他Sprite均使用setVisable(false)使其不在顯示,同樣的pzbz要賦予1,以消除玩家飛機還能與敵人碰撞的BUG。

??? 如果cboss.getX()<0,則表示其在屏幕左方出界,應改為右飛。同理如果cboss.getX()

>(getWidth()-cboss.getWidth()),則表示其在屏幕右方出界,應改為左飛。

在飛機橫向飛行中,使用以下語句判斷飛機是否開火:

if(((cboss.getX()<=c1.getX()-10)||(cboss.getX()<=c1.getX()+60))&&(jbsz==0))

當每發一組子彈后,jbsz=1,則飛機無法開火,知道子彈

飛出屏幕,jbsz才重新設定為0。而((cboss.getX()<=

c1.getX()-10)||(cboss.getX()<=c1.getX()+60)表示當

玩家飛機處于BOSS的左右各10個象素的范圍內時。BOSS

開火。關尾參見圖4-10。

4.8本章小結

第四章中按照相應的步驟描述了所有關鍵類的具體算

圖4-10關尾

法實現,引用了相關函數進行了具體流程的解釋,并對原

理稍復雜的函數做了詳細的分析。對游戲有關的各運行面也做了展示。

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

5? 測試

5.1 打包測試的過程

?? ?使用Eclipse完成代碼的調試之后,需要使用WTK生成包(即jar和jad文件),其過程如下:首先,使用WTK的新建項目功能建立一個新項目,要求與Eclipse工作區下的項目名稱、MIDlet類名相同(圖5-1)。

5-1

?? 新建項目后,將Eclipse工作區下的.java文件拷入src文件夾,將.class文件拷入class文件夾(需要新建),將pic文件夾拷入res文件夾,點擊生成,如一切正常,將如圖片5-2所示。

圖5-2

之后,選擇項目-包-生成包。如圖5-3所示。

圖5-3

生成的jar和jad文件存儲在lzhhdm/bin目錄下。

運行Motorola SDK v4.2 for J2ME,使用MOTOA760手機模擬器進行測試。參考圖5-4。點擊Lanuch按紐,進入如圖5-5的界面,即可以進行游戲測試了。

圖5-4

? ?測試的過程,實際上就是找不同的同學玩這款游戲,以期望發現BUG。實際上,幾乎每一版本都會產生很多BUG。?????????

5.2 發現的BUG及解決情況????

幾乎每一個計算機程序都會有這樣

那樣的不足,尤其是未經過精心維護的

非商業軟件。即使是作為操作系統的各

種版本的Windows也時常會發生許多類

型的錯誤和漏洞。本游戲程序對于初涉

此領域的畢業設計課題來說,尤其在開

始初期,感覺邏輯復雜,難以控制,因

此產生了大量BUG,其中一些BUG還沒有

解決,所有發現的BUG如下:

1.玩家子彈出現順序問題;

2.玩家飛機爆炸后仍然可以控制爆

炸圖片;?????????

3.當過關后仍然會發生碰撞;

圖5-5

4.當玩家擊落可獎人飛機的同時玩

家被擊落,并且此為玩家的最后

一架飛機,雖然顯示援軍到達,但

圖5-5

游戲仍然結束。

5.有某組飛機在飛機被擊中后仍能發射子彈;

6.sboos左側子彈發射后不停在原位置刷新問題;

7.? 游戲運行一段時間后變的很卡;

??? 其中,1、2、3、4條BUG已經解決(方法已在第4章相關位置進行了說明)。4、5、6沒有解決,其中,4、5、6三條如果有足夠的時間可以解決。第7條以現有水平無法解決,因為出現這種情況的原因估計是內存的問題,而由于水平的關系,現在的代碼變量過多,并且效率低下,有很多重復的地方,解決的方法只能是在水平提高的情況下重寫整個程序。

5.3 未完善的功能

經過匯總測試人員的建議,本游戲應該完善的功能如下

1. 由于每按一次開火,就會對玩家子彈的精靈數組進行一次循環檢查,使得本運行效率就不高的KVM運行異常緩慢。即使刷屏沒有間隔也不會提高速度;

??? 2. 最好有接寶物的設置,增強可玩性;

??? 3. 由于沒由合適的圖片,使得敵人設置單一;

??? 4. 地圖本應由外部文件讀入,但設計初期并沒有掌握這項技術;

??? 5. 手機游戲最好只有一個類,而我卻有4個;

??? 7. 沒有添加成績記錄,即英雄榜;

??? 6. 最大的遺憾,敵人不夠智能化。

??? 希望不遠的將來,我能夠有能力對這個游戲進行重寫,以解決BUG、完善功能。

???

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

6? 總結

6.1 本程序的總結和展望

?? ??本程序設計實現了手機上以J2ME為平臺的飛行射擊游戲的開發,敵人運行的方式由程序進行控制,具有一定的可玩性和復雜性。經過了細心的調試和排錯解決了絕大部分的問題。

?但是我的水平實在有限,在第5章列舉的眾多BUG和遺憾就可以看出這一點來,但我相信,隨著時間的推移,個人水平的增長,我一定會重寫這個程序,使其更加完善,

6.2 感想

?? 這款游戲作為我的畢業設計,是本人目前做過的最有意義的程序,這期間對J2ME的學習,使我又回到了初學PASCAL的時候。

本科期間做過很多課程設計,大多規模很小。在數據庫、各種應用軟件和游戲中,我仍覺得對游戲的設計有極大的熱情。因為其各個模塊間的聯系十分緊密,代碼重復執行率高,當經過無數次的調試、修改后,能最終看到成品,有無比自豪的心情。大學期間做過圖書館管理程序等簡單的數據庫管理系統的課程設計,思想大致相似,變化范圍有限,沒有太多自己可發揮的余地。大家作品的最終結果都離不開同一個模式。相比一些數據庫軟件,游戲的設計有很多人情色彩和藝術思想的發揮,正式商業的軟件的人性化界面和各個游戲間迥異的結構每每會讓人有去開發的沖動。

??? 學習J2ME的困難遠遠超出了想象,在設計初期,為了解決地圖的滾動、玩家飛機如何不飛出上下邊界兩個問題竟然花費了數天的時間。很多相關的技術,如需要使用到的線程、Game包的新功能、高級、低級圖形界面的使用、貼圖等,每一項都需要花一定的時間去掌握和熟悉。更為困難的是,J2ME為一種剛出現僅幾年的新技術,國內的參考資料非常少,僅有的幾本也停留在簡單的介紹階段。臺灣的王森寫了本較好的書,給了我很大的幫助,但對設計該游戲來說,仍只夠入門。

???? 幸運的是,互聯網上有那么多無私的人,由Jason Lam著,Deaboway Chou譯的電子書《J2ME&Gaming》給了我很大的幫助,作者、譯者的辛勤勞動的成果免費放在網上由大家下載,是開源精神的完美體現。

?

???

首先感謝我的指導老師馬慧彬副教授,她在我的畢業設計過程中提出了指導性的方案和架構,并指引我閱讀相關的資料和書籍,使我在不熟悉的領域中仍能迅速掌握新興的技術。

感謝黃明旭、包明輝同學對游戲進行測試,感謝包明輝同學對游戲相關圖片的修改。

感謝答辯組對本畢業設計的考核,如果可以得到專家的認可將對我的學習和工作給予極大的鼓勵。你們客觀的評價和建議我將牢記在心,在今后的發展中揚長避短,更加努力的嚴格要求自己。

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

參考文獻

[1]Joshua Bloce著. 潘愛民譯. Effective Java中文版.2004年7月第4版. 機械工業出版社.

[2]Bruce Eckel.侯捷譯.Java編程思想. 2005年3月第1版. 機械工業出版社出版社

[3]王森著.Java手機/PDA程序設計入門.2005年2月第3版.電子工業出版社.

[4]James Keogh著.潘穎王磊譯.J2ME開發大全.2004年2月第1版清華大學出版社.

[5]Ian Sommerville著.程成等譯.軟件工程.2003年1月第1版.機械工業出版社.

[6]Jason Lam著.Deabo way Chou譯 J2ME&Gaming 2004年末 www.jasonlanm604.com

[7]陳立偉 張克非 黎秀紅著.精通JAVA手機游戲與應用程序設計.中國青年出版社.

2005年5月

[8]飛思科技產品研發中心.精通Jbuilder9.電子工業出版社.2004年

[9]微型爪哇人.Java手機程序開發.中國鐵道出版社,2003年

[10]Frand M.Carrano,Janet J.Prichard?.著?韓志宏?譯.數據抽象和問題求解——

JAVA語言描述.清華大學出版社2005年4月

[11]袁海燕 王文濤著.JAVA實用程序設計100例.人民郵電出版社.2005年5月

[12]Jonathan Knudsen.What's New in the J2ME Wireless Toolkit 2. 22004年4月www.sun.com



?

?

?

?

?

?

?

?

?

?

?

?

?

附錄一? 代碼


import javax.microedition.midlet.MIDlet;

import javax.microedition.midlet.MIDletStateChangeException;

import javax.microedition.lcdui.*;

public class lzhhdm extends MIDlet implements CommandListener {

??????? public Display display;

?????? private Image splashLogo;

?????? private boolean isSplash=true;

??????? public Form a;

??????? private Alert alert;

??????? int length;

??????? private MenuScreen menuscreen;

??????? private gameScreen gamescreen;

??????? private Command ok,back;

??????? private byte[] byteInputData;

?????? public lzhhdm()

?????? {

?????? }

?????? protected void startApp() throws MIDletStateChangeException {

?????? display=Display.getDisplay(this);

?????? menuscreen=new MenuScreen(this);

?????? if(isSplash)

?????? {? a=null;

????????????? a=new Form("覽橋風光V1.0");

????????????? ok=new Command("ok",Command.OK,1);

?????? ??? a.append(new StringItem(null,"....."));

????????????? a.addCommand(ok);

????????????? a.setCommandListener(this);

?????? ??? display.setCurrent(a);?

?????? }

?????? }

?????? protected void menuscreenShow()

?????? {

????????????? display.setCurrent(menuscreen);

?????? }

?????? protected void menuscreensecond() {

?????????????

????????????? menuscreen=new MenuScreen(this);

????????????? MenuScreen.mainmenu[0]="重新開始";//玩完一遍或掛了后在玩一遍 菜單第一項改為 重新開始

????????????? display.setCurrent(menuscreen);

????????????? }

?????? protected void pauseApp() {}

?????? protected void destroyApp(boolean arg0) throws MIDletStateChangeException {??

?????? }

?????? protected void helShow()

?????? {? a=null;

????????????? a=new Form("覽橋風光V1.0");

????????????? back=new Command("返回",Command.BACK,1);

?????? ??? a.append(new StringItem(null,"操作方式:上 2 下 8 左 4 右 6 開火 5"));

?????? ??? a.append(new StringItem(null,"彈藥數:一次最多打三組"));

????????????? a.addCommand(ok);

????????????? a.setCommandListener(this);

?????? ??? display.setCurrent(a);

?????? }

?????? protected void renwuShow()

?????? {

????????????? a=null;???

????????????? a=new Form("覽橋風光V1.0");

????????????? back=new Command("返回",Command.BACK,1);

?????? ??? a.append(new StringItem(null,"游戲名稱:覽橋風光"));

?????? ??? a.append(new StringItem(null,"版本號:V1.00"));

?????? ??? a.append(new StringItem(null,"制作者:信息電子技術學院01計算機5班 劉澤華 學號:7"));

????????????? a.addCommand(ok);

????????????? a.setCommandListener(this);

?????? ??? display.setCurrent(a);

?????? }

?????? protected void gameShow()

?????? {?? try{

??????

????????????? gamescreen=null;

????????????? gamescreen=new gameScreen(this);

?????????????

????????????? gamescreen.start();

???????????????????? display.setCurrent(gamescreen);

????????????? gamescreen.conti=true;

?????? }catch(Exception exp)

?????? {

?????? System.out.println("dfg");

?????? }

?????? }

??????

?????? public void commandAction(Command arg0, Displayable arg1) {

????????????? a=null;

?????????????

????????????? this.menuscreenShow();

?????? }

}

import javax.microedition.lcdui.*;

public class MenuScreen extends Canvas? implements Runnable,CommandListener

{

?Font lowfont=Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_PLAIN,Font.SIZE_MEDIUM);

?????? ? Font highfont=Font.getFont(Font.FACE_MONOSPACE,Font.STYLE_BOLD,Font.SIZE_MEDIUM);

?????? ?int lowColor=0x000000FF;

?????? ?int highColor=0x00FF0000;

?????? ?int highBGColor=0x00CCCCCC;

?????? ?int width;

?????? ?boolean co;

?????? ?int height;

?????? ?int startHeight;

?????? ?int spacing=highfont.getHeight()/2;

?????? public? static String[] mainmenu={"D?ó??·","°??ú","1?óú"};

?????? ?int menuIndex;

?????? Thread menuThread;

?????? private Command ok=new Command("ok",Command.OK,1);

?????? private lzhhdm midlet;

?????? public MenuScreen(lzhhdm midlet)

?????? {???? this.midlet=midlet;

????????????? width=getWidth();

????????????? height=getHeight();

????????????? startHeight=(highfont.getHeight()*mainmenu.length)+((mainmenu.length-1)*spacing);

????????????? startHeight=(height-startHeight)/2;

????????????? menuIndex=0;

????????????? addCommand(ok);

????????????? ?setCommandListener(this);??????

????????????? menuThread =new Thread(this);

????????????? menuThread.start();

????????????? co=true;

?????? }

??????

?????? public void run()

?????? {

????????????? while(co)

????????????? {

???????????????????? repaint();

????????????? }

?????? }

??????

?????? public void paint(Graphics g)

?????? {?

????????????? g.setColor(0x00FFFFFF);

????????????? g.fillRect(0,0,width,height);

????????????? for(int i=0;i<mainmenu.length;i++)

????????????? {

???????????????????? if(i==menuIndex)

???????????????????? {?

??????????????????????????? g.setColor(highBGColor);

??????????????????????????? g.fillRect(0,startHeight+(i*highfont.getHeight())+spacing,width,highfont.getHeight());

??????????????????????????? g.setFont(highfont);

??????????????????????????? g.setColor(highColor);?????? g.drawString(mainmenu[i],(width-highfont.stringWidth(mainmenu[i]))/2,startHeight+(i*highfont.getHeight())+spacing,20);

???????????????????? }else

???????????????????? {

??????????????????????????? g.setFont(lowfont);

??????????????????????????? g.setColor(lowColor);

???????????????????? ?????? g.drawString(mainmenu[i],(width-lowfont.stringWidth(mainmenu[i]))/2,startHeight+(i*highfont.getHeight())+spacing,20);

???????????????????? }

????????????? }

?????? }

?????? public void keyPressed(int code)

?????? {

????????????? if(getGameAction(code)==Canvas.UP&&menuIndex-1>=0)

????????????? {

???????????????????? menuIndex--;

????????????? }

????????????? else if(getGameAction(code)==Canvas.DOWN&&menuIndex+1<mainmenu.length)

????????????? {

????????????? ?????? menuIndex++;

????????????? }

?????? }

?????? public void commandAction(Command c,Displayable d)

?????? {

????????????? if (c==ok)

????????????? {

???????????????????? switch(menuIndex)

???????????????????? {

???????????????????? ? case 0:

???????????????????? ? ?? ?co=false;

???????????????????? ? ?? midlet.gameShow();

???????????????????? ? ?? break;

?????????? ? case 1:

?????????? ? ? midlet.helShow();

?????????? ? ? break;

?????????? ? case 2:

?????????? ? ? midlet.renwuShow();

?????????? ? ? break;

?????????? }??

?????? }

??? }

}

import javax.microedition.lcdui.*;

import javax.microedition.lcdui.game.*;

public class mybullets extends Sprite

{?? public? int score=0;

?????? private int[][] bullets;

?????? private int bulletstotal;

??? public int width,bulletheight;

? ?? public int no=0;

?????? public mybullets(Image img,int picwidth,int picheight,int bulletstotal,int width,int height)

?????? {??????

???????????????????? super(img,picwidth,picheight);

???????????????????? this.bulletstotal=bulletstotal;

???????????????????? bullets=new int[bulletstotal][4];

???????????????????? this.width=width;

???????????????????? this.bulletheight=height/7;???

?????? }

??? public void initBullets(int i)

??? {

??? ???????????? bullets[i][3]=1;

??? ???????????? bullets[i][2]=0;

??? }

??? public void updata(int i)

??? {

??? ????? bullets[i][1]+=bullets[i][2];

??? }

??? public void setfirstposition(int x,int y,int nof,Sprite sprite[],Image img)

??? {?? ???

??? ????? sprite[nof].setVisible(true);

??????? sprite[nof+1].setVisible(true);

??????? sprite[nof+2].setVisible(true);

??? ????? bullets[nof][0]=x+10;

??????? bullets[nof][1]=y-24;

??????? sprite[nof].setImage(img,6,6);

??????? bullets[nof+1][1]=bullets[nof][1]+10;

??????? bullets[nof+1 ][0]=x+10;

??????? sprite[nof+1].setImage(img,6,6);

??????? bullets[nof+2][1]=bullets[nof+1][1]+10;

??????? bullets[nof+2 ][0]=x+10;

??????? sprite[nof+2].setImage(img,6,6);

??? }

??? public void newposition(Sprite sprite[],int i,int v,Sprite jp0,Sprite jp1,Sprite jp2,Sprite boss,Image img)

??? {? ??????

??? ????? bullets[i][2]-=5;

??? ????? sprite[i].setPosition(bullets[i][0],bullets[i][1]+bullets[i][2]);

??? ????? sprite[i+1].setPosition(bullets[i][0],bullets[i+1][1]+bullets[i][2]);

??? ????? sprite[i+2].setPosition(bullets[i][0],bullets[i+2][1]+bullets[i][2]);

??????? if (sprite[i].collidesWith(jp0,true))

??????? {

??????? ???? sprite[i].setImage(img,32,32);

??????? ???? sprite[i+1].setImage(img,32,32);

?????? ????? sprite[i+2].setImage(img,32,32);

??????? ???? sprite[i].setFrame(1);

??????? ???? sprite[i+1].setFrame(1);

??????? ???? sprite[i+2].setFrame(2);

??????? ???? bullets[i][3]=0;

??????? ???? bullets[i+1][3]=0;

??????? ???? bullets[i+2][3]=0;

??????? ???? jp0.setVisible(false);

?????? ????? no=1;????

?????????? score=score+1;

??????? }

??????? if (sprite[i].collidesWith(jp1,true))

??????? {

??????? ???? sprite[i].setImage(img,32,32);

??????? ???? sprite[i+1].setImage(img,32,32);

??????? ???? sprite[i+2].setImage(img,32,32);

??????? ???? sprite[i].setFrame(1);

??????? ???? sprite[i+1].setFrame(1);

??????? ???? sprite[i+2].setFrame(2);

??????? ???? bullets[i][3]=0;

??????? ???? bullets[i+1][3]=0;

??????? ???? bullets[i+2][3]=0;

??????? ???? jp1.setVisible(false);

??????? ???? no=1;

??????????????? score=score+1;

??????? }

??????? if (sprite[i].collidesWith(jp2,true))

??????? {

??????? ???? sprite[i].setImage(img,32,32);

??????? ???? sprite[i+1].setImage(img,32,32);

??????? ???? sprite[i+2].setImage(img,32,32);

??????? ???? sprite[i].setFrame(1);

??????? ???? sprite[i+1].setFrame(1);

??????? ???? sprite[i+2].setFrame(2);

??????? ???? bullets[i][3]=0;

??????? ???? bullets[i+1][3]=0;

??????? ???? bullets[i+2][3]=0;

??????? ???? jp2.setVisible(false);

??????? ???? no=1;

??????? score=score+1;

??????? }

??? }

??? public boolean isAlive(int i)

??? {

??? ????? if (bullets[i][3]==1) return true;

??????????? else return false;

??? }

??? public void setAlive(int i)

??? {

??? ????? for (int z=i;z<i+3;z++)

??? ????? {

??? ???????????? bullets[i][3]=0;

??? ????? }????

??? }

??? public int rscore()

??? {

??? ????? return score;

??? }

public void clean(int i,Sprite sprite[])

{

?????? for (int z=i;z<i+3;z++)

?????? {

????????????? //sprite[z].setPosition(0,-1500);

????????????? sprite[z].setVisible(false);

????????????? no=1;????

?????? }}}

import javax.microedition.lcdui.*;

import javax.microedition.lcdui.game.*;

import java.util.*;

public class gameScreen extends GameCanvas implements Runnable,CommandListener

{?? private Form al;

??? public LayerManager lm,lm1;

??? TiledLayer b1;

??? int height=getHeight();

??? int bosscolor=0;

??? int sbosscolor=0;

??? int sbz=0;

??? int sbmove=0;

??? int sfire=0;

??? int smovebz=0;

??? int sbpzbz=0;

??? int slife=0;

??? int sbo=0;

??? int drawslife=0;

??? int lr=0;

??? int drawadd=0;

??? int pzbz=0;

??? int pzbzover=0;???

??? int? playlife=-1;

??? int bosslife=0;

??? int inputno=0;

??? int position=0;

??? int j1b=0;

??? int jbsz=-1;

??? int sbsz0=-1;

??? int sbsz1=-1;

??? int sbsz2=-1;

??? int sbsz3=-1;

??? int planepo;

??? int planepoup;

??? int kkk;

??? int gz=0;

??? int gzks=0;

??? int jiangli=0;

??? int jplaneno;

??? int cloundno=0;

??? int right=0;

??? int left=1;

??? int boss=0;

??? int over=0;

??? int ai=0;

??? int planert=-1;

??? int supermen=0;

??? int overcmd=0;

??? int bossover=0;

??? int jpb=-12;

??? int aipp=0;

??? int jbz=0;

??? int cloudposition;

??? Random aik=new Random();

??? Random aip=new Random();

??? Random aicloud=new Random();

??? int jb[]=new int[5];

??? int playerno=3;

private mybullets[] huokebullet=new mybullets[9];

privateSpritejbullet0,jbullet1,jbullet2,bossbullet0,bossbullet1,bossbullet2;

private Sprite cloud[]=new Sprite[5];

private MenuScreen ms;

privateSpritec1,sboss,cboss,j0,j1,j2,boss1; private lzhhdm midlet;

int s1=0;int s2=65;int s3=0;int row2;

int row;int planecolor=0;

int planecoco=0;public int by1;

public int y1;

public gameScreen (lzhhdm midlet)

{? super(true);this.midlet=midlet;

addCommand(new Command("暫停",Command.BACK,1));

?setCommandListener(this);

?lm=new LayerManager();

c1=new Sprite(img("/pic/MyPlaneFrames.png"),24,24);

cboss=newSprite(img("/pic/boss.png"),65,50);jbullet0=newSprite(img("/pic/bullet.png"),6,6);

jbullet1=new Sprite(img("/pic/bullet.png"),6,6);

jbullet2=new Sprite(img("/pic/bullet.png"),6,6);

bossbullet0=new Sprite(img("/pic/bullet.png"),6,6);

bossbullet1=new Sprite(img("/pic/bullet.png"),6,6);

bossbullet2=new Sprite(img("/pic/bullet.png"),6,6);

sboss=new Sprite(img("/pic/smallboss.png"),65,50);

b1=createBackGround(); c1.setPosition(getWidth()/2,row2+getHeight()-25);

System.out.println("ffffffffffff");

?planepoup=row2;

?planepo=row2+getHeight();

j0=new Sprite(img("/pic/jplane2.png"),24,22);

?j1=new Sprite(img("/pic/jplane2.png"),24,22);

?j2=new Sprite(img("/pic/jplane2.png"),24,22);

?kkk=getHeight()/8;

?lm.append(j0);

?lm.append(j1);

?lm.append(j2);

?cboss.setVisible(false);

?aipp=aip.nextInt()%3;

if(aipp==0)

{aipp=aip.nextInt()%3;

}lm.append(cboss);

?lm.append(bossbullet0);

?lm.append(bossbullet1);

?lm.append(bossbullet2);

?lm.append(jbullet0);

?lm.append(jbullet1);

lm.append(jbullet2);

?lm.append(sboss);

?jb[0]=1;jb[1]=1;jb[2]=1;jb[3]=1;

?try{for(int i=0;i<=4;i++){

?cloud[i]=new Sprite(img("/pic/cloud1.png"),16,16);

?lm.append(cloud[i]);}

?}catch(Exception e)

{System.out.println("cloud");}

try{for(int i=0;i<9;i++){

??? ??????????????????? huokebullet[i]=playerbullet("/pic/bullet.png");}}catch(Exception e){}

?try{for(int i=0;i<=8;i=i+3)

?{huokebullet[i].no=1;//ok

? huokebullet[i].score=0;}

? }catch(Exception e){System.out.println("ffffffffffffff");}

?for(int i=0;i<9;i++){

?lm.append(huokebullet[i]);}

?lm.append(c1);lm.append(b1);

}

private Image img (String pic)

{

?Image img=null;

try{ img=Image.createImage(pic);

}catch(Exception exp)

{System.out.println(exp);

}return img;

}

private mybullets playerbullet(String pic)

{Image img=null;

try{ img=Image.createImage(pic);

}catch(Exception exp)

{System.out.println(exp);

}return new mybullets(img,6,6,21,getWidth(),getHeight());}

public TiledLayer createBackGround()

{Image img=null;

try{??????? img=Image.createImage("/pic/beijing.png");

?????????????

?????? }catch(Exception exp)

{System.out.println("layer create image");

}???????????

TiledLayer tiledLayer=new TiledLayer(50,200,img,16,16);

int[] map1[]{ 地圖};

for(int i=0;i<map1.length;i++)

{ int? column=i%15;

row=(i-column)/15;?? ???? tiledLayer.setCell(column,row,map1[i]);}

row2=(row+1)*16-getHeight();

y1=-row2;

return tiledLayer;}

boolean conti=true;

int rate=50;

?????? public void run()

?????? {?? long st=0;

????????????? long et=0;

????????????? Graphics g=getGraphics();

????????????? int l=1350;

?????? ??? while(conti){?

st=System.currentTimeMillis();

???????????????????? input();

if(huokebullet[0].isAlive(0)){

huokebullet[0].no--;

if(huokebullet[0].no>0){?? ????? huokebullet[0].newposition(huokebullet,0,3,j0,j1,j2,cboss,img("/pic/explosion.png"));???? }

if(huokebullet[0].no<=0){??

huokebullet[0].setAlive(0);???????? ???? ?????huokebullet[0].clean(0,huokebullet);

?}}??????? ??? if(huokebullet[3].isAlive(3))

{huokebullet[3].no--;

if(huokebullet[3].no>0)

{? huokebullet[3].newposition(huokebullet,3,3,j0,j1,j2,cboss,img("/pic/explosion.png"));?????? }

?if(huokebullet[3].no<=0)

{huokebullet[3].setAlive(3);??????????

?huokebullet[3].clean(3,huokebullet);

}}?? ?????? if(huokebullet[6].isAlive(6))

{huokebullet[6].no--;??

if(huokebullet[6].no>0){?? ????? huokebullet[6].newposition(huokebullet,6,3,j0,j1,j2,cboss,img("/pic/explosion.png"));???? }

if(huokebullet[6].no<=0){huokebullet[6].setAlive(6);??????????

huokebullet[6].clean(6,huokebullet);} }if (huokebullet[0].collidesWith(cboss,true))

{huokebullet[0].setVisible(false);????????????? ??? huokebullet[1].setVisible(false);??????? ?? ?huokebullet[2].setVisible(false);

cboss.setFrame(1);

?if(bosslife<=55)

?{bosslife=bosslife+5;}

? huokebullet[0].setAlive(0);???????? huokebullet[0].clean(0,huokebullet);} if(huokebullet[0].collidesWith(sboss,true)&&(sbpzbz==0)){ ????? huokebullet[0].setVisible(false);

?? huokebullet[1].setVisible(false);?? ??????? huokebullet[2].setVisible(false);

?????? sboss.setFrame(1);

if(slife<=75){slife=slife+5;}

?huokebullet[0].setAlive(0);????????? ?????? huokebullet[0].clean(0,huokebullet);if(huokebullet[3].collidesWith(cboss,true)){cboss.setFrame(1);???????????? ?????? huokebullet[3].setVisible(false);

?huokebullet[4].setVisible(false);??????????????????????????? huokebullet[5].setVisible(false);

huokebullet[3].no=0;

if(bosslife<=55){

bosslife=bosslife+5;}??????????????????????? ? ?? ??????

huokebullet[3].setAlive(3);????????? huokebullet[3].clean(3,huokebullet);}

if(huokebullet[3].collidesWith(sboss,true)&&(sbpzbz==0)){sboss.setFrame(1);

huokebullet[3].setVisible(false);

huokebullet[4].setVisible(false);

huokebullet[5].setVisible(false);

huokebullet[3].no=1;

if(slife<=75){slife=slife+5;}

huokebullet[3].setAlive(3);?????????? huokebullet[3].clean(3,huokebullet);}

if(huokebullet[6].collidesWith(cboss,true)){???? huokebullet[6].setVisible(false);? ??????? huokebullet[7].setVisible(false);

huokebullet[8].setVisible(false);

cboss.setFrame(1);

if(bosslife<=55){ bosslife=bosslife+5;

}huokebullet[6].setAlive(6);????????? huokebullet[6].clean(6,huokebullet);??

}if(huokebullet[6].collidesWith(sboss,true)&&(sbpzbz==0)){sboss.setFrame(1);

?huokebullet[6].setVisible(false);????????????? ??? huokebullet[7].setVisible(false);??????? ?? huokebullet[8].setVisible(false);

if(slife<=75){slife=slife+5;}

huokebullet[6].setAlive(6);?????? ?????????????????????? ?????? huokebullet[6].clean(6,huokebullet);;}if((y1>-1350)&&(pzbzover==0))

{

?????? switch (ai){

?????? ??? ????? case 0:

?????? ?? ????????????? if(jb[0]==1){

?????? ??? ??????????????????? jbz=0;

???????????????????? ???? ??j0.setVisible(true);

?????? ????????? ????j1.setVisible(true);

?????? ????????????? j2.setVisible(true);

j1.setFrame(2);

?? ??????????????j0.setFrame(2);

?? ??????????????j2.setFrame(2);? j0.setPosition(100-aipp*30,planepoup+24);?? ???? ??????????j1.setPosition(100,planepoup); ????????????????j2.setPosition(100+aipp*30,planepoup-24);jb[0]=2;}

if (jb[0]==2){? j0.move(0,3);

j1.move(0,3);j2.move(0,3);

kkk=kkk-1;? }

if(kkk<=0){jb[0]=3;

if(aipp>=0){

j1.setFrame(0);? ??????? ??????j0.setFrame(0);j2.setFrame(0);?? ???? ????????????????????j0.move(-3,3);j1.move(-3,3);???? ?? ???????????????j2.move(-3,3);}else if(aipp<0)

{j1.setFrame(1);????????? ?????????? j0.setFrame(1);?????????? ???? j2.setFrame(1);j0.move(3,3);j1.move(3,3);

j2.move(3,3);}

if(j2.getY()>planepo)?? {

j0.setVisible(false);j1.setVisible(false);

j2.setVisible(false);jbullet0.setVisible(false);jbullet1.setVisible(false);???????? jbullet2.setVisible(false);jpb=-1;

ai=aik.nextInt()%4;????? ??? ????? ????????aipp=aip.nextInt()%5;

if(aipp==0){aipp=aip.nextInt()%5;

}if(ai<0) ai=ai*(-1);

jb[ai]=1;?????? ????????kkk=getHeight()/8;}}??????????? if((j1.getX()<=c1.getX()-18)&(jbz==0))

{ jpb=0;if(j0.isVisible()){

?jbullet0.setVisible(true);}

?if(j1.isVisible()){

? jbullet1.setVisible(true);}

? if(j2.isVisible()){

? jbullet2.setVisible(true);}????????? jbullet0.setPosition(j0.getX()+12,j0.getY()+30);jbullet1.setPosition(j1.getX()+12,j1.getY()+30);jbullet2.setPosition(j2.getX()+12,j2.getY()+30);jbz=1;}break;????? case 1:

?????? if(jb[1]==1){j0.setVisible(true);

? j1.setVisible(true);j2.setVisible(true);

?j1.setFrame(2);?? j0.setFrame(2);

j2.setFrame(2);j0.setPosition(100-aipp*30,planepoup+24);j1.setPosition(100,planepoup);j2.setPosition(100+aipp*30,planepoup-24);;jb[1]=2;}

if (jb[1]==2){? j0.move(0,3);

j1.move(0,3); j2.move(0,3);

kkk=kkk-1;}

if(kkk<0){jb[1]=3;}

if(jb[1]==3){ jpb=1;j1.setFrame(3);

j0.setFrame(3);j2.setFrame(3);

jb[1]=4;}

if(jb[1]==4){j0.move(0,-4);

j1.move(0,-4); j2.move(0,-4);??? ???

if(j2.getY()<planepoup) {j0.setVisible(false);

j1.setVisible(false);j2.setVisible(false);

jbullet0.setVisible(false);????? ? jbullet1.setVisible(false);jpb=-1;??? ?? ??jbullet2.setVisible(false);? ??? ????? ????ai=aik.nextInt()%4;???????????? ??? ????? ????????if(ai<0) ai=ai*(-1);jb[ai]=1;??

aipp=aip.nextInt()%5;???????? ??? ????? ?????if(aipp==0){ aipp=aip.nextInt()%5;}

kkk=getHeight()/8; }}break;

case 2: if(jb[2]==1){

jbz=0;j0.setVisible(true);

j1.setVisible(true);j2.setVisible(true);

j1.setFrame(2);j0.setFrame(2);j2.setFrame(2);?????? j0.setPosition(100-aipp*30,planepoup+aipp*30);j1.setPosition(100,planepoup);???? j2.setPosition(100+aipp*30,planepoup+aipp*30);;

jb[2]=2;} if (jb[2]==2){?

j0.move(0,3);j1.move(0,3);

j2.move(0,3);kkk=kkk-1;

}if(kkk<=0){jb[2]=3;

j1.setFrame(0);j0.setFrame(0);j2.setFrame(0);j0.move(-3,3);j1.move(-3,3);

j2.move(-3,3);? ? ???if(j2.getY()>planepo) {jpb=-1;

jbullet0.setVisible(false);

? jbullet1.setVisible(false);

?jbullet2.setVisible(false);

j0.setVisible(false); j1.setVisible(false);

j2.setVisible(false); ai=aik.nextInt()%4;

if(ai<0) ai=ai*(-1); jb[ai]=1;? ?? ????????aipp=aip.nextInt()%5; if(aipp==0)

{aipp=aip.nextInt()%5; }

kkk=getHeight()/8; ??? }

}??? if(((j1.getX()<=c1.getX()-18)||((j2.getX()-6)>=c1.getX()))&(jbz==0))

{if(j0.isVisible()){jbullet0.setVisible(true);} if(j1.isVisible()){

jbullet1.setVisible(true);}

if(j2.isVisible()) {

jbullet2.setVisible(true);}????

jpb=0; jbullet0.setPosition(j0.getX()+12,j0.getY()+30);?????? jbullet1.setPosition(j1.getX()+12,j1.getY()+30);

jbullet2.setPosition(j2.getX()+12,j2.getY()+30);jbz=1;}

??? ????? ??break;

???????? case 3:

?if(jb[3]==1){jbz=0;?? ??? j0.setVisible(true);j1.setVisible(true);

j2.setVisible(true);j1.setFrame(2);

j0.setFrame(2);j2.setFrame(2);?? j0.setPosition(200-aipp*50,planepoup-aipp*10);

j1.setPosition(100,planepoup);?? ??????????? j2.setPosition(100+aipp*50,planepoup-aipp*10); jb[3]=2; }

if (jb[3]==2){? j0.move(0,3);

j1.move(0,3);j2.move(0,3);

if(gzks==0){if(j1.getX()<c1.getX())

{j1.move(2,2);j1.setFrame(1);}

if(j1.getX()>c1.getX()){ j1.setFrame(0);

j1.move(-2,2);} if((j1.getX()<c1.getX())&&((j1.getX()+48)>c1.getX())&&(j1.getY()<c1.getY()))

?{j1.setFrame(2);j1.move(0,2); if(j1b==0){ jbullet1.setPosition(j1.getX()+12,j1.getY()+30);j1b=1;}}

?j0.move(0,3);jbullet1.move(0,3);

?j1.move(0,3);j2.move(0,3);} if((j2.getY()>(planepo+22))&&(j0.getY()>(planepo+22))&&((j1.getY()<(planepoup-22))||(j1.getY()>(planepo+22)))){

?jb[3]=1;

gz=0;gzks=0;jbullet1.setVisible(false);

jbullet2.setVisible(false);???? ?? ???????????????j0.setVisible(false);

???? j1.setVisible(false);

??? ????? j2.setVisible(false);

? ai=aik.nextInt()%4; if(ai<0)

?ai=ai*(-1);

jb[ai]=1;?? aipp=aip.nextInt()%5;

if(aipp==0) {aipp=aip.nextInt()%5;}

kkk=getHeight()/8;? }

if((j2.getX()<=c1.getX()-18)&(jbz==0))/

{ jpb=0; if(j0.isVisible())

{jbullet0.setVisible(true);}

if(j2.isVisible()){jbullet2.setVisible(true);

}jbullet0.setPosition(j0.getX()+12,j0.getY()+30);jbullet2.setPosition(j2.getX()+12,j2.getY()+30); jbz=1; }} break;}}if(jpb==0)

{jbullet0.move(0,5); jbullet1.move(0,5);

jbullet2.move(0,5); }

if((jbullet0.collidesWith(c1,true)||jbullet1.collidesWith(c1,true)||jbullet2.collidesWith(c1,true)||bossbullet0.collidesWith(c1,true)||bossbullet1.collidesWith(c1,true)||bossbullet2.collidesWith(c1,true))&&(pzbz==0)){

c1.setImage(img("/pic/explosion.png"),32,32); c1.setFrame(3); if((playerno>0))

{playerno=playerno-1; planert=1;

}else{pzbz=1; overcmd=1;???????

over=1;}}???? if((j0.collidesWith(c1,true)&&(pzbz==0)))????? {

?????? c1.setImage(img("/pic/explosion.png"),32,32); c1.setFrame(3); if(playerno>0)

?????? {playerno=playerno-1; planert=1;

playlife=0; }else{overcmd=1; playlife=1;

over=1;} j0.setVisible(false); pzbz=1;

}if((j1.collidesWith(c1,true)&&(pzbz==0))) {c1.setImage(img("/pic/explosion.png"),32,32); c1.setFrame(3); if(playerno>0)

{playerno=playerno-1; planert=1;

playlife=0; }else{overcmd=1;??????????

playlife=1; over=1;} j1.setVisible(false);

pzbz=1; if((j2.collidesWith(c1,true)&&(pzbz==0)))??????

{c1.setImage(img("/pic/explosion.png"),32,32); c1.setFrame(3);

if(playerno>0) {

playerno=playerno-1; planert=1;

playlife=0; }else{playlife=1;

if(overcmd==0) {}overcmd=1;

}???? over=1;} j2.setVisible(false);

pzbz=1; }if(overcmd==1)

{addCommand(new Command("返回",Command.OK,1)); overcmd=2;

if(boss==1) {cboss.setVisible(true);

if(cboss.getY()<25) {

????????????? ?? cboss.move(0,3);

????????????? ? }else lr=1;

????????????? if(lr==1)

????????????? {if(cboss.getX()<0)

???????????????????? {

??????????????????????????? right=0;

?????? left=1;? }

?????? else if(cboss.getX()>getWidth()-cboss.getWidth())

{left=0; right=1; }

if(right==0) {cboss.move(3,0); }

else if(left==0) {cboss.move(-3,0);} }

?????? if(((cboss.getX()<=c1.getX()-10)||(cboss.getX()<=c1.getX()+60))&&(jbsz==0))? {bossbullet0.setPosition(cboss.getX()+6,cboss.getY()+40); bossbullet1.setPosition(cboss.getX()+30,cboss.getY()+52);? ???bossbullet2.setPosition(cboss.getX()+54,cboss.getY()+40);? jbsz=1; }if(jbsz==1){

bossbullet0.setVisible(true);

bossbullet1.setVisible(true);

bossbullet2.setVisible(true);

bossbullet0.move(0,5);

bossbullet1.move(0,5);

bossbullet2.move(0,5); }

if(bossbullet2.getY()>getHeight()){jbsz=0;}}

if(bosslife==60){ cboss.setVisible(false);

j1.setVisible(false);j0.setVisible(false);

j2.setVisible(false);bossbullet0.setVisible(false);bossbullet1.setVisible(false);bossbullet2.setVisible(false);jbullet0.setVisible(false);jbullet1.setVisible(false);jbullet2.setVisible(false);

pzbz=1;bossover=1;boss=2;bosslife=65;

pzbzover=1; addCommand(new Command("返回",Command.OK,1));

????????????? }if(bosslife==45)

?????? {bosscolor=1; }

?????? if(slife==65)

?????? {sbosscolor=1;}

?????? if(y1<0){ render(g);

y1=y1+1;planepoup=planepoup-1;

planepo=planepo-1;c1.move(0,-1); }

if (y1>=0 ) { if(boss==0)

{jbsz=0; boss=1; planepoup=0;

planepo=getHeight();cboss.setPosition(80,-60); }renderboss(g); } if(bosscolor==0)

cboss.setFrame(0); else cboss.setFrame(1);

if(sbosscolor==0) sboss.setFrame(0);

else sboss.setFrame(1); if(cloundno==0)

{? cloud[0].setPosition(25,planepoup-(65));

?????? cloud[1].setPosition(80,planepoup-(140);

????? cloud[2].setPosition(112,planepoup-(90));?????? ????? cloud[3].setPosition(175,planepoup-(200)); cloud[4].setPosition(223,planepoup-(70));

cloundno=1; } cloud[0].move(0,1);

cloud[1].move(0,1); cloud[2].move(0,1);

?????? ?? ??????? cloud[3].move(0,1);

?????? ?? ??????? cloud[4].move(0,1);

?????? ???????? if(cloud[0].getY()>planepo){

cloudposition=aicloud.nextInt()%5;

if(cloudposition<0) {??? ?? ???????????? cloudposition=cloudposition*(-1);

?????? }???? cloudposition=cloudposition+1;

?????? cloud[0].setPosition(cloudposition*40,planepoup);? }if(cloud[1].getY()>planepo){

?????? cloudposition=aicloud.nextInt()%5;

if(cloudposition<0) {??? cloudposition=cloudposition*(-1);

}???? cloudposition=cloudposition+1;

cloud[1].setPosition(cloudposition*30,planepoup); }if(cloud[2].getY()>planepo){

cloudposition=aicloud.nextInt()%5;

if(cloudposition<0) {coudposition=cloudposition*(-1);

}

?????? cloudposition=cloudposition+1;

?????? cloud[2].setPosition(cloudposition*55,planepoup); }if(cloud[3].getY()>planepo){

cloudposition=aicloud.nextInt()%5;

if(cloudposition<0) {cloudposition=cloudposition*(-1);

}cloudposition=cloudposition+1;

cloud[03].setPosition(cloudposition*15,planepoup); } if(cloud[4].getY()>planepo){

cloudposition=aicloud.nextInt()%5;

if(cloudposition<0) {cloudposition=cloudposition*(-1); }

cloudposition=cloudposition+1; cloud[4].setPosition(cloudposition*22,planepoup); }if((y1==-1000)&&(sbz==0))

{sbsz0=0; sbsz1=0; sbsz2=0; sbsz3=0;

drawslife=1; sboss.setVisible(true);

sboss.setPosition(50,planepoup-65);

sbz=1; }if(sbz==1) {sboss.move(0,3);

if(sboss.getY()>planepoup) {sbz=2;

}}

if(sbz==2) {if(((sboss.getY()-50)<c1.getY())&&(smovebz==0)) {???? sbmove=1;//上移}

if(((sboss.getX()+30)<c1.getX())&&(smovebz==0)) {sbmove=4;//右移}

if(((sboss.getY()+50)<c1.getY())&&(smovebz==0)) {sbmove=2; }

if(((sboss.getX()-30)>c1.getX())&&(smovebz==0)) {sbmove=3; }if(sbmove==1)//上移

{ smovebz=1; sboss.move(0,-2); }

if(sbmove==2){smovebz=1; sboss.move(0,2);

}if(sbmove==3) {sboss.move(-2,0); }

if(sbmove==4)

{smovebz=1; sboss.move(2,0);? }

if(sboss.getY()<planepoup) {

?????? sboss.setPosition(sboss.getX(),planepoup); ?? smovebz=0; }

if(sboss.getY()>(planepo-65)){????? ?sboss.setPosition(sboss.getX(),planepo-65);

smovebz=0; }if(sboss.getX()<0) {sboss.setPosition(0,sboss.getY());smovebz=0; }if(sboss.getX()>(getWidth()-65)) {?????? sboss.setPosition(getWidth()-65,sboss.getY());????? smovebz=0; } if(((sboss.getX()+40)<c1.getX())&&(sboss.getY()<c1.getY())&&((sboss.getY()+65)>c1.getY())&&(sbsz0==0))

{bossbullet0.setVisible(true);

bossbullet0.setPosition(sboss.getX()+45,sbos.

getY()+35); sbsz0=1;

?????? ???????? }

?????? ???????? if(sbsz0==1)

{bossbullet0.move(3,0);???? if(bossbullet0.getX()>getWidth()) {

sbsz0=0; } }if((sboss.getX()>c1.getX())&&((sboss.getY()+65)>c1.getY())&&(sbsz1==0))

{bossbullet1.setPosition(sboss.getX()+10,sboss.getY()+35); sbsz1=1; }

if(sbsz1==1) {????? bossbullet1.move(-3,0);

if(bossbullet1.getX()<0) {

bossbullet1.setVisible(false);?????? sbsz1=0;}}?? ? if((sboss.getX()<c1.getX())&&((sboss.getX()+50)>(c1.getX()))&&(sboss.getY()>c1.getY())&&(sbsz2==0))? {

bossbullet2.setVisible(true);

bossbullet2.setPosition(sboss.getX()+25,sboss.getY());sbsz2=1; }if(sbsz2==1)

{bossbullet2.move(0,-4); if(bossbullet2.getY()<planepoup)

{bossbullet2.setVisible(false);???? sbsz2=0;

} }if((sboss.getX()<c1.getX())&&((sboss.getX()+50)>(c1.getX()))&&(sboss.getY()<c1.getY())&&(sbsz3==0))

{bossbullet0.setVisible(true); bossbullet1.setVisible(true); bossbullet2.setVisible(true);

bossbullet2.setPosition(sboss.getX()+10,sboss.getY()+25); bossbullet1.setPosition(sboss.getX()+30,sboss.getY()+50);

bossbullet0.setPosition(sboss.getX()+55,sboss.getY()+25); sbsz3=1; }

if(sbsz3==1) {bossbullet0.move(0,4);

bossbullet1.move(0,4); bossbullet2.move(0,4);

if(bossbullet0.getY()>planepo)

{

bossbullet0.setVisible(false);

bossbullet1.setVisible(false);

bossbullet2.setVisible(false); sbsz3=0;

}}} if((slife==80)) {

sboss.setImage(img("/pic/explosion.png"),32,32);sboss.setFrame(3);bossbullet0.setVisible(false); bossbullet1.setVisible(false);

bossbullet2.setVisible(false); jiangli=11;

slife=85; drawslife=0;

playerno=playerno+1; sbz=-1;//sbos ??????? sbpzbz=1; }

if((sboss.getY()==getHeight())){

sbz=-1; sbpzbz=1; drawadd=21;

}if(drawadd==21) {sboss.move(0,-3);

if(sboss.getY()<-65) {

sboss.setVisible(false); drawadd=31;

}}if(planert==1) {inputno=1;

pzbz=1; s2=65; c1.setImage(img("/pic/MyPlaneFrames.png"),24,24); c1.setFrame(0); c1.setVisible(true);?

c1.setPosition(getWidth()/2,planepo+48);

planert=2;

}if(planert==2)

{c1.move(0,-2); if(c1.getY()<(planepo-24))

{System.out.println(c1.getY());

System.out.println(planepo-24);inputno=0;

s1=1;

planert=3; }if(c1.getY()>(planepo+24))

{? c1.move(0,-2); }}

et=System.currentTimeMillis();

if((et-st)<rate){try{????? Thread.sleep(rate-(et-st));

}catch(Exception exp){} }

}}public void render(Graphics g)

{ g.setColor(255,255,255);

g.fillRect(0,0,getWidth(),getHeight());

lm.setViewWindow(0,0,getWidth(),getHeight()+10000); lm.paint(g,0,y1); if(over==1)

{ g.drawString("寒在杭州覽橋上空因座機被擊中,壯烈殉國,年",c1.getWidth()-24,60,0); g.drawString("1937年 8月14日,空軍第4大隊少尉飛行員劉思",c1.getWidth()-24,40,0); g.drawString("僅21歲",c1.getWidth()-24,80,0); inputno=1;

}g.drawString("37年8月14日 杭州覽橋 戰果:"+String.valueOf(huokebullet[0].rscore()+huokebullet[3].rscore()+huokebullet[6].rscore()),c1.getWidth()-24,c1.getHeight()-20,0);//

if(drawslife==1) {g.setColor(255,0,0);

g.fillRect(2,22,80,5);g.setColor(255,255,255);

g.fillRect(2,22,slife,5); }

if(playerno==3) {g.drawImage(img("/pic/playerbiaozhi.png"),170,4,0);? g.drawImage(img("/pic/playerbiaozhi.png"),195,4,0); g.drawImage(img("/pic/playerbiaozhi.png"),220,4,0); }if(playerno==2)

{g.drawImage(img("/pic/playerbiaozhi.png"),195,4,0);

g.drawImage(img("/pic/playerbiaozhi.png"),220,4,0); }if(playerno==1) {

g.drawImage(img("/pic/playerbiaozhi.png"),220,4,0); }if(playerno==4)

{g.drawImage(img("/pic/playerbiaozhi.png"),145,4,0);

?????? g.drawImage(img("/pic/playerbiaozhi.png"),170,4,0);

g.drawImage(img("/pic/playerbiaozhi.png"),195,4,0);

?? g.drawImage(img("/pic/playerbiaozhi.png"),220,4,0);g.setColor(255,0,0); }

if(jiangli==11){g.setColor(255,0,0);

g.drawString("援軍到達",100,150,0);

if(sboss.getY()>planepo) {jiangli=20;

?????? }} if(s1==1) {g.setColor(255,255,255);

g.fillRect(170,22,65,5); g.setColor(255,0,0);

g.fillRect(170,22,s2,5); g.drawString("無敵時間",124,18,0); drawadd=1; s2=s2-1;?????

if(s2==0) {pzbz=0; s1=2; }}

flushGraphics();}public void renderboss(Graphics g) {lm.setViewWindow(0,0,getWidth(),getHeight());?????? lm.paint(g,0,0); if(over==1)

{//c1.getHeight(),0); g.drawString("1937年 8月14日,空軍第4大隊少尉飛行員劉思",c1.getWidth()-24,40,0);

g.drawString("僅21歲",c1.getWidth()-24,80,0); inputno=1;

} g.setColor(255,0,0); g.fillRect(2,2,60,5);//

g.setColor(255,255,255); g.fillRect(2,2,bosslife,5);//

if((bossover==1)&&(c1.isVisible()))

{g.drawString("此處加覽橋空戰真實歷史戰果",c1.getWidth()-24,40,0); g.drawString("此處加覽橋空戰真實歷史戰果",c1.getWidth()-24,60,0); g.drawString("僅21歲",c1.getWidth()-24,80,0); }

if(playerno==4) {g.drawImage(img("/pic/playerbiaozhi.png"),145,4,0); g.drawImage(img("/pic/playerbiaozhi.png"),170,4,0);? g.drawImage(img("/pic/playerbiaozhi.png"),195,4,0);??????? g.drawImage(img("/pic/playerbiaozhi.png"),220,4,0);} if(playerno==3) {

g.drawImage(img("/pic/playerbiaozhi.png"),170,4,0);

g.drawImage(img("/pic/playerbiaozhi.png"),195,4,0);???? ??????? g.drawImage(img("/pic/playerbiaozhi.png"),220,4,0);}if(playerno==2){???? ?????? g.drawImage(img("/pic/playerbiaozhi.png"),195,4,0);

g.drawImage(img("/pic/playerbiaozhi.png"),220,4,0);

}if(playerno==1){ g.drawImage(img("/pic/playerbiaozhi.png"),220,4,0); }

if(s1==1) {??? g.setColor(255,255,255);

g.fillRect(170,22,65,5);g.setColor(255,0,0);

g.fillRect(170,22,s2,5);g.drawString("無敵",124,18,0);s2=s2-1;if(s2==0)

{pzbz=0;s1=2;}}

flushGraphics();}

public void input(){?? if(inputno==0)

{int keystate=getKeyStates();

if((keystate&UP_PRESSED)!=0){

moveUp();}

if((keystate&DOWN_PRESSED)!=0){

moveDown();}if((keystate&LEFT_PRESSED)!=0){ moveLeft();}

if((keystate&LEFT_PRESSED)==0){

c1.setFrame(0);}if((keystate&RIGHT_PRESSED)!=0){moveRight();}

if((keystate&FIRE_PRESSED)!=0){

for(int i=0;i<=6;i=i+3){

if(huokebullet[i].no==1){??

for( int z=i;z<i+3;z++){ ?????????????????????????

huokebullet[z].initBullets(z);????????????????????? ??????? huokebullet[z].no=huokebullet[z].bulletheight

}huokebullet[i].setfirstposition(c1.getX(),c1.getY(),i,huokebullet,img("/pic/bullet.png"));//

break;}}}}}private void moveDown() {

c1.move(0,4);?????????????

if((c1.getY()+c1.getHeight())>planepo)

{

c1.setPosition(c1.getX(),planepo-c1.getHeight());}}private void moveUp() {c1.move(0,-4);

if(c1.getY()<planepoup){?? c1.setPosition(c1.getX(),planepoup);}}

?????? private void moveRight() {

????????????? ? c1.setFrame(2);

???????????????????? c1.move(3,0);

?????? if(c1.getX()>(getWidth()-c1.getWidth()))

?????? {????????????????????????? c1.setPosition((getWidth()-c1.getWidth())c1.getY());?????????????????

}???? }

private void moveLeft() {

????????????? c1.move(-3,0);

????????????? c1.setFrame(1);???

????????????? if(c1.getX()<=0)

?????? ??? {

?????? ??? ????? c1.setPosition(0,c1.getY());

?????? ??? }

?????? }

?????? public void start()

?????? {

????????????? Thread t=new Thread(this);

????????????? t.start();

?????? }

?????? public void commandAction(Command c,Displayable d)

?????? {

????????????? if(c.getLabel()=="暫停")

????????????? {?? conti=false;

????????????? ?removeCommand(c);

????????????? ?addCommand(new Command("繼續",Command.OK,1));

????????????? }

????????????? if(c.getLabel()=="繼續")

????????????? {?? conti=true;

????????????? start();//

????????????? ?removeCommand(c);

????????????? ?addCommand(new Command("暫停",Command.OK,2));

????????????? }

if(c.getLabel()=="返回")

????????????? {?? conti=false;

midlet.menuscreensecond();

?????? }

?????? }?

}

?

?

?

?

?

????????????????????

?????? ?? ?????

??????


附錄二? 操作說明

在電腦中使用模擬器的步驟如下:

1?? 使用WTK的新建項目功能建立一個新項目,要求與Eclipse工作區下的項目名稱MIDlet類名相同。

2?? 新建項目后,將Eclipse工作區下的.java文件拷入src文件夾,將.class文件拷入class文件夾(需要新建),將pic文件夾拷入res文件夾,點擊生成,如一切正常。

3?? 選擇項目-包-生成包。

4?? 生成的jar和jad文件存儲在lzhhdm/bin目錄下。

?? 5??? 運行Motorola SDK v4.2 for J2ME,使用MOTOA760手機模擬器進行測試。點擊Lanuc按紐,即可以進行游戲了。

電腦鍵盤的方向鍵上、下、左、右可以控制玩家飛機的運動,回車可以發射子彈。

可以將鼠標移動到相應的按紐處單擊,以測試相應的按紐。

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

附錄三? 英文文獻及其譯文

What's New in the J2ME Wireless Toolkit 2.2

by Jonathan Knudsen
June 2004

The award-winning J2ME Wireless Toolkit has become the de facto standard toolkit for developing applications for Java 2, Micro Edition (J2ME). Since its debut in 2000, the toolkit has evolved to keep pace with the rapidly changing face of mobile Java technology. Don't be misled by the small change in version number from 2.1. The new toolkit supports new optional APIs specified through the Java Community Process (JCP) in four vital areas: 3D graphics, multimedia messaging, Bluetooth networking, and data management. In this article I'll describe these new APIs and show you how they're implemented in the toolkit.

Before I do, take a moment to admire the updated DefaultColorPhone emulator skin. Since version 2.1, this skin has gotten a larger screen (320 x 240, or QVGA) and far more colors (4096 instead of 256).

Mobile 3D Graphics

JSR 184, the Mobile 3D Graphics API for J2ME (M3G), provides three-dimensional graphics functionality in a compact package that's appropriate for devices that support the most widely adopted J2ME software stack, the Connected, Limited Device Configuration (CLDC) and the Mobile Information Device Profile (MIDP). The API provides two APIs for displaying 3D content. The immediate mode API makes it possible for applications to create and manipulate 3D elements directly. On top of this layer is a scene graph API, also called retained mode, that makes it possible to load and display entire 3D scenes you've designed ahead of time. Applications may use whichever API is most appropriate, or a combination of retained mode and immediate mode. The JSR 184 specification also defines a file format for scene graphs, .m3g.

The toolkit's emulator fully supports JSR 184 and you'll find several MIDlets that show off the API's capabilities in the Demo3D project.

Life3D demonstrates the use of immediate mode:

PogoRoo is an interactive demonstration that features a bouncing kangaroo:

Finally, retainedmode shows how to load and render a scene graph file:

Multimedia Messaging

The J2ME Wireless Toolkit has long supported JSR 120, version 1.1 of the Wireless Messaging API (WMA); the new release supports WMA 2.0 (JSR 205), which expands WMA's capabilities to include Multimedia Messaging.

In the toolkit, messaging takes place in a simulated environment. If you run the emulator multiple times, applications on the emulators can communicate with each other, and you can use the toolkit's handy WMA Console utility to exchange messages with the applications in the same environment. Messages may conform to any of three standard protocols: Short Message Service (SMS), Cell Broadcast Service (CBS), or - new in version 2.2 of the toolkit - Multimedia Messaging Service (MMS).

You can address MMS messages and add any collection of files to the message.

Furthermore, the network monitor now displays MMS messages that are sent or received by the emulator.

Bluetooth and OBEX

The J2ME Wireless Toolkit emulator supports JSR 82, the Java APIs for Bluetooth, which includes two independent APIs:

The Bluetooth API provides an interface to Bluetooth wireless

networking, including device discovery and data exchange.

The OBEX API allows applications to use the Object Exchange (OBEX)

protocol over Bluetooth or other communication channels.

?

The toolkit allows you to develop and test applications that use Bluetooth technology even if you don't have any actual Bluetooth hardware. The toolkit simulates a Bluetooth environment, in which you can run multiple emulator instances that can discover each other and exchange data using the Bluetooth API.

?

An example application, BluetoothDemo, shows how to transfer imagesfrom? one emulator to another.

?

The J2ME Wireless Toolkit implements OBEX transfer over simulated Bluetooth and infrared connections. The simulated infrared connection

follows the IrDA standard defined by the Infrared Data Association. The? toolkit simulates infrared transfers between multiple running emulators.

?????

You can configure the Bluetooth and OBEX environment using the Bluetooth/OBEX tab in the toolkit preferences. This controls such

parameters as how long the emulator attempts to discover other devices in the simulated Bluetooth environment and the maximum packet size. See the toolkit's User's Guide for more details.

?????

Local Files and Personal Information

The J2ME Wireless Toolkit supports JSR 75, the PDA Optional Packages for

the J2ME Platform, which also includes two independent APIs:

?

The FileConnection API gives MIDlets access to a local file system on the device.

The Personal Information Management (PIM) optional package includes APIs for manipulating contact lists, calendars, and to-do lists.

?????

A real device may have a local file system which can be accessed using the FileConnection API. In the J2ME Wireless Toolkit emulator, a simulated file system is maintained as a directory on your hard disk.

?????

The files your application can access using FileConnection are stored in subdirectories of <toolkit>/appdb/<skin>/filesystem., where <toolkit> is the installation directory of the J2ME Wireless Toolkit and <skin> is the name of the emulator skin. For example, the DefaultColorPhone emulator skin comes with a root directory installed called root1, which contains a file called Readme. The file's full path is <toolkit>/appdb/DefaultColorPhone/filesystem/root1/Readme.

?????

You can manage the root directories that are available by choosing MIDlet > External events from the emulator window's menu. You'll see a small utility window for adding and removing roots. These actions will also generate events for a registered listener object.

In a real device, personal information might be stored in a proprietary

format in memory. The emulator uses a directory on your hard disk to

contain this information, accessible using the PIM API. All information is stored in <toolkit>/appdb/pim. Lists are stored in subdirectories of the contacts, events, and todo directories. For example, a contact list called Contacts is contained in <toolkit>/ appdb/ pim/ contacts/ Contacts.

????

Inside the list directory, items are stored in standard formats specified by the Internet Mail Consortium. Contacts are stored in vCard format, while calendar and to-do items are both stored in vCalendar format.

Summary

The J2ME Wireless Toolkit 2.2 is much more than an incremental update of an excellent tool. It includes support for four exciting new

specifications that together define six new APIs. As the world of wireless Java technology rapidly evolves, the J2ME Wireless Toolkit keeps pace and contains all the tools you need for

About the Author: Jonathan Knudsen [e-mail] [home page] is the author of several books, including Wireless Java (second edition), The Unofficial Guide to LEGO MINDSTORMS Robots, Learning Java (second edition), and Java 2D Graphics. Jonathan has written extensively about Java and Lego robots, including articles for JavaWorld, EXE, NZZ Folio, and the O'Reilly Network. Jonathan holds a degree in mechanical engineering from Princeton University.

譯文

J2ME Wireless Toolkit 2.2 新改進

作者:Jonathan Knudsen
2004 年 6 月

屢獲殊榮的 J2ME Wireless Toolkit 已經成為 J2ME 開發應用程序的事實標準工具包。自從 2000 年初次亮相以來,該工具包一直在發展以趕上移動 Java 技術外觀上快速改變的步伐。不要被從 2.1 版本以來的小改變所誤導。新的工具包在四個重要的領域支持 Java Community Process (JCP) 所指定的新的可選 API:3D 圖形、多媒體通信、藍牙連網(Bluetooth networking)和數據管理。本文將描述這些新的 API 并且向您展示如何在工具包中實現他們。

在這之前,讓我們贊美一下更新后的 DefaultColorPhone 模擬器皮膚,自從 2.1 版本以來,該皮膚已有了一個更大的屏幕(320 x 240, 或 QVGA)和更多的顏色(4096 色而不是 256 色)。

移動 3D 圖形

JSR 184,? 即 Mobile 3D 圖形 API for J2ME (M3G) 在一個集成軟件包中提供了三維圖形功能,適用于支持最為廣泛采用的 J2ME 軟件棧、有限連接設備配置(CLDC)和移動信息設備描述(MIDP)的設備。API 為顯示 3D 內容提供了兩種 API。立即模式 API 使應用程序能夠直接創建和操縱 3D 元素。這一層之上是一個場景圖 API,也稱為保留模式,能夠提早加載并顯示已設計的整個 3D 場景。應用程序可以采用最適合的 API,或保留模式與立即模式的組合。JSR 184 規范還為場景圖定義了一種文件格式-.m3g。

該工具包的模擬器全面支持 JSR 184,并且有幾個 MIDlet 展示了 API 在 Demo3D 項目中的功能。Life3D 演示了立即模式的使用。PogoRoo 是一個的交互的演示,特點是顯示一只跳躍的袋鼠:

多媒體通信

J2ME Wireless Toolkit 長期支持 JSR 120、Wireless Messaging API(WMA)的1.1版本;新版本支持 WMA 2.0(JSR 205),其把 WMA 的功能擴展到包括多媒體通信。

在工具包中,通信發生于模擬的環境中。如果多次運行模擬器,模擬器上的應用程序能夠相互通信,并且可以使用工具包方便的 WMA Console 實用程序在同一環境中與應用程序交換消息。通信可以遵照以下三種標準協議之一:短消息服務(Short Message Service,SMS)、蜂窩廣播服務(Cell Broadcast Service,CBS)或工具包 2.2 版本中的新協議-多媒體通信服務(MMS)。

您可以標記 MMS 消息,并向消息添加任何文件集合。

而且,現在網絡監視器能夠顯示模擬器發送或接收的 MMS 消息。

藍牙和 OBEX

J2ME Wireless Toolkit 模擬器支持 JSR 82,即 Java API for Bluetooth,包括兩個獨立的 API:

藍牙 API 為藍牙無線網絡提供了接口,包括設備恢復和數據交換。

OBEX API 允許應用程序在藍牙或其他通信信道上使用對象交換(Object Exchange,OBEX)協議。

該工具包允許在即使沒有實際藍牙硬件的情況下,也可以開發和測試采用藍牙技術的應用程序。該工具包模擬藍牙環境,您可以在該環境中運行可相互發現的多個模擬器實例和使用藍牙 API 交換數據。

應用程序實例 BluetoothDemo 顯示了如何從一個模擬器將圖像傳輸到另一個模擬器。

J2ME Wireless Toolkit 通過模擬的藍牙和紅外連接上實現 OBEX 傳輸。模擬的紅外連接遵循 Infrared Data Association 定義的 IrDA 標準。工具包在多個運行的模擬器之間模擬紅外傳輸。

您可以使用工具包參數中的 Bluetooth/OBEX 標簽來配置藍牙和 OBEX 環境。其控制了諸如模擬器在模擬的藍牙環境中試圖用多長時間去發現其他設備,以及最大數據包大小等參數。請參見工具包的用戶指南獲取更多的詳細信息。

本地文件和個人信息

J2ME Wireless Toolkit 支持 JSR 75,即 PDA Optional Packages for the J2ME Platform,它也包括兩個獨立的 API:

FileConnection API 提供了 MIDlet 對設備上本地文件系統的訪問。

Personal Information Management (PIM) 可選軟件包包括用于操縱聯系人列表、日程安排和計劃列表的 API。

一臺真實的設備可能有一個能通過使用 FileConnection API 訪問的本地文件系統。在 J2ME Wireless Toolkit 模擬器中,模擬的文件系統作為硬盤上的一個目錄存在。

應用程序使用 FileConnection 可訪問的文件都存放在子目錄 <toolkit>/appdb/<skin>/filesystem.中,此處 <toolkit> 是 J2ME Wireless Toolkit 的安裝目錄,<skin> 是模擬器皮膚的名稱。例如,DefaultColorPhone 模擬器皮膚隨安裝根目錄 root1 而產生,包含一個 Readme 文件。文件的完整路徑為<toolkit>/appdb/DefaultColorPhone/filesystem/root1/Readme。

您可以從模擬器窗口的菜單種選擇 MIDlet > External events 來管理可用的根目錄。您將看到一個添加和刪除根目錄的小的實用程序窗口。這些操作也將為 registered listener 對象生成事件。

在真實的設備上,個人信息可能以專有格式存儲在內存中。模擬器使用硬盤中的一個目錄來存放這些信息,可使用 PIM API 來訪問。所有的信息存儲在 <toolkit>/appdb/pim 目錄中。列表存儲在聯系人、事件和計劃目錄的子目錄中。例如,聯系人列表 Contacts 位于 <toolkit>/appdb/pim/contacts/Contacts 目錄中。

在列表目錄內,列表項以 Internet Mail Consortium 指定的標準格式存儲。聯系人以 vCard 格式存儲,日歷和計劃項都以 vCalendar 格式存儲。

結束語

J2ME Wireless Toolkit 2.2 不僅僅是一個出色工具的增量更新。它包括了對令人激動的四項新規范的支持,同時定義了六種新的 API。隨著無線 Java 技術世界的快速發展,J2ME Wireless Toolkit 緊緊跟隨發展的步伐并且包含您所需的全部工具。

關于作者

Jonathan Knudsen[電子郵件] [主頁],有多本著作,包括:Wireless Java (second edition)、The Unofficial Guide to LEGO MINDSTORMS Robots、Learning Java (second edition) 和 Java 2D Graphics 。Jonathan 在 Java 和 Lego 機器人領域編寫了大量的文章,包括 JavaWorld、 EXE、 NZZ Folio 和 the O'Reilly Network 方面的文章。作者擁有普林斯頓大學的機械工程學位。


?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

目? 錄

1 緒論

1.1 手機軟件現狀

1.2 J2ME介紹

1.3 手機游戲應具有的特征

1.4 本游戲背景介紹

1.5 本章小結

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

2.1 開發環境

2.2 Java語言特點

2.3 關于ECLIPSE

2.4 關于Wireless Tool Kit

2.5 Java Appication Manager

2.6 本章小結:

3 程序結構、思想和相關技術

3.1 本程序需要解決的主要技術問題

3.2 程序流程

3.3 Canvas類

3.4 Graphics類

3.5 MIDP1.0技術下的繪制背景技術

3.6 MIDP2.0新增的GameCanvas包

3.7 PNG圖片格式

3.8 玩家飛機的控制方式和敵人方的智能運行

3.9 子彈的運行和控制

3.10 內存的優化

3.11 內存檢測器

3.12 關于混淆器

3.13 本章小結

4 程序分析和具體實現

4.1 游戲進入前的選擇

4.2 mybullets類

4.3 游戲邏輯及gameScreen類

4.3.1 gameScreen類所實現的功能

4.3.2 地圖的創建

4.3.3地圖的移動

4.3.4 gameScreen類的構造函數

4.3.5 關于commandAction()方法

4.3.6 Sprite類對象的碰撞檢測及相關屬性

4.3.7 玩家4次游戲機會的實現方法

4.3.8 input()

4.3.9 render()renderboss()

4.4 游戲中的獎勵及相關飛機的行為

4.5 普通敵人相關屬性

4.6 白云的實現原理

4.7 關尾BOSS及相關屬性

4.8本章小結

5測試

5.1 打包測試的過程

5.2 發現的BUG及解決情況

5.3 未完善的功能

6總結

6.1 本程序的總結和展望

6.2 感想

???

參考文獻

附錄一代碼

附錄二操作說明

附錄三英文文獻及其譯文

?

摘? 要

這款游戲的名字叫《覽橋風光》。J2ME(Java 2 Micro Edition) 是近年來隨著各種不同設備,尤其是移動通信設備的飛速發展而誕生的一項新的開發技術。它定位在消費性電子產品的應用上,對設備的智能化、多樣化,提供了革命性的解決方案,并因其“Write Once, run anywhere”的Java特性而提高開發的效率。

隨著手機的日益普及、Java功能在移動設備上的實現,Java應用程序產生的手機增值服務逐漸體現出其影響力,對豐富人們的生活內容、提供快捷的資訊起著不可忽視的作用。本論文著眼于J2ME技術的應用,開發一款可商用的手機游戲程序。本程序將老少皆宜的經典作品移植到手機上來,為更流行的硬件平臺提供應用軟件。

本論文介紹了J2ME的相關技術及本程序的結構分析和具體功能的實現。

總結

以上是生活随笔為你收集整理的手机游戏毕业设计论文的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

国产视频精品视频 | 欧美一区二区三区特黄 | 久久福利剧场 | 日韩字幕在线观看 | 丁香婷婷激情 | 日韩高清免费观看 | 人人爱爱 | 国产一二区视频 | 91久久奴性调教 | 国产福利精品一区二区 | 日韩在线短视频 | 91麻豆视频 | 伊人日日干 | 成人资源在线观看 | 亚洲婷婷网 | 日韩在线观看一区 | 色久综合 | 亚洲91精品在线观看 | 国产精品v欧美精品 | 人人玩人人添人人 | 精品一区二区久久久久久久网站 | 日日弄天天弄美女bbbb | 国产一区精品在线 | 粉嫩av一区二区三区四区 | 日韩精品一区二区三区免费观看视频 | 中文国产字幕在线观看 | 91成人亚洲| 亚洲精品动漫在线 | 久久精品亚洲综合专区 | 日日夜夜亚洲 | 三级黄色大片在线观看 | 亚洲黄色三级 | 亚洲精品玖玖玖av在线看 | 超黄视频网站 | 国产高清在线精品 | 国产精品久久久久久久久久久久午夜片 | 免费av 在线 | 99精品视频免费观看视频 | 夜夜高潮夜夜爽国产伦精品 | 69av视频在线观看 | 在线观看免费av片 | www.色五月 | 久久久久国产精品一区 | 欧美一级爽 | 国色天香在线观看 | 在线中文字幕电影 | 521色香蕉网站在线观看 | 99久久精品免费一区 | 国产精品女同一区二区三区久久夜 | 成人久久电影 | 亚洲精品乱码白浆高清久久久久久 | 免费观看的av网站 | 国产日韩精品在线观看 | 国内精品久久久久影院日本资源 | 五月丁香 | 色综合久久五月天 | 精品国产不卡 | 日韩理论片 | 九九免费在线视频 | 人九九精品 | 成人作爱视频 | 欧美91精品 | 精品国产片 | 国产一区二区手机在线观看 | 午夜狠狠操| 国产成人精品在线 | 久久久国产日韩 | 免费看片成年人 | 丁香六月婷婷激情 | 69视频在线 | 欧美va日韩va| 精品一区二三区 | 欧美极品少妇xbxb性爽爽视频 | 狠狠干天天射 | 久久久久久久久久免费视频 | 亚洲精品免费观看 | 久久久久99精品国产片 | 亚洲天堂在线观看完整版 | 骄小bbw搡bbbb揉bbbb | 日日夜夜网 | 国产精品久久伊人 | 99国产视频 | 奇米影视8888在线观看大全免费 | 日日色综合| 国产精品一区二 | 成人av免费| 毛片美女网站 | 婷婷六月色| 亚洲精品麻豆视频 | 黄色大全免费观看 | 中文字幕在线观看免费观看 | 91麻豆精品一区二区三区 | 91精品国产自产在线观看永久 | 亚洲一级在线观看 | 久久久久久久久久伊人 | 中文字幕在线观看三区 | 黄色av电影在线 | 欧美aa级 | 国产不卡一 | 亚洲毛片视频 | 一色av | 人人爽人人乐 | 97超级碰碰 | 91精品国产福利在线观看 | 欧美精品成人在线 | 日韩视频一 | 不卡的av在线播放 | 久久国产亚洲视频 | 亚洲成av人片在线观看无 | 欧美了一区在线观看 | 最新黄色av网址 | 一级黄色免费网站 | 99久久久成人国产精品 | 久久一级电影 | 看片网站黄 | 国产视频每日更新 | 国产精品一区二区免费视频 | 日韩视频a | 婷婷在线色 | 成人免费在线观看入口 | 一级片视频在线 | 黄色软件视频网站 | 黄色av一区二区三区 | 视频一区二区在线 | 天天综合天天做天天综合 | 中文av在线免费观看 | 激情综合五月网 | 日韩精选在线 | 成人资源站| 黄色电影在线免费观看 | 97色在线观看免费视频 | 视频在线一区二区三区 | 亚洲日日日 | 国产亚洲va综合人人澡精品 | 日韩精品欧美精品 | a午夜电影| 日日爱影视 | av福利在线播放 | 综合视频在线 | 精品国产伦一区二区三区 | 亚洲成人av在线电影 | 久操综合| 欧美性久久久 | 亚洲理论视频 | 久久综合久久综合久久 | 亚洲一级特黄 | 免费亚洲视频在线观看 | 久久精品日本啪啪涩涩 | 国产精品videossex国产高清 | 久久久久久网址 | 狠狠gao | 国产99久久精品一区二区永久免费 | 丝袜+亚洲+另类+欧美+变态 | 久久精品国产成人精品 | 中文字幕在线播放第一页 | 久久99婷婷 | 黄色网址国产 | 久久久蜜桃 | 干干干操操操 | 国产五月| 欧美性大战 | 欧美日韩在线视频免费 | 国产精品久久久久久久电影 | 中文字幕2021 | 午夜av激情 | 91精品视屏 | 国产视频第二页 | 日本系列中文字幕 | 久久九九影视网 | 天天爽夜夜爽精品视频婷婷 | 久久精久久精 | 少妇bbw撒尿 | 一区二区视频在线看 | 99精品国产福利在线观看免费 | 91大神电影 | 色视频成人在线观看免 | 久久一线 | 91久久一区二区 | 久久九九免费 | 四虎国产精 | 91精品国产自产老师啪 | 色香蕉在线视频 | 操操综合 | 亚洲成人家庭影院 | 亚洲精品免费在线观看 | 国产成人av | 在线免费看黄色 | 欧美日韩一区三区 | 西西大胆啪啪 | 91三级视频| 最近乱久中文字幕 | 在线小视频你懂得 | 婷婷电影在线观看 | 国产精品 日韩 欧美 | 五月天婷婷丁香花 | 国产一级片网站 | 亚洲精品免费在线观看视频 | 在线免费成人 | 午夜免费福利视频 | 91视视频在线直接观看在线看网页在线看 | 亚洲春色综合另类校园电影 | 五月黄色 | 国产精品麻豆免费版 | www免费| 在线小视频 | 亚洲一区二区麻豆 | av高清在线观看 | 97在线成人| 亚洲一区美女视频在线观看免费 | 美女久久99 | 国产精品v a免费视频 | 麻豆视频国产在线观看 | 999在线精品| 国产成人精品一区二区三区福利 | 97超碰影视| 日韩欧美区 | 国产毛片在线 | 91免费高清 | 日本中文字幕在线看 | 中国精品少妇 | 精品国产伦一区二区三区观看说明 | 免费一级黄色 | 国产成人精品一区二区三区福利 | 久久婷婷网| 欧美视频在线二区 | 波多野结衣在线视频一区 | 中文字幕国产精品一区二区 | 不卡精品视频 | 精品国产一区二区三区在线 | 四虎视频 | 精品uu | av成人亚洲| 99欧美| 欧美黑吊大战白妞欧美 | 国产精品国产精品 | 日韩高清毛片 | 天天操夜夜操 | 四虎海外影库www4hu | 久草网站| 欧美激情第一页xxx 午夜性福利 | 最新超碰| 久久人人爽人人爽 | 在线 精品 国产 | 97在线观看免费观看 | 丰满少妇高潮在线观看 | 九九久久久 | 中文字幕网址 | 国产在线播放一区二区三区 | 国产视频综合在线 | 91你懂的 | 日韩中文字幕第一页 | 久草| 久久综合九色综合97婷婷女人 | 国产精品久久久久久久久毛片 | www国产亚洲| 91看毛片 | 91高清在线看 | 成人小视频在线免费观看 | 欧美精选一区二区三区 | 欧美一级性视频 | 免费的黄色av | 久久婷婷一区二区三区 | 波多野结衣小视频 | 亚洲六月丁香色婷婷综合久久 | a在线免费观看视频 | 亚洲国产伊人 | 久久综合国产伦精品免费 | 曰韩精品 | 天天做天天爱夜夜爽 | 久国产在线播放 | 成人黄色免费在线观看 | www.五月激情.com | 亚洲不卡av一区二区三区 | 狠狠色丁香婷婷综合基地 | 成人在线视频免费看 | 在线观看日韩精品 | 亚洲国产资源 | 亚洲精品男人天堂 | 免费在线观看中文字幕 | 91在线播放综合 | 精品在线视频一区二区三区 | 最新国产精品久久精品 | 久久99精品国产麻豆婷婷 | 国产亚洲字幕 | 免费网站在线观看成人 | 久久国产免费看 | 天天操天操 | 欧美日韩国产精品一区二区 | 久久天天躁狠狠躁亚洲综合公司 | 午夜影院日本 | 亚洲精色 | 五月婷婷在线观看视频 | 亚洲精品国产精品国 | 九七人人干 | 亚洲国产三级在线观看 | 久久视频这里有久久精品视频11 | 亚洲热视频 | 久久免费观看视频 | 久久久wwww| 正在播放国产一区二区 | 国产尤物在线观看 | 免费看污在线观看 | 91精品夜夜 | 日韩国产欧美在线视频 | 欧亚日韩精品一区二区在线 | av播放在线 | 天天干天天操天天爱 | 天天爱天天射 | 日韩a在线 | 香蕉视频网站在线观看 | 亚洲成av人片在线观看香蕉 | 中文字幕文字幕一区二区 | 国产福利午夜 | 午夜天天操 | 中文字幕成人在线观看 | 欧美天堂影院 | 黄污网站在线观看 | 91亚洲精品久久久蜜桃借种 | 久久99在线观看 | av免费片 | 精品一区 精品二区 | 十八岁以下禁止观看的1000个网站 | 激情五月开心 | 日韩国产精品一区 | 精品久久精品久久 | 亚洲国产999| 一本一道久久a久久精品蜜桃 | 99精品国产99久久久久久97 | 91麻豆看国产在线紧急地址 | 特级黄色电影 | 国产精品久久99精品毛片三a | 99久久精品国产系列 | 国产99久久久国产精品免费看 | 97电影在线观看 | 国产网红在线 | 精品国产乱码久久 | www.国产在线视频 | 亚洲成av人电影 | 久久久久麻豆v国产 | 色综合久久88色综合天天人守婷 | 久久久综合电影 | 午夜视频在线观看一区二区三区 | 国产99在线免费 | 中文字幕视频网站 | 中文字幕av最新更新 | 二区三区av| 91人人视频在线观看 | 午夜av一区 | 波多野结衣精品 | 国产中文伊人 | 久久人人爽人人人人片 | 91女子私密保健养生少妇 | 久久av不卡 | 激情丁香综合五月 | 久久99热精品这里久久精品 | 久草av在线播放 | 亚洲精品中文字幕视频 | 国产啊v在线观看 | 久久久久久欧美二区电影网 | 亚洲欧美日本国产 | 操操操影院 | 久久伊人婷婷 | 成年人网站免费观看 | 午夜精品久久久久久久99无限制 | 精品国产一区二区三区噜噜噜 | av午夜电影 | 中文在线√天堂 | 日日夜夜免费精品视频 | 99久久久久成人国产免费 | 日本午夜免费福利视频 | 久久精品香蕉 | 丁香激情婷婷 | 欧美日韩一区二区三区视频 | 久久综合五月天 | 久久免费视频网站 | 日本公妇在线观看高清 | 黄色小网站免费看 | 黄污污网站 | 久久国产精品一二三区 | 久久精品站 | 久久久男人的天堂 | 69国产精品视频免费观看 | 国产精品99蜜臀久久不卡二区 | 日韩字幕| 一级黄色片毛片 | 久久精彩视频 | 欧美色图亚洲图片 | 成人av av在线 | 亚洲动漫在线观看 | 99精品乱码国产在线观看 | 日韩免费电影一区二区 | 国产不卡在线观看视频 | www.亚洲精品| 国产精品永久免费观看 | 成人动漫一区二区 | av天天在线观看 | 欧美成人黄色 | 国产免费大片 | 国产午夜精品一区 | 欧美国产精品一区二区 | 500部大龄熟乱视频 欧美日本三级 | 国产精品v欧美精品 | 婷婷干五月| 香蕉久久国产 | 欧美日韩精品在线视频 | 日本中文字幕网 | 女女av在线 | 欧美日韩网站 | 中文字幕乱视频 | 九九视频精品在线 | 麻豆系列在线观看 | 欧美一级在线 | 国产精品99久久久久 | 国产精品99久久久久久宅男 | 国产精品久久久久av | 最新日韩视频在线观看 | 毛片a级片 | 精品二区久久 | 成人在线视频免费观看 | 天天射天天干 | 日韩av电影一区 | www.狠狠色 | 五月天久久综合 | 国产91电影在线观看 | 久久久精品 一区二区三区 国产99视频在线观看 | 成人精品在线 | 国产手机在线观看视频 | 一本一本久久a久久 | 亚洲 欧洲av | 97精品超碰一区二区三区 | 91久久丝袜国产露脸动漫 | 亚洲欧美日韩一二三区 | 国产视频一区二区三区在线 | 成人国产精品久久久久久亚洲 | 蜜臀aⅴ国产精品久久久国产 | 手机看片国产日韩 | www.干| 狠狠网站 | 最新超碰在线 | 成年人免费电影在线观看 | 美女久久久久久久久久 | 91麻豆产精品久久久久久 | 色偷偷中文字幕 | 国产精品一区二区三区观看 | 国产成人精品综合久久久久99 | 天天做天天爱天天爽综合网 | 亚洲视频一级 | 丁香五月亚洲综合在线 | 亚州精品成人 | 69国产在线观看 | 激情中文字幕 | 国产精品久久久久久久久久了 | 精品999久久久 | 在线观看国产区 | 香蕉免费在线 | 亚洲v欧美v国产v在线观看 | 97超碰人人澡人人爱 | 精品久久1 | 欧美一级性视频 | 久久精品国产精品亚洲 | 中文字幕在线影院 | 国产精品11 | 人人插人人舔 | 日韩在线不卡 | 四虎最新域名 | 天天操狠狠操网站 | 色婷婷狠狠 | 久久视频在线免费观看 | 99精品国产成人一区二区 | 日韩在线免费观看视频 | 天天操夜夜想 | 天天干天天爽 | 精品美女视频 | 天天爽夜夜爽人人爽曰av | 96香蕉视频 | 免费a级观看| 欧美精品亚洲精品日韩精品 | 看毛片的网址 | 国产一级h | 亚洲黄色免费网站 | 黄色视屏免费在线观看 | www.久久精品视频 | 久久尤物电影视频在线观看 | 十八岁免进欧美 | 亚洲性少妇性猛交wwww乱大交 | 在线观看日韩国产 | 少妇视频在线播放 | 欧美色伊人 | 日韩av高潮| 亚洲 欧美 另类人妖 | a级一a一级在线观看 | 久久露脸国产精品 | 色婷婷国产精品 | 蜜桃麻豆www久久囤产精品 | 91福利视频免费观看 | 免费看的黄网站软件 | 17婷婷久久www | 九色免费视频 | 九九欧美| 91桃色在线观看视频 | 天天操天天爽天天干 | 免费观看黄色av | 欧美贵妇性狂欢 | 国产一级精品绿帽视频 | 国产精品99久久久久人中文网介绍 | 综合色亚洲 | 国产成人精品综合 | 天天色天天上天天操 | 日韩午夜在线观看 | 中文字幕一区二 | 在线观看蜜桃视频 | 美女久久视频 | 中文资源在线播放 | 国产精品一区在线观看 | 午夜视频黄 | 国产精品免费一区二区 | 996久久国产精品线观看 | 91免费的视频在线播放 | 亚洲精品tv久久久久久久久久 | 久久电影日韩 | 色婷婷精品大在线视频 | 国产另类av | 一本色道久久综合亚洲二区三区 | 91在线蜜桃臀 | 91成人免费电影 | 99亚洲精品在线 | 91高清免费在线观看 | 日本xxxx.com | 国产五月色婷婷六月丁香视频 | 99久久99视频只有精品 | 国产高清av在线播放 | 日韩av在线不卡 | 国产亚洲免费观看 | 欧美激情视频在线观看免费 | 91视频免费观看 | 三级av在线播放 | 又湿又紧又大又爽a视频国产 | 天天草天天干天天射 | 国产在线综合视频 | 亚洲另类在线视频 | 一区二区三区影院 | 中文字幕免费观看视频 | 久久99热这里只有精品 | 激情婷婷亚洲 | 国产高清久久久久 | 美女网站色免费 | 天天做天天看 | 免费91麻豆精品国产自产在线观看 | 91九色最新地址 | 久久久久久久久久久久久国产精品 | 久久手机在线视频 | 349k.cc看片app| 黄网站色成年免费观看 | 久久久久一区二区三区四区 | 中文字幕精品一区二区精品 | 国产精品第一视频 | 热久久国产精品 | 永久免费毛片在线观看 | 国产精品一区二区三区久久 | 国产精品你懂的在线观看 | 国产午夜三级一二三区 | 亚洲免费小视频 | 免费av小说 | 欧美一区二区免费在线观看 | 五月激情av| 干狠狠| 精品国产视频在线观看 | 色射爱| 成年人在线视频观看 | 成人免费网站在线观看 | 在线观看91久久久久久 | 日韩欧美一区二区三区视频 | 亚洲电影影音先锋 | 99视频在线看 | 精品久久久影院 | 黄色毛片电影 | 国产视频综合在线 | 玖草影院 | 国产日韩av在线 | 日日爽夜夜爽 | 欧美日韩国产在线精品 | 狠狠综合久久 | 亚洲欧美成人网 | 在线日本看片免费人成视久网 | 91系列在线 | 久草在线久 | 在线看国产视频 | 中文字幕制服丝袜av久久 | 日韩中午字幕 | 91福利影院在线观看 | 九九热视频在线播放 | 国内精品毛片 | av高清在线观看 | 亚洲网站在线 | 在线观看视频一区二区三区 | 成人免费色 | 久久国产精品区 | 午夜精品成人一区二区三区 | 六月丁香在线视频 | 婷婷射五月 | 久久久久久精 | 国产精品亚洲成人 | 成人h电影在线观看 | 亚洲一区欧美激情 | 2018亚洲男人天堂 | 国产99区 | 国产精品一区二区免费 | 国产一级一片免费播放放 | 麻豆影视在线免费观看 | 国产伦精品一区二区三区无广告 | 色婷婷视频在线观看 | 综合色综合色 | 高潮毛片无遮挡高清免费 | 精品国内 | 久久国产精品久久国产精品 | 日韩欧美精品在线观看视频 | 国产精品 日韩 | 伊人天堂网| 色网站在线观看 | 色综合久久久久久中文网 | 日韩最新在线视频 | 99国内精品久久久久久久 | 天天天天天天操 | 一级片免费视频 | 色综合久久综合中文综合网 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 97超碰在线免费 | 久草久草视频 | 亚洲一区二区观看 | 成人午夜影院在线观看 | 狠狠做六月爱婷婷综合aⅴ 日本高清免费中文字幕 | 久久午夜影视 | 91精品伦理 | 色综合天天干 | 五月天丁香亚洲 | 日韩在线免费视频 | 中文在线8资源库 | 欧美性受极品xxxx喷水 | 国产97视频在线 | 青青河边草手机免费 | 日本3级在线观看 | 国产成人精品电影久久久 | 国产一区二区三区免费视频 | 国产手机在线播放 | 日韩精品中文字幕在线观看 | 天天综合操 | 国产精品入口a级 | 一区二区电影网 | 麻豆一精品传二传媒短视频 | 亚洲国产一区在线观看 | 99久久精品免费看国产一区二区三区 | 亚洲一区精品二人人爽久久 | 天天综合五月天 | 国产中文字幕免费 | 91福利专区| 香蕉视频免费看 | 久久精品香蕉视频 | av免费电影在线观看 | 五月天激情综合 | 中文字幕乱在线伦视频中文字幕乱码在线 | 97超碰精品 | 久久天堂亚洲 | 亚洲精品乱码久久久久久按摩 | 懂色av一区二区三区蜜臀 | 九草在线观看 | 亚洲在线视频免费 | 亚洲天堂香蕉 | 深爱激情婷婷网 | 中文在线字幕免费观 | 国产精品色在线 | 国产成人精品午夜在线播放 | 精品国产理论 | 99在线视频精品 | 久久久影院一区二区三区 | 国内精品美女在线观看 | 高清av不卡 | 最近中文字幕完整视频高清1 | 黄色www在线观看 | 久久久久久久影视 | 欧美一二三区在线播放 | 这里只有精品视频在线 | 日日夜夜91 | 国产精品九九久久久久久久 | 国产精品久久久久久69 | 国产精品理论视频 | 国产午夜三级一区二区三桃花影视 | 国产精品久久久久久超碰 | 日韩欧美电影在线 | 伊人婷婷 | 超碰在线免费福利 | 亚洲精品一区二区网址 | 成人av.com | 精品人人爽 | 日本韩国精品一区二区在线观看 | 黄色三级网站在线观看 | 成人精品99 | 国产精品一区二区久久 | 五月婷婷丁香在线观看 | 成人在线视频网 | 国产不卡一二三区 | 日韩免费不卡视频 | 91亚洲狠狠婷婷综合久久久 | 97人人模人人爽人人喊网 | av性在线| 久久大香线蕉app | 日韩一级片网址 | 国内精品久久久久影院一蜜桃 | 日韩二区精品 | 99精品视频免费 | 绯色av一区 | 国产第一福利网 | 少妇高潮流白浆在线观看 | 九九九热精品免费视频观看 | 91在线免费观看国产 | www.天天色 | 欧美日韩国产mv | 久草国产在线 | 91麻豆精品国产91久久久久久 | 亚洲高清视频在线观看 | 国产日产精品一区二区三区四区 | 天堂av免费在线 | 国产不卡一 | 黄网站免费大全入口 | 在线观看aaa | 国产精品久久久久久模特 | 日韩激情视频在线 | 97成人精品视频在线观看 | 成人黄色片免费看 | 久久久不卡影院 | 中文字幕一区二区三区精华液 | 日本99热 | 日韩在线一区二区免费 | 日韩欧在线 | 日本精品一区二区三区在线观看 | 黄色网免费| 久草网视频在线观看 | 激情综合亚洲精品 | 免费在线黄色av | 日韩视频免费在线 | 久久福利 | 欧美亚洲精品在线观看 | 91亚洲影院 | 久久视频免费在线观看 | 在线一级片 | 18做爰免费视频网站 | 91高清免费观看 | 成 人 免费 黄 色 视频 | 天天玩天天操天天射 | 色www.| 午夜久久网 | 九月婷婷人人澡人人添人人爽 | 91漂亮少妇露脸在线播放 | 蜜臀久久99静品久久久久久 | 亚洲天堂毛片 | 国产成人免费网站 | 日韩理论在线视频 | 免费的黄色av | 天天干天天操天天操 | 在线a人片免费观看视频 | 久久视频这里只有精品 | 黄色成人av | 狠狠色狠狠色综合日日92 | 天天插伊人 | 美女黄频在线观看 | 天天干,狠狠干 | 欧美一区免费观看 | 免费在线成人av电影 | 国产又粗又猛又爽又黄的视频免费 | 91av视频在线免费观看 | 久草影视在线 | 天天爽夜夜爽人人爽曰av | 久草在线手机观看 | 国产 欧美 日本 | www99精品 | 欧美日韩高清免费 | 亚洲 欧美日韩 国产 中文 | av中文字幕在线看 | 天天操天天干天天爽 | 91亚洲精品久久久久图片蜜桃 | 欧美一级黄色网 | 天天爱天天射天天干天天 | 午夜男人影院 | 国产成人久久av免费高清密臂 | 五月天婷亚洲天综合网精品偷 | 欧美另类xxx | 日日夜夜免费精品视频 | 又黄又爽又色无遮挡免费 | 午夜精品久久久久99热app | 91香蕉视频在线 | 亚洲涩涩色 | 天天干天天干天天射 | 国产视频中文字幕在线观看 | 中文字幕丰满人伦在线 | 日韩综合视频在线观看 | 久久综合加勒比 | 日韩欧美国产免费播放 | av片子在线观看 | 久久综合精品国产一区二区三区 | 国内免费久久久久久久久久久 | 久草综合在线观看 | 国产视频一二区 | 日韩精品大片 | 中文字幕888| 欧美污污视频 | 久草精品国产 | 96精品高清视频在线观看软件特色 | 国产麻豆果冻传媒在线观看 | 在线观av| 国产99re| 亚洲欧洲精品一区二区精品久久久 | 国产在线观看h | 中文字幕最新精品 | 嫩模bbw搡bbbb搡bbbb | 精品国产成人av在线免 | 欧美一区二视频在线免费观看 | 五月天婷亚洲天综合网鲁鲁鲁 | 国产一区二区三区免费视频 | 国产精品久久久久久久久久久免费看 | 少妇bbr搡bbb搡bbb | 91香蕉国产 | www99精品| 高清精品在线 | 99久久99久久综合 | 欧美国产日韩在线观看 | 午夜视频免费在线观看 | 久久中文欧美 | 大荫蒂欧美视频另类xxxx | 天天射天天色天天干 | 黄色片网站免费 | 狠狠色狠狠色综合日日92 | 欧美一级片免费观看 | 天天做日日做天天爽视频免费 | 亚洲人人av | av在线免费播放 | 五月天综合网站 | 91精品国产91久久久久久三级 | 久久综合桃花 | 2020天天干夜夜爽 | 欧美精品三级在线观看 | 免费电影播放 | 最近高清中文在线字幕在线观看 | 精品国产一区二区在线 | 免费在线观看黄 | 激情偷乱人伦小说视频在线观看 | 亚洲欧美在线观看视频 | 992tv在线| 欧美在线18| 精品一区 精品二区 | 久久9999久久免费精品国产 | 欧美久久久| 天天射一射 | 国产一区精品在线观看 | 99国产精品久久久久久久久久 | 九九九九热精品免费视频点播观看 | 久久久久草 | 一区二区在线影院 | 精品欧美一区二区三区久久久 | www.久草.com | 青草视频在线看 | 九色精品免费永久在线 | 夜夜干夜夜 | 欧美人体xx| 婷婷六月天丁香 | 婷婷五综合 | 特级毛片在线观看 | 国产美女视频网站 | 日韩av综合网站 | 国产一级精品绿帽视频 | 国产亚洲精品久 | 午夜精品久久久久久久99无限制 | 91视频免费网站 | 97电影院在线观看 | 欧美大片大全 | 成人av中文字幕 | 日韩有码欧美 | 最近中文字幕视频完整版 | 91亚洲精品久久久久图片蜜桃 | 久久精品香蕉 | 五月天婷婷在线视频 | 亚洲女欲精品久久久久久久18 | 久久久久综合精品福利啪啪 | 黄色成人毛片 | 久久免费电影 | 五月婷婷中文 | 欧美成年黄网站色视频 | 国产精品精 | av在线播放免费 | 精品久久久久久久久久国产 | 国产精品黑丝在线观看 | 综合婷婷 | 欧美午夜视频在线 | 成人精品一区二区三区中文字幕 | 一区二区中文字幕在线播放 | 在线国产高清 | 久久99国产综合精品免费 | 日b视频国产 | 操操操com| 免费av福利 | 一区二区三区 亚洲 | 91成人精品在线 | 91久久精品日日躁夜夜躁国产 | 97免费在线观看视频 | 91传媒免费观看 | 亚洲精色 | 999色视频| 成人免费大片黄在线播放 | 国产成人精品一区二区在线观看 | 97超视频免费观看 | 亚洲欧美在线观看视频 | 国产区免费在线 | 婷婷五月在线视频 | 99久久精品视频免费 | 操碰av| 日韩精品在线视频免费观看 | 狠狠干天天干 | 免费av网站在线看 | 国产日韩欧美在线观看视频 | 草在线视频 | 婷婷六月综合亚洲 | 91九色成人蝌蚪首页 | 成人一级在线观看 | 中文字幕二区 | 激情久久伊人 | 九九九热精品免费视频观看 | 日韩中文在线字幕 | 欧美天堂视频在线 | 国产亚洲情侣一区二区无 | 欧洲精品视频一区二区 | 91麻豆国产| 在线看av网址 | 91精品视屏| 看片的网址| 夜夜骑日日操 | 亚洲一区精品人人爽人人躁 | 国产精品毛片一区视频播 | 91视频免费看片 | 黄色毛片在线 | 91禁在线观看| 国产日韩精品在线 | 四虎成人网 | 久二影院| 久久久久久久久久久影院 | 亚洲欧美日韩精品一区二区 | 天天天天天天天天操 | 久久人人爽人人爽人人片 | 麻豆成人在线观看 | 国产亚洲片 | 1024在线看片 | 欧美日韩一区二区免费在线观看 | 国产精品毛片久久久久久 | 久久一区二区免费视频 | 色婷婷综合在线 | 97超级碰碰碰碰久久久久 | 久久99国产综合精品 | 四虎永久视频 | av在线等 | 九九九免费视频 | 久久国内免费视频 | 视频一区视频二区在线观看 | 国产特级毛片aaaaaa | 日免费视频 | 欧美性久久久久久 | 久久黄色精品视频 | 成人性生交大片免费看中文网站 | 国产精品国产三级国产不产一地 | 天天操天天干天天操天天干 | 中文字幕在线观看第三页 | 亚洲免费公开视频 | 国产成人福利在线观看 | 久久精品中文字幕免费mv | 91麻豆国产福利在线观看 | 国内99视频 | 国产精品白浆视频 | 91色视频 | 亚洲无人区小视频 | 国产精品男女 | 久久久久成人精品免费播放动漫 | 中文字幕黄色网 | 黄色影院在线播放 | 99re8这里有精品热视频免费 | 日本一区二区高清不卡 | 在线精品观看 | 丁香六月av | a天堂免费 | 一级免费片 | 国产黄影院色大全免费 | 国产亚洲欧美日韩高清 | 亚洲女同videos | 在线视频免费观看 | 九九热在线视频免费观看 | 热久久电影 | 日韩区欠美精品av视频 | 免费看污污视频的网站 | 少妇精69xxtheporn | www.午夜视频| 久久国内免费视频 | 日韩成人精品一区二区三区 | 免费在线观看91 |