生活随笔
收集整理的這篇文章主要介紹了
小游戏“终结者”程序的设计与实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
08年9月入學,12年7月畢業,結束了我在軟件學院愉快豐富的大學生活。此系列是對四年專業課程學習的回顧,索引參見:http://blog.csdn.net/xiaowei_cqu/article/details/7747205
面向對象程序設計
這是我們學習程序設計的第一課。我也在這門課上第一次接觸程語言、寫代碼。我們以影印版的《C++ Program Design : An Introduction to Programming and Object-Oriented Design?》為教材。
現在想來那段“入門”的經歷真是痛苦不堪,很多概念難以理解,就只能一點點把書中的代碼一遍遍的敲。但每次跑出一點小東西也都覺著興奮到不行。大一末的時候有個“大”的課程設計:兩人一組編寫一個小游戲。我和小琦一組,寫了一個比較簡略的闖關游戲,這次經歷之后才真的對編程有了“入門”的感覺。
小游戲"YingMu"
【游戲功能需求說明】
本游戲是基于日本漫畫《灌籃高手》而設計的,相信大家對游戲中的人物都相當熟悉。在游戲中我們采用了鍵盤上、下、左、右控制玩家的移動,空格鍵發射子彈。如果玩家碰到敵人,則游戲結束;消滅所有敵人,則通關。游戲共分為兩關,每一關的地圖是隨機產生的,敵人的移動速度也逐漸加快。雖然功能看似簡單,但其中樂趣無窮,是一款集娛樂、冒險為一體的游戲。
我們這次是在Microsoft Visual C++ 6.0, ?EzWindow library的開發環境下設計完成的,一些程序的功能我們一時沒有想到好的方法來實現,所以在這款游戲中沒有呈現給大家。相信在以后的學習中,我們能更好地掌握并對這款小游戲進行升級更新。
【游戲總類圖】
【游戲中的關鍵類】
Player
[cpp]?view plaincopy
enum?Floor{FLoor1=0,Floor2,Floor3,Floor4};?? ?? class?Player?{?? ????public:?? ?????????? ????????Player(SimpleWindow?&w);?? ????public:?? ?????????? ????????SimpleWindow&?GetWindow()?const;?? ????????Position?GetPosition()?const;???? ????????Direction?GetDirection()?const;???? ????????BitMap&?GetBmp(const?Direction?&d,int?i);??? ????????const?BitMap&?GetBmp(const?Direction?&d,int?i)?const;??? ????????Floor?GetFloor()const;???? ????????bool?IsDying();????? ????????bool?AtRightEdge()?const;?????? ????????bool?AtLeftEdge()?const;?? ?? ?????????? ????????void?Create();???? ????????void?Kill();?????? ????????void?Move();?????? ????????void?Fire();?????? ????????void?OKUp();?????? ????????void?OKDown();?? ????????void?CannotUpDown();?? ?? ?????????? ????????void?SetPosition(const?Position?&p);??? ????????void?SetFloor(Floor?&f);???? ????????void?SetDirection(const?Direction?&d);??? ?????? ?????????? ????????vector<Bullet*>?bullets;????? ????????????????????????????????????? ????????????????????????????????????? ????????????????????????????????????? ????private:?? ?????????? ????????void?Draw();?? ????????void?Erase();???? ????????????????????????? ????????????????????????? ????????????????????????? ?????????? ????????SimpleWindow?&Window;?? ????????vector<vector<BitMap>?>?Bmp;??? ????????Direction?CurrentDirection;?? ????????Position?CurrentPosition;?? ????????bool?bUpOk;?? ????????bool?bDownOk;?? ????????Floor?CurrentFloor;?? ???????????? ???????????? ???????????? ???????????? ???????????? ???????????? ????????int?Steps;???? ?????????????????????? ?? ?????????? };?? Enemy 和 Bullet
[cpp]?view plaincopy
?? ?? ?? ?? ?? ?? #ifndef?ENEMY_H?? #define?ENEMY_H?? ?? const?int?EnemyBitMaps=2;?? enum?EnemyStatus?{Alive,Dead,DeadAlready};?? ????????????????????????????? ?? class?Enemy{?? ???public:?? ????????? ?????Enemy(SimpleWindow?&W,const?Position?&p1=(0,0),const?Position?&p2=(0,0),double?h=1?);?? ??????? ??????? ???public:?? ????????? ???????SimpleWindow&?GetWindow()?const;??? ???????Position?GetPosition()?const;??? ???????Direction?GetDirection()?const;??? ???????double?GetHorizMovement()?const;???? ???????BitMap?&GetBmp(const?Direction?&d);??? ???????const?BitMap?&GetBmp(const?Direction?&d)?const;??? ???????EnemyStatus?GetStatus()const;?? ???????? ???????? ???????void?SetWindow(SimpleWindow?&W);???? ???????void?SetDirection(const?Direction?&d);??? ???????void?SetPosition(const?Position?&p);??? ???????void?SetStatus(EnemyStatus?s);???? ???????void?SetHorizMovement(double?h);??? ???????void?SetP1P2(const?Position?&pp1,const?Position?&pp2);??? ?? ????????? ???????void?Create();????? ???????void?Kill();??? ???????void?Move();??? ???????void?Draw();??? ???????void?Erase();??? ???????Position?NewPosition()?const;??? ???????void?ChangeDirection();??? ????????? ???private:??????? ????????? ???????SimpleWindow&?Window;?? ???????vector<BitMap>?Bmp;?? ???????double?HorizMovement;?? ???????Direction?CurrentDirection;?? ???????Position?CurrentPosition;?? ???????Position?P1,P2;?? ???????EnemyStatus?CurrenStatus;?? ?? };?? #endif?? ?? ?? ?? ?? ?? ?? ??????????? #ifndef?ENEMY_1_H?? #define?ENEMY_1_H?? #include?"enemy.h"?? class?Enemy_1?:?public?Enemy{?? ????public:?? ??????Enemy_1(SimpleWindow?&W,const?Position?&p1=(0,0),?? ??????????const?Position?&p2=(0,0)?,double?h=0.5);?? };?? #endif?? ?? ?? ?? ?? #ifndef?ENEMY_2_H?? #define?ENEMY_2_H?? #include"enemy.h"?? class?Enemy_2?:?public?Enemy{?? ???public:?? ???????Enemy_2(SimpleWindow?&W,?const?Position?&p1=(0,0),?? ???????????const?Position?&p2=(0,0),double?h=0.8?);?? };?? #endif?? ?? ?? ?? ?? ?? ?? #ifndef?BULLET_H?? #define?BULLET_H?? #include?"enemy.h"?? class?Bullet?:?public?Enemy{?? ???public?:?? ?????Bullet(SimpleWindow?&W,Direction?d?,?? ?????????const?Position?&p1=(0,0),?const?Position?&p2=(0,0));?? ?????bool?AtRightEdge()?const;???? ?????????????????????????????????? ?????bool?AtLeftEdge()?const;?? ?????void?B_Creat();???? ???????? };?? #endif?? GameController
[cpp]?view plaincopy
?? ?? ?? ?? ?? ?? #ifndef?GAMECONTROL_H?? #define?GAMECONTROL_H?? ?? enum?GameLevel?{?One,?Second,?Done?};?? ?? class?GameController?{?? ????public:?? ?????????? ????????GameController(const?string?&Title?=?"終結者(櫻木花道版)",?? ?????????const?Position?&WinPosition=Position(2.0,2.0),?? ?????????const?float?WinLength?=16,??const?float?WinHeight?=?13);?? ??????????? ??????????? ?????????? ????????~GameController();?? ?? ?????????? ????????SimpleWindow?*GetWindow();?? ????????GameLevel?CurrentLevel()?const;??? ?? ?????????? ????????void?Play(const?GameLevel?Level);??? ????????void?TestGap(Player*?player,vector<Gap*>?gap);???? ??????????????? ?????????? ????????void?TestBullet(vector<Enemy_1*>?e,vector<Bullet*>?b);?? ????????void?TestBullet(vector<Enemy_2*>?e,vector<Bullet*>?b);?? ??????????????? ????????bool?TestPlayer(Player*?player,vector<Enemy_1*>?e);?? ????????bool?TestPlayer(Player*?player,vector<Enemy_2*>?e);?? ??????????????? ????????int??TimerTick();?? ??????????????? ??????????????? ??????????????? ??????????????? ??????????????? ?? ????private:?? ?????????? ????????SimpleWindow?*GameWindow;?? ????????GameLevel?Level;?? ?????????? ?????????? ?????????? ????????Player?*player;?? ????????vector<Gap*>?gaps;?? ????????vector<Layer*>?layers;?? ????????vector<Enemy_1*>?enemy1;???? ????????vector<Enemy_2*>?enemy2;?? ?? ?? };?? #endif?? 全局的類:Global 和 Welcome
[cpp]?view plaincopy
?? ?? ?? ?? ?? ?? ?? ?? ?? #ifndef??WEL_H?? #define??WEL_H?? ?? ?? ?? ?? ?? SimpleWindow?End("終結者(櫻木花道版)",15.0,12.0,Position(2.0,2.0));?? BitMap?WellDone(End);?? BitMap?Quit(End);?? BitMap?Fail(End);?? ?? void?SetWindows(){?? ????Fail.Load("bmp\\fail.bmp");?? ????assert(Fail.GetStatus()==BitMapOkay);?? ?? ????WellDone.Load("bmp\\done.bmp");?? ????assert(WellDone.GetStatus()==BitMapOkay);?? ?? ????double?width=Fail.GetWidth();?? ????double?height=Fail.GetHeight();?? ?? ????Quit.Load("bmp\\quit.bmp");?? ????Quit.SetPosition(Position(0.6*width,0.8*height));?? ????assert(Quit.GetStatus()==BitMapOkay);?? ?? }?? ?? int?MouseClickEnd(const?Position&?MousePosition){?? ????if(Quit.IsInside(MousePosition)){?? ????????End.Close();?? ????}?? ????return?1;?? }?? #endif?? welcome.h
[cpp]?view plaincopy
?? ?? ?? ?? ?? ?? #ifndef?WELCOME_H?? #define?WELCOME_H?? #include?"assert.h"?? ?? SimpleWindow?Welcome("終結者(櫻木花道版)",15.0,12.0,Position(2.0,2.0));?? BitMap?PlayButton(Welcome);?? BitMap?InstructionButton(Welcome);?? BitMap?Instruction(Welcome);?? ?? void?SetWelcomeWindows(){?? ????BitMap?WelcomeBmp(Welcome);?? ????WelcomeBmp.SetPosition(Position(0,0));?? ????WelcomeBmp.Load("bmp\\hello.bmp");?? ????WelcomeBmp.Draw();?? ????assert(WelcomeBmp.GetStatus()==BitMapOkay);?? ?? ????double?width=WelcomeBmp.GetWidth();?? ????double?height=WelcomeBmp.GetHeight();?? ?? ????PlayButton.SetPosition(Position(0.1*width,0.85*height));?? ????PlayButton.Load("bmp\\play.bmp");?? ????assert(PlayButton.GetStatus()==BitMapOkay);?? ?? ????Instruction.SetPosition(Position(0,0));?? ????Instruction.Load("bmp\\in.bmp");?? ????assert(Instruction.GetStatus()==BitMapOkay);?? ?? ????InstructionButton.SetPosition(Position(0.1*width,0.35*height));?? ????InstructionButton.Load("bmp\\inbutton.bmp");?? ????assert(InstructionButton.GetStatus()==BitMapOkay);?? ????InstructionButton.Draw();?? ?? }?? ?? #endif?? 【游戲控制邏輯框圖】
【游戲說明】
本游戲無需安裝。打開文件夾“YingMu”,雙擊“YingMu.exe”可直接開始游戲。
打開會出現游戲的進入窗口——顯示有灌籃高手劇照圖,單擊窗口中的“Instruction”圖標可以看到具體的游戲操作說明,之后單擊“Play”圖標即可開始游戲。
游戲開始后,玩家可以看到左下角的櫻木花道以及三個在窗口中不停移動的敵人,玩家以鍵盤的左右鍵控制櫻木花道在窗口中移動,當走到籃筐下時,可以有上下鍵控制實現層的跳躍。游戲中,玩家按空格鍵發射子彈(子彈的數目沒有限制),子彈遇到敵人即可消滅敵人。當消滅玩所有的敵人,游戲會彈出對話框提示玩家進入下一關。第二關所有敵人被消滅后,游戲勝利。玩家會看到恭喜的窗口,單擊左下角的“Quit”圖標即可退出游戲。如果游戲中,玩家不小心被敵人捉到,游戲失敗,會出現提示游戲失敗的界面,單擊“Quit”圖標退出游戲。
【游戲截圖】
【項目總結】
通過大一的C++語言學習后,我們小組完成了第一個項目編程—終結者(櫻木花道版)。
接到任務,我們迅速開始……
我們首先上網查閱了相關資料,并下載了一些相關的小游戲進行試玩,揣摩游戲的設計架構及功能實現,汲取別人的長處。接著我們進行課程設計“終結者”的構思,我們最初的設計是界面分為幾層,玩家可以在每一層上走動,通過方向鍵左右移動,遇到樓梯可以上下爬動,空格鍵發射子彈,并設有各種不同的食物,玩家控制小人走過去“吃”,不同的食物增加或減少相對應的屬性(如:生命值、速度等)。然而在真正動手的時候,才發現敲代碼遠遠不像讀代碼那么簡單。我們分工合作,兩個人分別編寫不同的類,幾乎是白手起家,決定和實現每個類有怎樣的功能顯得異常的生疏和困難,尤其在派生的時候才發現總結出對象必要的屬性、行為是多么重要。而這只是困難的開始,當我們把零零散散的代碼拼在一起時,終于見識到所謂的“面向對象”并沒有我們想象的那么簡單。雖然都認真的開了書中的BugHunt程序,可實際上我們很多地方并沒有理解到位,尤其是GameController的重要——把一個個孤立的對象聯系起來,可以相互“交流”的才是真正“活”的對象,才組成了生動的游戲。我們熬了幾個通宵,重寫了很多次,刪減了許多一開始野心勃勃想要實現的內容,于是有了想在這個終結者的雛形。
之后的時間是我們一起小心翼翼的在游戲中添加一些功能,比如發射子彈,櫻木的“走動”效果,以及圖片的處理等等……游戲進入和退去的界面也是在這個時期完成的。
在游戲最終出品前期,我們在實驗室進行試玩,卻發現一個問題:不同的屏幕和分辨率造成了窗口及圖片坐標的偏移,我們最初是在自己的電腦上設定的坐標,因為偷懶而直接使用的數字——迅速顯出弊端,而在實驗室的電腦上,圖片甚至發生了重疊。我們隨即想到的是把游戲做成兩個版本(標屏和寬屏),但后來我們又發現分辨率也會對坐標產生影響,所以兩個版本的計劃無法實施。我們也去請教了別人查閱了資料,最后用圖片的大小來調整層之間的坐標(因為似乎不同的屏幕圖片還是不變的),但問題也沒有得到根本的解決,結果沒有預期的好,這讓我們尤其以為可以自慰的地方——游戲的整體美觀度大打折扣,希望在以后的學習中能更好的解決該問題,進行游戲的升級與更新。
游戲問世,不是期望的樣子……
現在再回頭看我們自己編寫的第一個游戲,即使抱著“敝帚自珍”的心態,依舊覺得她有那么多不盡人意的地方,畢竟最終的成果有點簡單,和當初的設想差得太遠,許多功能都沒有實現——因為ezwin的功能有限,添加游戲背景甚至是在“梯子”上的走動,都有很明顯的閃圖,就改成了跳躍;死掉的子彈和敵人都被我們投機取巧的藏在游戲圖中,沒有真正的delete以釋放內存;時間有限,也沒有再去在界面中做“生命值”、“速度”等……應該是在開始進行程序架構時,我們就缺乏嚴謹的邏輯思考,想法太雜太亂,導致有些功能實現起來太過復雜,而使得程序顯的臃腫且不利于閱讀。
一月奮戰,我們還是收獲了很多……
這次課程設計中,我們深切的體會到調試的重要,很多問題都是在編譯、連接中發現的,看著自己編寫的程序一編譯出現那么多的錯誤,信心肯定受到打擊,但是通過一次次的修改,看著錯誤數量的減少,還是很有成就感的。總的來說,我們用于調試的時間遠遠多與編寫代碼的時間。
通過課程設計,我們不僅鍛煉了自己的實踐能力,更培養了團隊合作能力。遇到問題時,大家一起互相討論,一起請教別人,最終找到解決方法,我想這應該是最好的學習過程,在實踐中提高自己,比看書的效率高太多了。同時我們也意識到書本上的那些知識對于編程是遠遠不夠的,教科書只是介紹一些皮毛而已,它只是引導你入門而已。我們更多的是要主動的學習,一起做項目就是一種好的方法。
我們知道,我們差的太遠太遠,要走的路還很長很長……
這次我們小組出品的游戲——終結者(櫻木花道版)雖然有些粗糙,功能也十分有限,但是做為這款游戲的整個框架與體系,它實現了我們利用面向對象思想設計游戲的初衷。而在編寫以及后來的程序調試與排錯的過程中也練習了我們使用C++語言的熟練度以及對常見問題解決的經驗積累。更主要的是,他使我們深深地看到自己的差距——學習了一年,還沒用過MFC;不能短時間內迅速掌握HGE;即便是參考別人的代碼,還要一個字一個字的讀……這個挺普通的程序也許是對我們貧乏知識的真實寫照,但,這絕不是終點,我們會在今后的學習中努力提高自己的水平,努力創造出優秀的作品。
這是我們軟件學習上的第一次試煉,也是我們大一面向對象程序設計學習的成果,相信我們每個人都將終生難忘……
轉載請注明出處:http://blog.csdn.net/xiaowei_cqu/article/details/7747650
總結
以上是生活随笔為你收集整理的小游戏“终结者”程序的设计与实现的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。