【正文】
數(shù)、類的名稱變?yōu)楹喍痰挠⑽淖帜复?,如果缺乏相應的函?shù)名指示和程序注釋,即使被反編譯,也將難以閱讀。為了能與各種IDE集成,就像Java2 SDK一樣,混淆器采用命令行參數(shù)的形式,以便可被其調(diào)用。如圖34,是內(nèi)存跟蹤測試隨時間變化的調(diào)試器。 內(nèi)存監(jiān)視器 本章小結(jié) 第三章中介紹了程序的流程、相關(guān)技術(shù)的思想及其在本程序中的應用。它控制著整個程序的運行,并且可以通過相應函數(shù)從程序描述文件中獲取相關(guān)的信息。運行畫面如圖41所示。Alert對象用于顯示提示、警告等告之用戶信息的臨時閃現(xiàn)的屏幕,它可作為setCurrent的參數(shù),提前顯示在最終需要顯示的屏幕前。 使用說明畫面startChoice繼承了接口mandListener,這樣,就可以使用高級界面的Command按鈕。鍵盤事件中,可用getCommandType()返回的Command類型來確定選擇的是什么按鈕。 主游戲邏輯及其涉及到的若干類開始敵人小于0 顯示記分畫面最后一關(guān)?進入下一關(guān)敵人數(shù)量大于屏幕上的數(shù)量嗎?增加一個敵人玩家是否死亡顯示GameOver重繪屏幕內(nèi)存回收結(jié)束YNYNNYYN BattleCanvas類主要關(guān)系流程圖 BattleCanvas主管著所有類之間的協(xié)調(diào),決定何時死亡,何時分配新的敵人,及控制敵人出現(xiàn)處的閃光圖標、游戲結(jié)束后的動態(tài)Gameover字樣。其主邏輯如圖43所示。BattleCanvas包括了LayerManager,這樣所有靜態(tài)和動態(tài)的圖象都不需要手動刷新,只需要在LayerManager中加入所有的需控制的元素,再統(tǒng)一由LayerManager刷新即可。 構(gòu)造函數(shù)中,需初始化地圖。在創(chuàng)建了InputStream類的map對象后,使用read()函數(shù)可將流中的下一個字節(jié)讀出,并返回此字節(jié)代表的整數(shù)。繪出地圖后,可用LayerManager的append()將地圖放置在第一層。由于敵人將依次出現(xiàn)在屏幕上,同時出現(xiàn)的數(shù)量應當受到控制。在構(gòu)造函數(shù)自己調(diào)用了線程的start后,程序?qū)㈤_始循環(huán)運行,直至跳出while的循環(huán)。當然,如果當前已是最后一關(guān),就不會再轉(zhuǎn)回。以在兩秒鐘內(nèi)反復閃現(xiàn)兩次為一個生命周期。本程序設(shè)置的兩次坦克出現(xiàn)的最小間隔為2秒。在出現(xiàn)正式畫面前設(shè)置了一個loading state*字樣的單獨屏幕,調(diào)用了loadinglevel()函數(shù),并停滯了1500毫秒,提示用戶做好準備。在每次刷新繪圖頁面時,應使用GameCanvas的flushGraphics()將屏幕后臺的緩沖區(qū)內(nèi)的圖象刷新到前臺來。EnemeySprite和UserSprite都繼承了該類以簡化結(jié)構(gòu)。在setBulletDirection()中,將根據(jù)坦克當前的方向確定子彈出膛后的方向,其中setRefPixelPosition()將子彈的參考點設(shè)置在其未變形狀態(tài)的底部,setXY()將其放置到炮口的位置,setTransform()將其圖片方向轉(zhuǎn)到需要使用的位置。在得到障礙物屬性后,判斷其序號是否與草相同,或是否為空(序號為0)。需要聯(lián)系的還有自身坦克、地圖。最終調(diào)用其start()開始子彈自己的線程。這樣,它才能有掃描的目標。在go()函數(shù),每個方向在走前都須用if (canPass(UP)amp。collidesEnenmy檢測是否前方有坦克阻礙行動。否則,當玩家向上走,而有敵人從左方向右走,并且已經(jīng)碰撞到玩家坦克時,玩家坦克會因為被判定已與敵人發(fā)生碰撞而不允許前進。 敵人坦克的功能屬性 由于和UserSrite同屬于一個TankSprite的繼承類,其功能就與UserSprite有很大的相似之處,但也有其自身的特別屬性。因此,它可以運行在單獨的線程中。Random random=new Random(())。getRandomStep()的原理類似: Random random=new Random(())。每個敵人還需要擁有一個內(nèi)部的所有敵人的數(shù)組元素。if(i==number)break 。此函數(shù)用來檢測是否在剛出現(xiàn)時就與其他坦克發(fā)生碰撞的。如果不是剛出現(xiàn)(由isBeginner決定),判斷是否與將其他坦克發(fā)生碰撞,就向當前方向前進一步驟,否則,將需要循環(huán)檢測的當前隨機步數(shù)減少為原先的2/3(為了加速離開的時間)。當所有的步驟走完后,因為需要轉(zhuǎn)動方向,于是,調(diào)用一次隨機取得方向的函數(shù)再次獲值。如果是,就不應該受到其他坦克的影響而直接改變坐標,但若不是,就應當遠地不動。其主要功能流程圖見圖46。爆炸效果需要將圖片insert進第0層,這樣才不至于被其他景物所覆蓋,爆炸結(jié)束后layerManager會自動相應調(diào)整。amp。amp。如果程序在子彈已經(jīng)到達X軸的155坐標時仍允許子彈繼續(xù)運行,子彈將一次性向右運行2個象素,到達157點。 子彈運行中,將用collidesWith(tiledLayer,true)測試是否碰撞上了地圖。 如果沒有擊中物體,就繼續(xù)檢測是否擊中了某輛坦克。 如果是來自敵人的子彈,將同樣檢測與玩家子彈的碰撞,及與玩家坦克的碰撞如有碰撞,玩家生命數(shù)減少一位,位置重置。如果不放置到屏外,敵人坦克仍會被阻擋,子彈仍會再次擊中用戶坦克。 記分系統(tǒng)記分系統(tǒng)的功能指定在ScoreScreen類內(nèi)。隨后將分別建立ByteArrayOutputStream 和DataOutputStream以便實現(xiàn)多字段的記錄。getScore()函數(shù)得到所需要序號的分數(shù)。(i+1,record,0,)將把已讀出的當前位置的記錄寫入到下一條中,當發(fā)現(xiàn)移動完畢后當前序號即為所需要插入的位置時,(name), (score),(i,record,0,),將記錄寫入。效果如圖47顯示。每關(guān)的分數(shù)被設(shè)置為100000/duration。如果需要進入下一關(guān),則進入本關(guān)統(tǒng)計分數(shù)的顯示。當用戶的分數(shù)達到一定的高度可以寫進記錄時,將調(diào)用inputName=new Form(Congratulations)創(chuàng)建一個新的Form類的屏幕,其中包括一個TextField,允許用戶輸入自己的姓名,這樣使用getString就可以將輸入讀出,寫入到記錄中。經(jīng)過了細心的調(diào)試和排錯解決了絕大部分的問題。目前發(fā)現(xiàn)的bug和未完善的功能列表如下:1. 與敵人對子彈的時候有時候可能會出現(xiàn)當敵人死后,自己若仍在原地,子彈會發(fā)不出去。即使刷屏沒有間隔也不會提高速度。 2. 有時會莫名其妙的死機。在數(shù)據(jù)庫、各種應用軟件和游戲中,我仍覺得對游戲的設(shè)計有極大的熱情。相比一些數(shù)據(jù)庫軟件,游戲的設(shè)計有很多人情色彩和藝術(shù)思想的發(fā)揮,正式商業(yè)的軟件的人性化界面和各個游戲間迥異的結(jié)構(gòu)每每會讓人有去開發(fā)的沖動。運行在12MHz,8K內(nèi)存的硬件機器上仍不失流暢性和可玩性。.[4] (美)莫尼遜 著編著 《J2ME手機游戲編程入門》 電子工業(yè)出版社 .[5] (美)梅特斯克,(美)韋克著 《Java設(shè)計模式》 人民郵電出版社 .[6] 張鵬等著 《JAVA手機游戲?qū)嵗謨浴? 海洋出版社 .[7] 陳剛著 《Eclipse從入門到精通》 清華大學出版社 .[8] (美)Ron patton,張小松等譯 《軟件測試》 機械工業(yè)出版社 .[9] (美)哈特姆諾著 《Java技術(shù)精髓》 機械工業(yè)出版社 .[10] .[11] [12] .[13] .[14] .[15] .致 謝首先感謝我的指導老師XX,他在我的畢業(yè)設(shè)計過程中提出了指導性的方案和架構(gòu),并指引我閱讀相關(guān)的資料和書籍,使我在不熟悉的領(lǐng)域中仍能迅速掌握新興的技術(shù)。本科學習中的各科老師對提高我的編程素質(zhì)有很大的幫助,我的同學在設(shè)計完成后對程序的測試,沒有他們,也許就難以發(fā)現(xiàn)一些潛在的錯誤,在此一并表示感謝。import .*。private TiledLayer board。public static int enemyNum=9。private String level2=/tank/。public static long beginTime。 // used to calculate how much time had been taken on a single level to determine the obtained score./*3 positions are defined at top of the screen each time theenemy es are 1,2,3 will taketurns to e out from these three ports. Default postion is 1. */ public BattleCanvas() throws IOException{ super(true)。 (board)。 board=createTiledLayer()。public static boolean pleted=false。 //define what level the game is in now.private boolean isLoading=true。public static int enemyOnScreen=0。private ScoreScreen scoreScreen=new ScoreScreen()。private LayerManager layerManager。import .*。你們客觀的評價和建議我將牢記在心,在今后的發(fā)展中揚長避短,更加努力的嚴格要求自己。機器代碼級和基于虛擬機的半解釋性處理的程序在這里得到了最大的對比。然而,回首80年代的紅白機上的坦克大戰(zhàn)原始游戲,將驚嘆那樣的商業(yè)軟件的巧奪天工。大學期間做過學生管理程序等簡單的數(shù)據(jù)庫管理系統(tǒng)的課程設(shè)計,思想大致相似,變化范圍有限,沒有太多自己可發(fā)揮的余地。 經(jīng)驗和感想這款游戲作為我的畢業(yè)設(shè)計,是本人目前做過的最有意義的程序,這期間對J2ME的學習,使我又回到了初學Java的時候。6. 當敵人和自己同時死亡時,仍會過關(guān),但game over字樣會出現(xiàn),下一關(guān)坦克不會出現(xiàn),但可以隱身發(fā)炮。 3. 子彈和敵人經(jīng)常會與畫面的刷新的線程不同步,造成畫面閃爍。即使是作為操作系統(tǒng)的各種版本的Windows也時常會發(fā)生許多類型的錯誤和漏洞。對游戲有關(guān)的各運行界面也做了展示。按鈕由addCommand()加入,并設(shè)置了mandListener()確定按鍵事件發(fā)生后的動作。就不將當前關(guān)得到的分數(shù)加入到總分的計算里,否則就調(diào)用totalScore=totalScore+levelScore進行累加。在這個在刷新屏幕時(repaint()被調(diào)用)需要執(zhí)行的方法中,設(shè)置了一個整形的duration,用來記錄完成一關(guān)所用的時間。drawList()函數(shù)繪畫出當前的屏幕分數(shù)。使用它只是為了將記錄的指針向后推移到可以讀出分數(shù)字段的位置。score=()將所得的被寫入的數(shù)據(jù)流輸送到score的字節(jié)數(shù)組中。在BattleCanvas請求調(diào)入分數(shù)統(tǒng)計的屏幕時,將首先調(diào)用initRs()初始化一些環(huán)境變量。為了能控制一輛坦克在同一時間只能發(fā)射一發(fā)子彈,在子彈生命運行結(jié)束時候,()恢復坦克繼續(xù)發(fā)炮的能力。因為layerManager的remove函數(shù)并不會真正將層移除。當來自玩家時,將首先檢測所有的敵人發(fā)出的子彈,當發(fā)生子彈間的碰撞時,用戶的子彈將被移除,雖然按照道理敵人的子彈同時也應被移除,但敵人子彈是運行在另一線程中的,應當由它自己來控制為好,用戶的子彈只需要管理好自己的狀態(tài)就可以了。這將針對四個不同的方向分別以象素級檢測。地圖的tiledLayer對象中并不存在序號為20的塊,最大只為19。這幾項參數(shù)在編寫時很容易出錯。amp。 setShootCheck(EnemySprite enemySprite[]);setUserSprite(UserSprite userSprite);setEnemySprite(EnemySprite enemySprite)都是將相關(guān)的坦克傳入到子彈類里來,以便確認來源或攻擊目標。當擊中了需要作出反映的物體時,就分別采取措施:擊中草時,由于沒有定義相關(guān)函數(shù),就不會有任何反映,會重合在草上正常通過;擊中磚塊時,將產(chǎn)生爆炸,調(diào)用setCell將當前塊置為空,并產(chǎn)生爆炸效果。它擁有一個很重要的變量,isFromEnemy。開始是否出界是否擊中物體將障礙物消除玩家的子彈嗎是否與任何敵人的子彈碰撞是否擊中敵人敵人的子彈嗎?是否碰撞是否擊中玩家結(jié)束NYNYYN子彈抵消Y消除敵人YNNNNN消除玩家子彈抵消 子彈運行的主要功能流程圖YYY在go()函數(shù)中首先檢測是否正處于碰撞狀態(tài)中,如果不是,就需要取消Beginner的狀態(tài),因為不需要Beginner這樣的特殊身份,讓別的坦克不檢測了。當隨機發(fā)炮數(shù)減少到0時,就進行發(fā)炮的動作。在運行的線程中,需在每前進的一步驟中循環(huán)做下列事件:如果坦克已死亡,立刻退出。collidesInOtherTank()雖與上面的函數(shù)很相似,但仍有一些細微不同,那就是不需要在檢測前設(shè)置被檢測方的矩形區(qū)域。 collidesWithOtherTank()將檢測是否與其他坦克(包括敵人和玩家)。只是需要乘以每秒會刷新的屏幕的次數(shù)。此時返回的值的范圍就確定在1~4之間,正好對應四個方向。此函數(shù)由BattleCanvas調(diào)用。 首先,EnemySprite繼承