呂佳歡 蔣富 金易
摘要:炸彈人是一個2D休閑小游戲,可以一機雙人操作,只要使用方向鍵控制人物移動方向,空格鍵和Ctrl鍵放置炸彈,就可以進行游戲。游戲制定了一些主要規(guī)則:倒計時結(jié)束若仍有玩家生存則玩家勝利,游戲結(jié)束;倒計時內(nèi)玩家全部死亡則玩家失敗,游戲結(jié)束;玩家與敵人相碰則死亡。同時該游戲還實現(xiàn)了其他擴展功能。
關(guān)鍵詞:炸彈人;2D雙人小游戲
中圖分類號:TP393 ? ? ?文獻標識碼:A
文章編號:1009-3044(2020)25-0097-02
1需求分析
1)后端與前端的耦合性低。后端代碼包括背景、道具、人物、計分、音樂;前端代碼包括菜單和游戲界面。
2)實現(xiàn)炸彈爆炸后鏈式引爆相鄰的炸彈。放置的炸彈在一定時間后爆炸會產(chǎn)生沖擊波,從而消滅在該范圍內(nèi)的人或可炸毀物。若沖擊波范圍內(nèi)有其余炸彈,不管它們是否到達爆炸時間,都會爆炸。
3)多個參數(shù)可配置。玩家可以在菜單界面自行調(diào)整多種參數(shù)。比如:玩家人數(shù)、敵人個數(shù)等。
4)控制音樂開關(guān)。在菜單界面可通過單擊按鈕來控制音樂的開關(guān)。
5)可隨機產(chǎn)生地圖。既可在菜單界面選擇要產(chǎn)生的地圖,也可點擊隨機按鈕產(chǎn)生隨機地圖。
6)可選擇不同的角色。游戲開始前,必須為玩家選擇游戲時的角色。
7)完善道具使用功能,增加道具種類。
2 系統(tǒng)設(shè)計
2.1 總體分析
建立GUI界面。GUI界面分為開始界面和游戲界面,從開始界面可打開游戲界面。開始界面的不同按鈕可以進行參數(shù)的選擇。將這些參數(shù)傳遞給游戲界面,則可控制游戲界面出現(xiàn)的玩家人數(shù)及角色等。
開始界面添加一個JPanel類的卡片式布局的面板,在這個面板中再添加多個面板(MyPanel),MyPanel面板繼承自JPanel類并重寫了paint(g)方法,可實現(xiàn)背景的繪制。
開始界面添加鼠標監(jiān)聽,為不同的MyPanel面板添加相應(yīng)的按鈕,通過按鈕實現(xiàn)不同面板的切換以及參數(shù)的配置。
游戲界面添加一個面板(MapPanel),將之前選擇的參數(shù)傳遞進這個面板中,之后在這個面板里重寫paint(g)方法,通過調(diào)用其他類里編寫的draw(g)方法,即可將各種物體顯示在面板上。
游戲界面添加鍵盤監(jiān)聽來控制人物的移動以及放置炸彈。
游戲中的屬性包括:地圖塊,玩家,敵人,炸彈,道具。同時有一個計分+計時功能。
2.2 問題及解決方法
該游戲的設(shè)計過程中,主要解決以下問題,這些問題根本上都是控制圖片的顯示與移動。
1) 地圖的實現(xiàn):因為要涉及某些地圖塊的炸毀,所以畫地圖時不能直接畫一整塊,而是要一塊一塊地畫。在地圖二維數(shù)組中存儲地圖塊數(shù)據(jù),不同數(shù)字代表不同地圖塊。一個Field對象代表一個地圖塊,由它的構(gòu)造函數(shù)里的參數(shù),可以選擇不同的地圖以及該地圖塊所處位置。地圖參數(shù)不同,所對應(yīng)的地圖數(shù)組也就不同。由傳遞進Field構(gòu)造函數(shù)里的位置參數(shù)選擇地圖二維數(shù)組的某個數(shù)據(jù),以此來決定要畫的地圖塊種類。同時為該地圖塊設(shè)置屬性:是否可以移動、是否可以炸毀、是否可以添加道具。在后續(xù)編寫代碼過程中就可以依據(jù)這些屬性來移動人物、炸毀某些障礙物、炸毀障礙物后添加道具。
2) 障礙物的判斷:判斷相應(yīng)位置的地圖塊的移動屬性即可。
3) 玩家的上下移動:為窗體添加鍵盤監(jiān)聽,判斷按鍵以及地圖塊是否可行來決定是否改變玩家的位置。
4) 空格放炸彈:利用ArrayList<>()存儲Bomb。放炸彈不能只判斷按鍵,還要判斷地圖上的情況。如果玩家在的地方已經(jīng)放了炸彈且未爆炸,則不能再放。如果放過炸彈但已經(jīng)爆炸了的地方,則可以放炸彈。這里需要用到碰撞檢測,而且也要給Bomb添加一個屬性來表示炸彈是否爆炸。
5) 敵人的自由移動:設(shè)置一個整型變量,它的4個不同數(shù)字代表不同的運動方向。用一個隨機函數(shù)來改變這個變量的數(shù)字,通過控制Enemy對象的位置來實現(xiàn)敵人的自由移動。
6) 爆炸效果+爆炸后更新地圖:在Bomb的draw(g)中,用time變量控制顯示炸彈還是顯示爆炸后的沖擊波。顯示沖擊波時,要判斷炸彈周圍的地圖塊是否可炸,若是道路,則直接畫沖擊波;若是可炸的障礙物,則要利用數(shù)組列表的set方法將該障礙物替換成道路,并畫沖擊波。
7) 炸彈沖擊波與玩家、敵人、障礙物的碰撞檢測:利用Rectangle對象的intersects(Rectangle)方法。
8) 炸彈爆炸后鏈式引燃相鄰的炸彈:利用碰撞檢測,若炸彈的沖擊波與未爆炸的炸彈碰撞,則改變此炸彈的time,使其立馬爆炸。
9) 控制游戲結(jié)束:利用JOptionPane.showMessageDialog(null, String, String,JOptionPane.INFORMATION_MESSAGE)。若倒計時結(jié)束,或者玩家全部死亡則結(jié)束。其中玩家死亡可以通過玩家的live屬性。游戲過程中,若玩家死亡則令其live為0。當(dāng)所有玩家的live全為0時游戲結(jié)束。
2.3 流程圖
2.4 函數(shù)調(diào)用關(guān)系
2.5 函數(shù)功能說明
后端:
前端GUI:使用JDK中的AWT和Swing庫繪制GUI
3 結(jié)論與心得
3.1 調(diào)試
1) 背景的大小與窗體不適應(yīng)。
解決方法:畫背景圖片時,g.drawImage( )方法中的圖片大小不用確切的數(shù)字,而是用窗體的獲取寬度和高度的方法。
2) 繪制地圖塊時,出現(xiàn)越界的錯誤。
解決方法:繪制地圖塊時,我是利用二維數(shù)組里的行數(shù)和列數(shù)來畫的,因為這樣可以與二維數(shù)組里的數(shù)字相對應(yīng),從而畫出對應(yīng)的地圖塊類型。地圖塊的位置就是二維數(shù)組里的行數(shù)和列數(shù)分別乘寬度與高度后得到的數(shù)。而我將行數(shù)乘寬度當(dāng)作了橫坐標,將列數(shù)乘高度當(dāng)作了縱坐標,所以出錯。橫坐標應(yīng)為列數(shù)乘寬度,縱坐標為行數(shù)乘高度。
3) 若地圖上有炸彈,在其他地方放另一個炸彈時原先的炸彈就立馬消失了。
解決方法:每次添加炸彈時都用ArrayList的add()方法將其放入 ArrayList<>()對象中,解決炸彈的 獨立問題。
4) 炸彈爆炸時,沖擊波會穿透不可炸物。
解決方法:在Bomb的draw方法中增加if條件語句,使得當(dāng)放置炸彈的周圍的地圖塊為可炸物時才會繪制沖擊波。
5) 炸彈可炸物后,可炸物不會消失。
解決方法:僅改變地圖數(shù)組里的數(shù)字不能直接將地圖塊置換,需將所有的Field對象全部放入List中,當(dāng)可炸物被炸彈炸到后,利用List里的set方法將可炸物地圖塊換成玩家可以行走的地圖塊。
3.2心得
游戲的開發(fā)需要做到以下幾點:窗體顯示、圖片繪制、圖片移動、窗體監(jiān)聽、相交判定等。游戲的本質(zhì),實際上可以理解為圖像的顯示和圖像的移動。明白這個實質(zhì)后,寫游戲的關(guān)鍵問題就變成了怎么顯示圖片和怎么控制圖片移動。
顯示圖片需要用到 javax.swing 包下的 JPanel類與JFrame類。JPanel 提供了一個面板(畫板),顯示圖片就相當(dāng)于在面板上把圖片畫出來。JFrame 提供了一個窗體(窗口),面板被放到窗體中,最終展示在屏幕上。JPanel 上顯示圖片,是通過重寫JPanel中的繪制方法 void paint(Graphics g)。其參數(shù)Graphics相當(dāng)于為我們提供了“一支畫筆”,我們可以通過調(diào)用它的畫圖方法drawImage在面板上畫任何東西。
控制圖片移動實際上就是改變一下drawImage中的圖片的坐標。JPanel對象的paint方法,只在窗體顯示時調(diào)用一次,所以在改變圖像坐標的同時,還需要不斷地重新繪制面板內(nèi)容,以達到畫面的刷新,圖片才能真正地被肉眼所看到移動。JPanel提供了一個刷新的方法repaint( ),即重新繪制。圖像的移動分為人為控制與非人為控制,人為控制時需加監(jiān)聽,非人為控制時只需用循環(huán)即可。
總之,此系統(tǒng)做的效果較可以,界面美觀,功能豐富,易于上手,最初的需求均已實現(xiàn),有利于其他編程人員學(xué)習(xí)。
【通聯(lián)編輯:光文玲】