版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、課程設(shè)坦克大戰(zhàn)一、游戲介紹相信大部分同學(xué)都玩過(guò)或看過(guò)“坦克大戰(zhàn)”這款經(jīng)典游戲?,F(xiàn)在,就由我們自己動(dòng)手來(lái)開(kāi)發(fā)它。只要大家具備了 C+語(yǔ)言和面向?qū)ο蟮幕A(chǔ)知識(shí),然后按照實(shí)驗(yàn)指南的指導(dǎo)一步一步進(jìn)行下去,相信我們每個(gè)同學(xué)都能把這款經(jīng)典游戲做出來(lái)。二、實(shí)驗(yàn)?zāi)繕?biāo)綜合運(yùn)用C+及其面向?qū)ο蟮闹R(shí)開(kāi)發(fā)一款小游戲。三、實(shí)驗(yàn)內(nèi)容在一個(gè)戰(zhàn)場(chǎng)上,玩家控制坦克,消滅敵方坦克,并防止敵方坦克摧毀我方基地。游戲的具體要求如 下:1、游戲有一個(gè)初始頁(yè)面,如下圖。2、按下任意鍵開(kāi)始游戲,玩家控制坦克在戰(zhàn)場(chǎng)上穿梭,碰到墻時(shí),不能通過(guò)。3、敵方坦克自由移動(dòng),每隔 2秒改變一個(gè)方向,每隔 3 秒發(fā)射一發(fā)子彈。4、敵方坦克每隔 5 秒出
2、現(xiàn)一輛,從屏幕上方的左、中、右三個(gè)位置依次出現(xiàn)。5、 當(dāng)玩家被消滅或者我方基地被摧毀或者游戲時(shí)間大于30 秒的時(shí)候,游戲結(jié)束。游戲開(kāi)始前進(jìn)入游戲四、游戲的整體框架五、實(shí)驗(yàn)指南實(shí)驗(yàn)準(zhǔn)備打開(kāi)FunCode,創(chuàng)建一個(gè)新的 C+項(xiàng)目。注意:項(xiàng)目名稱(chēng)必須為英文和數(shù)字,且不能有空格。點(diǎn)擊“項(xiàng)目”7“導(dǎo)入地圖模板”,從對(duì)話(huà)框中選取名稱(chēng)為 Tan kWar的模板導(dǎo)入。導(dǎo)入成功后,界面 如下:實(shí)驗(yàn)一 游戲開(kāi)始【實(shí)驗(yàn)內(nèi)容】1、設(shè)置游戲標(biāo)題2、按空格鍵 , 提示圖片消失 , 游戲進(jìn)入開(kāi)始狀態(tài) .【實(shí)驗(yàn)運(yùn)行結(jié)果】游戲開(kāi)始前按下空格鍵后【實(shí)驗(yàn)思路】按下空格鍵是鍵盤(pán)按下事件 ,可在 CSystem:OnKeyDown 函
3、數(shù)中編寫(xiě)響應(yīng)代碼。為了保證程序結(jié)構(gòu)的清晰、一致,更好的辦法是在 CGameMair類(lèi)中添加一個(gè)相應(yīng)的鍵盤(pán)按下事件處理函數(shù),然后在CSystem:OnMouseClick 函數(shù)中進(jìn)行調(diào)用。g_GameMain是CGameMair類(lèi)的對(duì)象,它是全局變量,在程序運(yùn)行時(shí)最先被創(chuàng)建?!緦?shí)驗(yàn)指導(dǎo)】1、 C+程序的 執(zhí)行入口是主函數(shù)。Fun Code的 主函數(shù)名稱(chēng)叫 Win Ma in ,寫(xiě)在文件中。CSystem:SetWi ndowTitle是設(shè)置程序運(yùn)行窗口標(biāo)題的函數(shù),修改如下:CSystem:SetWindowTitle(坦克大戰(zhàn));2、 參考 CSystem:OnKeyDown 函數(shù),為 CGam
4、eMair類(lèi)創(chuàng)建一個(gè) OnKeyDown函數(shù)。CGameMair類(lèi)的頭文 件是文件,實(shí)現(xiàn)代碼寫(xiě)在文件中。因此,先在文件對(duì)函數(shù)進(jìn)行聲明。函數(shù)的返回值和參數(shù)列表都與CSystem:OnKeyDown函數(shù)保持一致。訪(fǎng)問(wèn)權(quán)限應(yīng)該是 public。代碼如下: void On KeyDow n( const int iKey, const bool bAltPress, const bool bShiftPress, const bool bCtrlPress );3、接著,在文件中對(duì)該函數(shù)進(jìn)行定義:void CGameMa in :O nKeyDow n( const int iKey, const b
5、ool bAltPress, const bool bShiftPress, const bool bCtrlPress )4、 在CSystem:OnKeyDown函數(shù)(文件中)調(diào)用 CGameMain:OnKeyDown函數(shù),并將自己的參數(shù)傳遞 給該函數(shù)。g_GameMain是是CGameMain類(lèi)的對(duì)象,它是全局變量,在程序運(yùn)行時(shí)最先被創(chuàng)建。因此,我們可以用 g_GameMain調(diào)用自己的成員函數(shù) On KeyDown(iKey, bAltPress, bShiftPress, bCtrlPress);5、 FunCode程序運(yùn)行時(shí),當(dāng)發(fā)生鍵盤(pán)按下事件,程序首先調(diào)用并執(zhí)行 CSystem
6、:OnKeyDown函數(shù),然 后由CSystem:OnKeyDown函數(shù)調(diào)用并執(zhí)行 CGameMain:OnKeyDown函數(shù)。因此,鍵盤(pán)按下事件的 響應(yīng)代碼我們?cè)?CGameMai n:O nKeyDown函數(shù)中編寫(xiě)即可。6、 我們要處理的兩個(gè)精靈如下圖,它們的名稱(chēng)分別是splash和start。我們需要?jiǎng)?chuàng)建兩個(gè) CSprite 類(lèi)對(duì)象與這兩個(gè)精靈綁定。7、 在CGameMain類(lèi)中聲明兩個(gè)CSprite*類(lèi)型,根據(jù)面向?qū)ο蟮姆庋b性原理,成員變量的訪(fǎng)問(wèn)權(quán)限應(yīng) 該是private。代碼應(yīng)該寫(xiě)在哪個(gè)文件,請(qǐng)參看前面的實(shí)驗(yàn)步驟。CSprite* m_pSplash;CSprite* m_pStar
7、t;在CGameMain類(lèi)的構(gòu)造函數(shù)中,對(duì)上面兩個(gè)指針變量進(jìn)行初始化。通過(guò)調(diào)用CSprite的構(gòu)造函數(shù), 將精靈和精力對(duì)象綁定在一起。m_pSplash= new CSprite(splash); m_pStart= new CSprite(start);8、最后,我們?cè)?CGameMai n: :O nKeyDown函數(shù)中處理空格鍵按下事件。if( 0 =GetGameState()if(iKey =KEY_SPACE)mGameState = 1;KEY_SPAC是枚舉變量 KeyCodes的成員,表示空格鍵。 KeyCodes定義在文件中。該枚舉變量定 義了全部的鍵盤(pán)值。 注意:必須將m
8、GameState的值改為1。當(dāng)GameMainLoop函數(shù)再次執(zhí)行時(shí), 根據(jù)mGameState的值調(diào)用并執(zhí)行 Gamelnit函數(shù),游戲進(jìn)入開(kāi)始狀態(tài)。進(jìn)入游戲開(kāi)始狀態(tài)時(shí),調(diào)用CSprite類(lèi)的SetSpriteVisible函數(shù)將精靈圖片設(shè)置為不可見(jiàn)。在Gamelnit函數(shù)中添加代碼:m_pSplash-SetSpriteVisible(false); m_pStart-SetSpriteVisible(false);9、 程序執(zhí)行完 CGameMain:Gamelnit 函數(shù)后,執(zhí)行 CGameMain: SetGameState(2),將 mGameState的值改為2,游戲進(jìn)入運(yùn)行狀
9、態(tài)。10、 在CGameMain類(lèi)的析構(gòu)函數(shù)中delete本實(shí)驗(yàn)創(chuàng)建的指針對(duì)象,以釋放分配的內(nèi)存。CGameMain:CGameMain()delete m_pSplash;delete m_pStart;11、編譯并運(yùn)行程序,然后按下空格鍵,看看運(yùn)行效果。實(shí)驗(yàn)二坦克運(yùn)動(dòng)【實(shí)驗(yàn)內(nèi)容】1、創(chuàng)建坦克類(lèi)CTankPlayer ;2、游戲開(kāi)始時(shí),將坦克放置于 (0,0)的坐標(biāo)上;3、通過(guò)按鍵 WSA控制坦克上下左右運(yùn)動(dòng);4、坦克運(yùn)行到黑色區(qū)域邊界時(shí)不能繼續(xù)前進(jìn)?!緦?shí)驗(yàn)運(yùn)行結(jié)果】在區(qū)域內(nèi)運(yùn)動(dòng)運(yùn)動(dòng)到區(qū)域邊界【實(shí)驗(yàn)思路】坦克也是精靈,但是它具備一些自己獨(dú)特的功能,比如通過(guò)鍵盤(pán)控制運(yùn)動(dòng)、開(kāi)炮等。因此我們可以
10、創(chuàng)建一個(gè)新的類(lèi) CTankPlayer類(lèi),并讓它繼承 CSprite類(lèi)。通過(guò)WAS鍵,控制坦克做相應(yīng)的的上左下右運(yùn)動(dòng)。按下某個(gè)鍵,給坦克設(shè)置相應(yīng)方向的運(yùn)動(dòng)速度; 松開(kāi)時(shí),將該方向的速度設(shè)為0,表示停止運(yùn)動(dòng)。屏幕上最內(nèi)部的黑色區(qū)域?yàn)橥婕姨箍说幕顒?dòng)區(qū)域,左上角坐標(biāo)為(-26,-22),右下角坐標(biāo)為(26,22)。當(dāng)坦克運(yùn)動(dòng)到該區(qū)域邊界時(shí),坦克不能繼續(xù)前進(jìn)。【實(shí)驗(yàn)指導(dǎo)】1、通過(guò)類(lèi)向?qū)?chuàng)建 CTankPlayer類(lèi),其繼承于 CSprite類(lèi)。以VC+為例:第一步、點(diǎn)擊菜單“插入”-“新建類(lèi)”。第二步、在“ New Class ”對(duì)話(huà)框中輸入類(lèi)名和父類(lèi)名。第三步、點(diǎn)擊“ Change按鈕,在新對(duì)話(huà)框中
11、修改CTankPlayer類(lèi)的頭文件和cpp文件的路徑。將頭文件保存到項(xiàng)目文件夾的SourceCodeHeader 文件夾中,將 cpp文件保存到項(xiàng)目文件夾下的SourceCodeSrc 文件夾中。這里需要特別注意的是創(chuàng)建文件路徑的問(wèn)題,所有的.h頭文件應(yīng)該在項(xiàng)目文件夾 SourceCodeHeader 中,所有的.cpp源文件應(yīng)該放在項(xiàng)目文件夾下的 SourceCodeSrc 文件夾 中。2、為CTankPlayer類(lèi)添加 mDir,m_fSpeedX,m_fSpeedY , mHp四個(gè)成員變量(成員變量。用來(lái)表示坦克在 X軸和Y軸方向上的速度以及運(yùn)行的方向,并且在構(gòu)造函數(shù)中初始化為0。這里
12、規(guī)定,mDir的值為0、1、2、3,分別表示上、右、下、左。成員函數(shù)的聲明和定義如何添加,訪(fǎng)問(wèn)權(quán)限是什么,可參考實(shí)驗(yàn)一,下文不再繼續(xù)提示),分別表示運(yùn)動(dòng)方向、X軸、Y軸速度以及血量值。 本文檔的命名采用匈牙利命名法,m_表示類(lèi)成員變量,i表示整型,f表示float型,sz表示字符指針,g_表示全局變量等。同時(shí)需要在public權(quán)限下定義獲取和設(shè)置這些變量的Get和Set方法:/set方法void SetHp(i nt hp)mHp = hp;void SetDir(i nt dir)m_iDir = dir;void SetSpeedX(float speedX)m_fSpeedX = spe
13、edX;void SetSpeedY(float speedY)m_fSpeedY = speedY;/get方法int GetHp()return mHp;int GetDir()return mDir;float GetSpeedX()return m fSpeedX;float GetSpeedY()return m_fSpeedY;3、 CTankPlayer 的父類(lèi)是 CSprite 類(lèi)(具體聲明查看),構(gòu)造函數(shù)為 CSprite( const char *szName )。4、 所以通過(guò)上邊方法自動(dòng)生成的類(lèi),如果系統(tǒng)自動(dòng)生成構(gòu)造函數(shù) CTa nkPlayer(void),刪除掉它以
14、 及在中自動(dòng)生成的對(duì)構(gòu)造函數(shù)實(shí)現(xiàn)的代碼:CTa nkPlayer:CTa nkPlayer(void)再為 CTankPlayer 類(lèi)添加新的構(gòu)造函數(shù):|CTankPlayer(const char* szName)。CTa nkPlayer:CTa nkPlayer(co nst char* szName):CSprite(szName) /對(duì)構(gòu)造函數(shù)進(jìn)行實(shí)現(xiàn)mDir=0; m fSpeedX=; m_fSpeedY=;mHp=2;|子類(lèi)對(duì)象創(chuàng)建時(shí),要先調(diào)用父類(lèi)的構(gòu)造函數(shù)完成父類(lèi)部分的構(gòu)造。如果父類(lèi)沒(méi)有默認(rèn)構(gòu)造函數(shù), 子類(lèi)的構(gòu)造函數(shù)必須顯示調(diào)用父類(lèi)的構(gòu)造函數(shù)。CTankPlayer構(gòu)造函數(shù)調(diào)
15、用CSprite類(lèi)構(gòu)造函數(shù),并將參數(shù)szName的值傳遞給它,從而將名稱(chēng)為szName的精靈圖片與CTankPlayer對(duì)象綁定起來(lái)。5、 為CTa nkPlayer類(lèi)添加In it函數(shù),該函數(shù)主要用來(lái)完成該類(lèi)的初始化工作。這里,先調(diào)用setHp方法設(shè)置血量。然后調(diào)用父類(lèi)的SetSpritePosition函數(shù)將坦克精靈設(shè)置在屏幕中央(0,0)處。接下來(lái)給坦克精靈設(shè)置時(shí)間邊界的大小,與世界邊界的碰撞模式為WORLD_LIMIT_NULL表示精靈與世界邊界碰撞的響應(yīng)由代碼完成,同時(shí)設(shè)置坦克碰撞模式為發(fā)送碰撞和接收碰撞。void CTa nkPlayer:l ni t()SetHp(2);SetS
16、pritePositio n,;SetSpriteWorldLimit(WORLD_LIMIT_NULL, -26, -22, 26, 22);SetSpriteCollisio nActive(1,1);設(shè)置為可以接受和發(fā)生碰撞SetSpriteVisible(true);6、 在CGameMain類(lèi)中增加一個(gè)私有成員變量m_pTankplayer,類(lèi)型為 CTankPlayer* 。注意在添加頭文件:#i nclude7、 按下空格鍵后, 程序會(huì)調(diào)用鍵盤(pán)按下事件響應(yīng)函數(shù),將mGameState的值改為1,游戲進(jìn)入開(kāi)始狀態(tài)(見(jiàn)實(shí)驗(yàn)一)。程序再次執(zhí)行 CGameMain:GameMainLoo
17、p函數(shù)時(shí),根據(jù)mGameState的值調(diào) 用并執(zhí)行CGameMai n:Gamel nit函數(shù)。因此,可以在該函數(shù)中創(chuàng)建我方坦克,并調(diào)用 CTa nkPlayer:l nit函數(shù)來(lái)完成該類(lèi)對(duì)象的初始化工作。m_pTankPlayer= new CTankPlayer(myplayer);新建一個(gè)名字是 myPlayer 的我方坦克對(duì)象m_pTa nkPlayer-Clo neSprite(player);我方坦克克隆在 fun code模板中存在的名字為 player的坦克,表示新建的坦克對(duì)象有現(xiàn)在精靈的所有屬性m_pTa nkPlayer-l nit();&接下來(lái),我們?yōu)?CTan kPla
18、yer類(lèi)添加On Move函數(shù),參數(shù)iKey、bPress分別表示按下的是哪個(gè)按鍵和按鍵是否按下。首先聲明該函數(shù),訪(fǎng)問(wèn)權(quán)限為public :void OnMove(int iKey, bool bPress);9、接著,完成 OnMove方法。void CTankPlayer:OnMove(int iKey, bool bPress) switch (iKey)case KEY_W:SetDir(O);SetSpeedX(O);SetSpeedY(-8);case KEY_D: SetDir(1);SetSpeedX(8);SetSpeedY(O);break;case KEY S:SetDi
19、r(2);SetSpeedX(O);SetSpeedY(8);break;case KEY A:SetDir(3);SetSpeedX(-8);SetSpeedY(O);break;SetSpriteRotation(float(90*GetDir(); /用方向值乘于 90得到精靈旋轉(zhuǎn)度數(shù)SetSpriteLi nearVelocity(GetSpeedX(),GetSpeedY(); else if(iKey = KEY W | iKey = KEY D | iKey = KEY S | iKey = KEY A)SetSpeedX(0);SetSpeedY(0);SetSpriteLi
20、nearVelocity(GetSpeedX(),GetSpeedY();用參數(shù)bPress來(lái)判斷鍵盤(pán)是按下還是彈起。如果bPress為false,表示鍵盤(pán)彈起,且彈起的鍵是WASD1時(shí),設(shè)置坦克的 X軸和Y軸移動(dòng)速度都為0。如果bPress為true,表示鍵盤(pán)按下,根 據(jù)按下 的鍵,為 mDir,m_fSpeedX,m_fSpeedY 賦予相應(yīng) 的值。SetSpriteRotation和SetSpriteL in earVelocity函數(shù)用來(lái)設(shè)置精靈的角度和線(xiàn)性速度,具體含義參考文件。10、 在CGameMain類(lèi)的OnKeyDowr函數(shù)中,通過(guò)調(diào)用 CTankPlayer類(lèi)的OnMove
21、方法,根據(jù)按下的鍵, 控制坦克朝指定方向運(yùn)動(dòng)。只有游戲進(jìn)入開(kāi)始狀態(tài),按鍵才有效。注意:OnMove參數(shù)bPress的 值為true。在OnKeyDown函數(shù)中添加代碼如下:if(mGameState = 2)m_pTankPlayer-OnMove(iKey, true);11、 編譯并運(yùn)行程序。按空格鍵開(kāi)始,按WASDi,坦克會(huì)向規(guī)定的方向運(yùn)動(dòng)。但是松開(kāi)按鍵后,坦 克繼續(xù)前進(jìn),不會(huì)停止下來(lái)。12、參考CSystem:OnKeyUp函數(shù),給CGameMain類(lèi)聲明并定義一個(gè) OnKeyUp函數(shù),用來(lái)處理按鍵彈 起事件,然后在 CSystem:OnKeyUp函數(shù)中調(diào)用它。關(guān)于這個(gè)函數(shù)如何聲明、定
22、義以及調(diào)用參考實(shí)驗(yàn)一。13、 在 CGameMain:OnKeyUp函數(shù)中調(diào)用 CTankPlayer 的 OnMove方法,參數(shù) bPress 的值為 false 。 void CGameMain:OnKeyUp(const int iKey)if(m_iGameState = 2)m_pTankPlayer-OnMove(iKey, false);14、 編譯并運(yùn)行程序,按下WASDt,坦克運(yùn)行;松開(kāi)按鍵,坦克停止。接下來(lái),我們來(lái)實(shí)現(xiàn)坦克運(yùn) 行到黑色區(qū)域邊界停止運(yùn)動(dòng)的效果。15、參考 CSystem:O nSpriteColWorldLimit 函數(shù),給 CGameMai n 類(lèi)聲明并定義
23、一個(gè)On SpriteColWorldLimit函數(shù),用來(lái)處理精靈與世界邊界的碰撞事件,然后在CSystem:On SpriteColWorldLimit函數(shù)中調(diào)用它。關(guān)于這個(gè)函數(shù)如何聲明、定義以及調(diào)用參考實(shí)驗(yàn)一。16、 當(dāng)坦克精靈碰到邊界時(shí),將精靈的速度都設(shè)為0,精靈停止運(yùn)動(dòng)。用字符串處理函數(shù) strstr()來(lái)判斷碰到世界邊界的精靈是否為我方坦克。當(dāng)碰到世界邊界的精靈名字中含有” player ”的時(shí)候,strstr 會(huì)返回一個(gè)非空值。因此代碼如下:void CGameMai n:O nSpriteColWorldLimit( con st char *szName, con st int
24、 iColSide )if(strstr(szName,player) != NULL) /判斷碰到世界邊界的坦克是否為我方坦克m_pTa nkPlayer-SetSpriteLi nearVelocity(0,0);|實(shí)驗(yàn)三坦克開(kāi)炮【實(shí)驗(yàn)內(nèi)容】1、創(chuàng)建子彈類(lèi)CBullet ;2、通過(guò)按鍵J控制坦克開(kāi)炮;【實(shí)驗(yàn)運(yùn)行結(jié)果】【實(shí)驗(yàn)思路】創(chuàng)建子彈類(lèi),該類(lèi)應(yīng)具備子彈的運(yùn)動(dòng)方向、起始位置、X軸速度、Y軸速度等屬性,其中運(yùn)動(dòng)方向和起始位置由坦克的方向和位置決定。通過(guò)按鍵控制坦克發(fā)射子彈,因此在CGameMain類(lèi)的OnKeyDown方法中實(shí)現(xiàn)該需求。此時(shí)我們?yōu)镃Ta nkPlayer類(lèi)添加發(fā)射子彈的方法O
25、nFire。當(dāng)按下J鍵后,坦克發(fā)射子彈,在On Fire方法中,我們需要告訴子彈的方向和初始位置。而創(chuàng)建子彈我們由CGameMain類(lèi)來(lái)完成。這樣減少了類(lèi)之間的耦合。【實(shí)驗(yàn)指導(dǎo)】1、通過(guò)類(lèi)向?qū)?chuàng)建 CBullet類(lèi),其繼承于 CSprite類(lèi),具體做法參考實(shí)驗(yàn)一;2、 為CBullet類(lèi)添加 mDir,m_fSpeedX,m_fSpeedY,mHp ,mOwner五個(gè)成員,分別表示方向、X軸、Y軸速度、子彈血量以及發(fā)射子彈歸屬坦克,0表示地方坦克,1表示我方坦克,并參考實(shí)驗(yàn)二添加變量的get和set方法。3、 為CTankPlayer類(lèi)添加構(gòu)造函數(shù)和析構(gòu)函數(shù)。參照實(shí)驗(yàn)二,把構(gòu)造函數(shù)中將所有變量
26、進(jìn)行初始化。4、為CBullet類(lèi)添加On Move方法,參數(shù)為iDir表示子彈的運(yùn)動(dòng)方向。5、完成OnMove方法。根據(jù)方向 mDir,首先設(shè)置 m_fSpeedX,m_fSpeedY的值,然后設(shè)置根據(jù)方向 設(shè)置旋轉(zhuǎn)角度,最后設(shè)置子彈的運(yùn)動(dòng)速度。void CBullet:OnMove(int iDir)SetDir(iDir);switch(GetDir()case 0:SetSpeedX(0);SetSpeedY(-10);break;case 1:SetSpeedX(10);SetSpeedY(0);break;case 2:SetSpeedX(0);SetSpeedY(10);brea
27、k;case 3:SetSpeedX(-10);SetSpeedY(0);break;SetSpriteRotatio n( 90*GetDir(); SetSpriteLi nearVelocity(GetSpeedX(),GetSpeedY();6、在CGameMain類(lèi)中添加表示子彈數(shù)目的成員變量mBulletNum(注意初始化為 0)。然后添加AddBullet 方法。方法中有 iDir、fPosX、fPosY、iOwner四個(gè)參數(shù)分別表示子彈方向、子彈初 始位置的X軸Y軸坐標(biāo)以及子彈所屬坦克。由于地圖上只有一個(gè)子彈模板,所以我們需要先復(fù)制 這個(gè)模板,然后設(shè)置該精靈的世界邊界。void
28、 CGameMain:AddBullet( int iDir,float fPosX,float fPosY ,int iOwner)char* szName = CSystem:MakeSpriteName(bullet,m_iBulletNum);創(chuàng)建坦克名字CBullet* pBullet = new CBullet(szName);pBullet-Clo neSprite(bullet);pBullet-SetSpriteWorldLimit(WORLD LIMIT NULL,-26, -22, 26, 22); /設(shè)置世界邊界pBullet-SetSpritePositio n(fP
29、osX,fPosY);pBullet-SetSpriteCollisio nSe nd(true); /設(shè)置接收碰撞pBullet- OnM ove(iDir);mBulletNum+; /子彈個(gè)數(shù)加 1if(iOw ner = 1)pBullet-SetOw ner;/1表示我方坦克發(fā)射的子彈 elsepBullet-SetOw ner(O); 0表示地方坦克發(fā)射的子彈7、為CTa nkPlayer類(lèi)增加On Fire方法,實(shí)現(xiàn)發(fā)射子彈的功能。在根據(jù)坦克的運(yùn)動(dòng)狀態(tài),得到子彈 的相關(guān)屬性后,通過(guò)AddBullet方法在游戲中增加一發(fā)子彈。void CTa nkPlayer:O nF ire()
30、float x,y;x = GetSpritePositio nX();y = GetSpritePositio nY();switch(GetDir()case 0:y=y-GetSpriteHeight()/2-1;break;case 1:x=x+GetSpriteWidth()/2+1;break;case 2:y=y+GetSpriteHeight()/2+1;break; case 3:x=x-GetSpriteWidth()/2-1;break;(GetDir(),x,y,1);因?yàn)橛玫絞_GameMain這個(gè)全局對(duì)象,所以需要在中聲明頭文件:#include ”8、按 J 鍵發(fā)
31、射子彈。在 CGameMair類(lèi)的 OnKeyDown函數(shù) if(m_iGameState = 2) 下添加 i f(iKey =KEY_J)/判斷按下鍵是夠?yàn)?J鍵m_pTa nkPlayer-OnFire();實(shí)驗(yàn)四敵方坦克【實(shí)驗(yàn)內(nèi)容】1、創(chuàng)建 CTankEnemy類(lèi);2、創(chuàng)建一個(gè)敵方坦克實(shí)例,實(shí)現(xiàn)坦克從上方左中右三個(gè)位置隨機(jī)出現(xiàn)。3、實(shí)現(xiàn)坦克隔2秒,隨機(jī)改變一個(gè)方向。4、實(shí)現(xiàn)坦克隔5秒發(fā)射一發(fā)子彈;5、當(dāng)坦克與世界邊界碰撞時(shí),改變方向;【實(shí)驗(yàn)運(yùn)行結(jié)果】【實(shí)驗(yàn)思路】同我方坦克一樣,敵方坦克運(yùn)動(dòng),也需要有運(yùn)動(dòng)方向、X軸Y軸速度三個(gè)基本屬性。為了實(shí)現(xiàn)坦克能自由運(yùn)動(dòng),即坦克運(yùn)動(dòng)一段時(shí)間后改變方向
32、,需增加一個(gè)改變方向的時(shí)間間隔。同時(shí)為了實(shí)現(xiàn)坦克自動(dòng) 發(fā)射子彈,需增加一個(gè)發(fā)射子彈的時(shí)間間隔。然后為敵方坦克增加移動(dòng)和發(fā)射子彈的方法。最后我們?cè)贑GameMair類(lèi)的GameRun方法中調(diào)用敵方坦克移動(dòng)和發(fā)射子彈的方法?!緦?shí)驗(yàn)指導(dǎo)】1、通過(guò)類(lèi)向?qū)?chuàng)建 CTa nkEn emy類(lèi);2、 為類(lèi) CTankEnemy添加 mDir,m_fSpeedX,m_fSpeedY,mHp 四個(gè)成員,分別表示方向、X軸、Y 軸速度和血量;3、參照前面的實(shí)驗(yàn),為 CTa nkE nemy類(lèi)添加構(gòu)造函數(shù)和析構(gòu)函數(shù)。4、 為類(lèi)CTankEnemy添加Init方法初始化敵方坦克。設(shè)置血量為2,位置坐標(biāo)為上方左中右的隨機(jī)
33、位置,然后函數(shù)中給坦克精靈設(shè)置時(shí)間邊界的大小,與世界邊界的碰撞模式為 WORLD_LIMIT_NULL表示精靈與世界邊界碰撞的響應(yīng)由代碼完成。最后設(shè)置方向和速度代碼如下:int iPos = CSystem:Ra ndomRa nge(0,2);float fPosX;SetDir(2);SetHp(2); switch (iPos )case 0:SetSpritePositio n( fPosX,;SetSpriteL in earVelocity,;SetSpriteCollisio nActive(1,1); /設(shè)置可以接受和發(fā)送碰撞SetSpriteRotatio n(float(9
34、0*GetDir();SetSpriteWorldLimit(WORLD_LIMIT_NULL,-26, -22, 26, 22);5、為類(lèi)CTankEnemy添加OnMove方法,實(shí)現(xiàn)坦克順時(shí)針旋轉(zhuǎn)90度運(yùn)動(dòng)。然后根據(jù)方向設(shè)置子彈的運(yùn)動(dòng)速度m_fSpeedX,m_fSpeedY的值。與 CTan kPlayer類(lèi)的On Move方法類(lèi)似。設(shè)置速度方向與原來(lái)方向旋轉(zhuǎn)90度的代碼如下:int iDir=0;if(GetDir()=0 | GetDir()=1 | GetDir()=2)iDir = GetDir()+1;Else /如果方向值等于3,設(shè)為0通過(guò)方向設(shè)置速度參考前邊實(shí)驗(yàn)。6、 為類(lèi)
35、CTa nkEn emy添加帶參的On Move方法,參數(shù)fDeltaTime ,為游戲的時(shí)間差,實(shí)現(xiàn)隔一段時(shí)間隨機(jī)改變方向。在 CTankEnemy類(lèi)中添加成員變量 m_fChangeDirTime在構(gòu)造函數(shù)中初始化為0,并添加get和set方法。void CTa nkEn emy:O nM ove(float fDeltaTime)m fCha ngeDirTime+=fDeltaTime;if(m_fCha ngeDirTimeOnM ove();m_fCha ngeDirTime =;|7、 為類(lèi)CTa nkEnemy添加On Fire方法,參數(shù)也為 fDeltaTime,實(shí)現(xiàn)隔一段時(shí)
36、間自動(dòng)發(fā)射子彈。在 CTankEnemy類(lèi)中添加成員 m_fBulletCreateTime 變量并在構(gòu)造函數(shù)中初始化為0。void CTa nkE nemy:O nFire(float fDeltaTime)m fBulletCreateTime+=fDeltaTime;if(m_fBulletCreateTimem fBulletCreateTime =;float x,y;x = GetSpritePositio nX();y = GetSpritePositio nY();switch(GetDir()case 0:y=y-GetSpriteHeight()/2-1;break;cas
37、e 1:x=x+GetSpriteWidth()/2+1;break;case 2:y=y+GetSpriteHeight()/2+1;break;case 3:x=x-GetSpriteWidth()/2-1;break; (GetDir(),x,y,O); 因?yàn)橛玫饺謱?duì)象 G_GameMain所以需要在中聲明頭文件:#i nclude8、在CGameMair類(lèi)中添加CTankEnemy類(lèi)指針變量m_pTankEnemy注意在中聲明頭文件:#i nclude然后在Game In it中創(chuàng)建并初始化。m_pTa nkEn emy = new CTa nkEn emy(e nemy); m_p
38、Ta nkEn emy-I nit();9、在CGameMair類(lèi)的GameRun方法中實(shí)現(xiàn)敵方坦克自由移動(dòng)和發(fā)射子彈。void CGameMai n:GameRu n( float fDeltaTime )if(m_pTa nkEn emy) m pTa nkEn emy- OnM ove(fDeltaTime); m_pTa nkEn emy- On Fire(fDeltaTime); 10、 在CGameMair類(lèi)的OnSpriteColWorldLimit方法中添加敵方坦克與世界邊界碰撞的檢測(cè)。 if(m_pTa nkEnemy&strcmp(m_pTa nkEn emy-GetNam
39、e(),szName)=0) m_pTa nkEn emy-OnMove();實(shí)驗(yàn)五加載地圖【實(shí)驗(yàn)內(nèi)容】1、加載游戲地圖;【實(shí)驗(yàn)運(yùn)行結(jié)果】 【實(shí)驗(yàn)思路】在CGameMain類(lèi)中添加方法LoadMap實(shí)現(xiàn)地圖加載。地圖數(shù)據(jù)是已知的,數(shù)據(jù)中的0表示此處為空;1表示的是地圖中此處為墻;2表示此處為玩家指揮部。每塊墻大小為 4*4。【實(shí)驗(yàn)指導(dǎo)】1、首先在中定義一個(gè)表示地圖的二維數(shù)組來(lái)表示地圖,其中0表示沒(méi)有墻塊,1表示有墻塊:in t g_i Map1113=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,
40、0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0, 0,0,0,0,0,1,0,1,0,0,0,0,0;2、在CGameMain類(lèi)中添加LoadMap方法,實(shí)現(xiàn)加載地圖。在方法中用for循環(huán)遍歷地圖二維數(shù)組,當(dāng)二維數(shù)組中的某個(gè)值為1時(shí)表示該處是一堵墻。void CGameM
41、ai n:LoadMap()char* szName;int i,j;float x,y;for(i=0;i11;i+)for(j=0;jClo neSprite(wall); /克隆墻塊pWall-SetSpriteCollisionActive(0,1); /設(shè)置為接受碰撞pWall-SetSpriteCollisio nRespo nse(COL_RESPONSE_CUSTOM); x =float(-24+4*j);y =float(-20+4*i); pWall-SetSpritePositio n(x,y);|3、在GameInit中調(diào)用加載地圖的函數(shù):LoadMap(); |實(shí)驗(yàn)
42、六創(chuàng)建父類(lèi)-CWeapor類(lèi)【實(shí)驗(yàn)內(nèi)容】1、添加 CWeapon類(lèi),使 CBullet、CTankPlayer、CTankEnemy類(lèi)繼承 CWeapor類(lèi)。2、將三個(gè)子類(lèi) OnFire和On Move方法中相同的功能抽取出來(lái),在父類(lèi)中創(chuàng)建相應(yīng)方法。子類(lèi)調(diào)用父 類(lèi)方法進(jìn)行改進(jìn)。3、創(chuàng)建一個(gè)容器,用來(lái)存放所有精靈?!緦?shí)驗(yàn)運(yùn)行結(jié)果】【實(shí)驗(yàn)思路】1、CBullet、CTankPlayer、CTankEnemy類(lèi)中有許多共同的屬性和方法,或者為了方便管理,我們添加 父類(lèi) CWeapon2、把所有創(chuàng)建的精靈存入到容器中,增加從容器中查找和刪除精靈的函數(shù)。在此基礎(chǔ)上,對(duì)整個(gè)項(xiàng)目 進(jìn)行大改。注意此步驟對(duì)于下
43、方實(shí)驗(yàn)非常重要,需要理解繼承的用法,根據(jù)自己的理解把該刪除和更改的地方 做好。此實(shí)驗(yàn)會(huì)創(chuàng)建一個(gè)包含內(nèi)容為CWeapo n*的容器,把創(chuàng)建的我方坦克,敵方坦克,墻塊,子彈,全部存入到這個(gè)容器中進(jìn)行管理?!緦?shí)驗(yàn)指導(dǎo)】1、通過(guò)類(lèi)向?qū)砑?CWeapor類(lèi),其繼承于 CSprite類(lèi)。2、 根據(jù)分析為CWeapon類(lèi)添加表示方向、血量、X軸Y軸速度、四個(gè)變量。int mDir;int mHp;float m fSpeedX;float m_fSpeedY;添加get和set方法;3、 仿照前面的實(shí)驗(yàn)添加構(gòu)造函數(shù),在構(gòu)造函數(shù)中對(duì)這些數(shù)值初始化,其中mHp初始化為2,其他 初始化為0;4、添加函數(shù)以及虛函
44、數(shù):bool IsDead(); /判斷精靈是否死亡virtual void Ini t(); /初始化函數(shù)virtual void OnM ove(float fDeltaTime); /敵方坦克移動(dòng)函數(shù)virtual void On Move();virtual void On Fire(float deltaTime); /發(fā)射子彈函數(shù)virtual void On SpriteColSprite(CWeapo n* pSprite); /精靈與精靈碰撞時(shí)處理函數(shù)在CWeapor類(lèi)中實(shí)現(xiàn)lsDead()函數(shù),此函數(shù)的作用是判斷精靈是否死亡,在游戲運(yùn)行時(shí),會(huì)根 據(jù)這個(gè)函數(shù)的返回值來(lái)確定是否
45、此精靈:boolCWeapo n:lsDead()if(mHp = 0)return true;return false;5、 將 CBullet、CTankPlayer、CTankEnemy類(lèi)的父類(lèi)改為 CWeapon 例如在中把 class CTankPlayer :public CSprite改為 class CTankPlayer :public CWeapon注意需要、包含頭文件:#i nclude6、 注意同時(shí)修改構(gòu)造函數(shù)。把繼承類(lèi)的名稱(chēng)由CSprite改為Cweapon刪除與CWeapon定義重復(fù)的變量聲明,原來(lái)的get和set方法,以及在構(gòu)造函數(shù)中對(duì)這些變量賦初值的代碼。特別主
46、要要設(shè)置Hp=27、 在CGameMain類(lèi)中添加一個(gè)成員變量m_vWeapon用來(lái)存儲(chǔ)所有精靈:vectorvCWeap on* m_vWeap on;注意用到容器,添加頭文件聲明和命名空間:#in clude using n amespace std;&然后聲明和定義查找和刪除容器成員的兩個(gè)函數(shù)FindWeaponByNam訓(xùn)DeleteWeaponByNameCWeapo n* CGameMai n:Fi ndWeapo nByName(c on st char* szName)/根據(jù)名字查找到對(duì)象for(i nt i=0; iGetName() = 0)retur n m_vWeap
47、on i;|void CGameMai n:DeleteWeapo nByName(co nst char* szName)/根據(jù)名字把精靈從容器中刪除for(vector:iterator it=();it!=();)CWeap on* cw =*it;if(strcmp(szName,cw-GetName() = 0)(it);cw-DeleteSprite();delete cw;break;elseit+;|9、在前邊創(chuàng)建子彈、我方坦克、以及地圖的地方用()函數(shù)把精靈添加到容器中。1) 我方精靈添加容器中方法為,在GameInit()函數(shù)中創(chuàng)建我方坦克的代碼:m_pTa nkPlaye
48、r =new CTan kPlayer(myplayer);m_pTa nkPlayer-Clo neSprite(player);m_pTa nkPlayer-In it();下邊添加如下代碼:(m_pTa nkPlayer);2) 子彈添加到容器,在AddBullet函數(shù)最后添加一行代碼:(pBullet); |3) 地圖添加容器,在 LoadMap()函數(shù)中,把 CSprite* pWall = new CSprite(szName); 改為: CWeapo n* pWall = new CWeap on (szName);然后在 pWall-SetSpritePosition(x,y)
49、;下添加:(pWall);實(shí)驗(yàn)七游戲整體正常運(yùn)行【實(shí)驗(yàn)內(nèi)容】1、 創(chuàng)建敵方坦克每隔5秒出現(xiàn)一輛,從屏幕上方的左、中、右三個(gè)位置隨機(jī)出現(xiàn)。2、當(dāng)子彈與游戲中的任何東西碰撞時(shí),雙方都消失;3、當(dāng)我方坦克與敵方坦克碰撞時(shí),我方坦克靜止不動(dòng),敵方坦克改變方向;4、當(dāng)我方坦克被消滅或者我方軍營(yíng)被擊中時(shí),游戲結(jié)束?!緦?shí)驗(yàn)運(yùn)行結(jié)果】【實(shí)驗(yàn)思路】3、創(chuàng)建一個(gè)函數(shù)生成坦克的函數(shù)產(chǎn)生坦克。4、 在OnSpriteColSprite方法中添加碰撞檢測(cè)。5、 更改在OnSpriteColWorldLimit中與世界邊界的碰撞檢測(cè)。【實(shí)驗(yàn)指導(dǎo)】1、注釋掉實(shí)驗(yàn)四中,在 CGameMai類(lèi)中添加的聲明和創(chuàng)建一個(gè)敵方坦克對(duì)象
50、的代碼。中:/CTankEn emy* m_pTa nkEn emy; 在文件GameInit函數(shù):m_pTankEn emy = new CTa nkEn emy(e nemy);m_pTankEn emy-I nit();同時(shí)注釋在 GameRur函數(shù)中添加的使敵方坦克運(yùn)動(dòng)的代碼。/*if(m_pTa nkEn emy)m_pTa nkEn emy- OnMo ve(fDeltaTime);m_pTa nkEn emy- On Fire(fDeltaTime);*/2、 在CGameMai中創(chuàng)建一個(gè)不斷產(chǎn)生地方坦克的函數(shù)AddTankEnemy先在 CGameMai中添加一個(gè)成員變量 m_
51、fTankEnemyTime和m_iTankEnemyNumber分別代表創(chuàng)建坦克時(shí)間,以及坦克數(shù)量(注意將兩數(shù)進(jìn)行初始化)。當(dāng)時(shí)間m_fTankEnemyTime大于5時(shí),創(chuàng)建敵方坦克,設(shè)置屬性,并進(jìn)行調(diào)用初始化函數(shù)init來(lái)設(shè)置敵方坦克的初始位置以及碰撞模式等內(nèi)容。voidCGameMai n:AddTa nkE nemy(float fDeltaTime)m fTa nkEn emyTime += fDeltaTime;if(m_fTa nkEn emyTime 5)char* szName = CSystem:MakeSpriteName(e nemy,m_iTa nkEn emyNu
52、mber);CTankEn emy* m pTa nkEn emy = new CTa nkEn emy(szName);m pTa nkEn emy-Clo neSprite(e nemy);m_pTa nkEn emy-I nit(); m_iTa nkEn emyNumber+;(m_pTa nkEn emy); /把創(chuàng)建的敵方坦克插入到容器中m fTa nkEn emyTime=; 在CGameMain類(lèi)的GameRun函數(shù)中調(diào)用增加敵方坦克的函數(shù):AddTa nkE nemy(fDeltaTime);此時(shí)運(yùn)行游戲可以看到,每五秒有一輛敵方坦克從下方隨機(jī)生成并向下運(yùn)動(dòng)。3、在GameRur中添加代碼遍歷容器,調(diào)用精靈移動(dòng)以及發(fā)射函數(shù)(子彈和墻沒(méi)有對(duì)這兩個(gè)函數(shù)進(jìn)行實(shí)現(xiàn),因此不會(huì)產(chǎn)生效果),把已死亡的精靈進(jìn)行刪除,使游戲運(yùn)行正常。for(int i=0;ilsDead()m_vWeapo ni- OnM ove(fDeltaTime);m_vWeapo ni-O nF ire(fDeltaTime);elseDeleteWeapo nByName(m vWeapo ni-GetName();4、 更改精靈世界邊界碰撞時(shí)間函數(shù)中的代碼,更改判斷敵方坦克與世界邊界碰撞和子彈與世界邊界碰撞的代碼:else if(strstr
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 機(jī)床設(shè)備銷(xiāo)售合同
- 電玩城裝修合同模板
- 皮革廠(chǎng)翻新合同
- 2025年合同能源管理項(xiàng)目投資分析及可行性報(bào)告
- 2025版信托投資公司人民幣外匯互換交易合同3篇
- 高級(jí)健身俱樂(lè)部會(huì)員權(quán)益與責(zé)任義務(wù)明確合同
- 節(jié)能環(huán)保技術(shù)設(shè)備采購(gòu)與銷(xiāo)售合同
- 2025年度特色商業(yè)街區(qū)商鋪?zhàn)赓U與社區(qū)服務(wù)合同
- 二零二五年度綠化工程生態(tài)保護(hù)與恢復(fù)分包合同
- 2025年度城市軌道交通項(xiàng)目連帶責(zé)任擔(dān)保借款合同
- 化學(xué)-河南省TOP二十名校2025屆高三調(diào)研考試(三)試題和答案
- 智慧農(nóng)貿(mào)批發(fā)市場(chǎng)平臺(tái)規(guī)劃建設(shè)方案
- 小學(xué)數(shù)學(xué)分?jǐn)?shù)四則混合運(yùn)算300題帶答案
- 林下野雞養(yǎng)殖建設(shè)項(xiàng)目可行性研究報(bào)告
- 2023年水利部黃河水利委員會(huì)招聘考試真題
- Python編程基礎(chǔ)(項(xiàng)目式微課版)教案22
- 01J925-1壓型鋼板、夾芯板屋面及墻體建筑構(gòu)造
- 欠電費(fèi)合同范本
- 2024年新高考地區(qū)數(shù)學(xué)選擇題填空壓軸題匯編十八含解析
- 大型商場(chǎng)招商招租方案(2篇)
- 2022年袋鼠數(shù)學(xué)競(jìng)賽真題一二年級(jí)組含答案
評(píng)論
0/150
提交評(píng)論