自己动手写游戏:飞机大战
要說微信中最火爆的小游戲是哪款,可能既不是精心打造的3D大作,也不是《植物大戰僵尸2》,而是微信5.0剛開啟時的《飛機大戰》。
就是這樣一款鉛筆手繪風格的簡單到不能再簡單的“打飛機”游戲,讓國內的微信用戶一次又一次地嘗試,并表示似乎又找回了童年時玩電子游戲的那份單純的快樂。至于游戲的玩法都不用加以介紹,就是簡單的“打飛機”。
二、關于游戲設計
2.1 總結游戲印象
(1)一個玩家飛機,多個電腦飛機
①
②
③
④
(2)玩家飛機可以發射子彈,電腦飛機也可以發射子彈
①
②
(3)玩家和電腦飛機被擊中后有爆炸效果,并且有一定幾率出現大型飛機
①
②
2.2 總結設計思路
(1)萬物皆對象
在整個游戲中,我們看到的所有內容,我們都可以理解為游戲對象(GameObject),每一個游戲對象,都由一個單獨的類來創建;在游戲中主要有三類游戲對象:一是飛機,二是子彈,三是背景;其中,飛機又分為玩家飛機和電腦飛機,子彈又分為玩家子彈和電腦子彈。于是,我們可以對飛機進行抽象形成一個抽象父類:PlaneBase,然后分別創建兩個子類:PlanePlayer和PlaneEnemy;然后對子彈進行抽象形成一個抽象類:BulletBase,然后分別創建兩個子類:BulletPlayer和BulletEnemy。但是,我們發現這些游戲對象都有一些共同的屬性和方法,例如X,Y軸坐標,長度和寬度,以及繪制(Draw())和移動(Move())的方法,這時我們可以設計一個抽象類,形成了GameObject類:將共有的東西封裝起來,減少開發時的冗余代碼,提高程序的可擴展性,符合面向對象設計的思路:
(2)計劃生育好
在整個游戲中,我們的玩家飛機對象只有一個,也就是說在內存中只需要存一份即可。這時,我們想到了偉大的計劃生育政策,于是我們想到了使用單例模式。借助單例模式,可以保證只生成一個玩家飛機的實例,即為程序提供一個全局訪問點,避免重復創建浪費不必要的內存。當然,除了玩家飛機外,我們的電腦飛機集合、子彈集合等集合對象實例也保證只有一份存儲,降低游戲開銷;
(3)對象的運動
在游戲買賣平臺中,玩家可以通過鍵盤上下左右鍵控制玩家飛機的上下左右運動,而飛機的運動本質上還是改變游戲對象的X軸和Y軸的坐標,然后一直不間斷地在窗體上重繪游戲對象。相比玩家飛機的移動,電腦飛機的移動則完全是通過程序中設置的隨機函數控制左右方向移動的,而玩家飛機發出的子彈執行的運動則是從下到上,而電腦飛機發出的子彈執行的運動則是從上到下。
(4)設計流程圖
三、關鍵代碼實現?
3.1 客戶端開發
(1)設計GameObject類:封裝所有游戲對象的公有屬性
?View Code
一切皆對象,這里封裝了游戲對象:飛機、子彈以及其他游戲對象共有的屬性,以及兩個抽象方法,讓對象們(飛機?子彈?爆炸效果?等)自己去實現。
(2)設計SingleObject類:保證游戲中的類都只有一個實例
?View Code
這里借助單例模式,保證玩家飛機對象只有一個存儲,電腦飛機集合也只有一個,而具體的電腦飛機對象則分別在單例類中的集合中進行Add和Remove。
(3)設計CollisionDetect方法:不停地進行碰撞檢測
①Rectangle的IntersectsWith方法
在游戲界面中,任何一個游戲對象我們都可以視為一個矩形區域(Rectangle類實例),它的坐標是X軸和Y軸,它還有長度和寬度,可以輕松地確定一個它所在的矩形區域。那么,我們可以通過Rectangle的IntersectsWith方法確定兩個Rectangle是否存在重疊,如果有重疊,此方法將返回?true;否則將返回?false。那么,在飛機大戰中主要是判斷兩種情況:一是玩家或電腦飛機發射的子彈是否擊中了對方?二是玩家是否撞到了敵人飛機?
②在定時器事件中定期執行碰撞檢測方法
?View Code
3.2 服務端開發
(1)創建監聽玩家連接的Socket,不停地監聽玩家的游戲連接請求
?View Code
在.NET中進行網絡編程,一般都會涉及到Socket,其過程大概會經歷如下圖所示的流程:
PS:Socket非常類似于電話插座,以一個電話網為例:電話的通話雙方相當于相互通信的2個程序,電話號碼就是IP地址。任何用戶在通話之前,首先要占有一部電話機,相當于申請一個Socket;同時要知道對方的號碼,相當于對方有一個固定的Socket。然后向對方撥號呼叫,相當于發出連接請求。對方假如在場并空閑,拿起電話話筒,雙方就可以正式通話,相當于連接成功。雙方通話的過程,是一方向電話機發出信號和對方從電話機接收信號的過程,相當于向Socket發送數據和從Socket接收數據。通話結束后,一方掛起電話機相當于關閉socket,撤消連接。
(2)使用線程池ThreadPool新開線程,不停地接收玩家發送的信息
ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveData), proxSocket);在監聽線程中使用了線程池,開啟了一個新的線程來接收客戶端發送過來的數據,那么這個ReceiveData方法如何實現的:
?View Code
(3)當所有玩家都發送完游戲分數,服務器端對所有分數進行排序并發送最終名次
?View Code
在服務端有一個鍵值對集合專門存儲玩家對應分數,然后對其按分數進行降序排序,排序后再遍歷集合一一向玩家發送名次信息;
四、個人開發小結
4.1 服務端開啟服務
服務器端主要開啟監聽玩家連接請求的服務,當幾個處在同一局域網的玩家連接后,服務端管理員點擊“開始游戲”則客戶端會啟動游戲。
4.2 客戶端開始游戲
在客戶端中,玩家飛機可以通過不停地發射子彈向不同類型的電腦飛機來獲取得分,但是如果被敵人飛機的子彈擊中分數也會被扣去一部分。
4.3 服務端計算成績客戶端顯示
當兩個玩家連接游戲服務端后,便開始了“打飛機”的戰斗,當指定時間后游戲結束,顯示各自的游戲名次和分數。
當然,還有很多核心的內容沒有實現。希望有興趣的童鞋可以去繼續完善實現,這里提供一個我的飛機大戰實現僅供參考,謝謝!
總結
以上是生活随笔為你收集整理的自己动手写游戏:飞机大战的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 知名论坛猴岛游戏论坛宣布永久关闭!
- 下一篇: 得到qq正在登录的qq号
