C++实战项目:坦克大战(七)

  目前我们的主战坦克已经能够开炮击毁敌人坦克了,但敌人坦克不会开炮貌似比较欺负人。今天我们让敌人坦克也拥有开炮功能。同时,我们要为游戏设定关卡,让它变得好玩起来。

  让敌人坦克开炮

  在EnemyTank类中,添加Shoot函数几乎和MainTank中完全相同,代码如下:

C++代码
  1. void EnemyTank::Shoot(list<Object*>& lstBullets)  
  2. {  
  3.     Bullet* pBullet = new Bullet(m_pos, m_dir, m_color);    
  4.     lstBullets.push_back(pBullet);    
  5.     m_bNeedShoot = false;  
  6. }  

  这里唯一的区别是最后一句话,我们对m_bNeedShoot属性进行了赋值。

  敌人坦克和主战坦克最大的区别在于自动开炮,它不像主战坦克那样通过相应空格键执行开炮函数,它是通过一定的算法完成自主开炮。因此我们在main函数中通过判断m_bNeedShoot属性来执行Shoot函数。

  在Move函数中,我们添加下面这段代码:

C++代码
  1. if (m_stepCnt % MAX_STEP_SHOOT == 0)  
  2. {  
  3.     m_bNeedShoot = true;  
  4. }  

  这段代码有点类似于敌人坦克的自动转向功能,我们让它每移动MAX_STEP_SHOOT步就通过将m_bNeedShoot设为true来执行开炮功能。

  最后,我们在main函数中绘制坦克时加入下面这段代码:

C++代码
  1. if ((*it)->NeedShoot())  
  2. {  
  3.     EnemyTank* p = (EnemyTank*)*it;  
  4.     p->Shoot(lstBullets);  
  5. }  

  当判断NeedShoot()返回值为true时,调用Shoot()函数进行开炮。

  关卡设置

  我们在玩游戏时,有一些必要的参数非常重要。比如,主要人物的生命值,等级,敌人数,分数等等。下面我们就给坦克大战中添加这些元素,让它变得更有游戏的乐趣。

  我们为工程添加一组新的文件Setting.h和Setting.cpp,代码如下:

  Setting.h

C++代码
  1. #ifndef __SETTING_H__  
  2. #define __SETTING_H__  
  3.   
  4. #include <list>  
  5.   
  6. using namespace std;  
  7.   
  8. class Setting  
  9. {  
  10. public:  
  11.     static void NewGameLevel();  
  12.     static void TankDamaged();  
  13.   
  14.     static int GetLife()  
  15.     {  
  16.         return m_nLife;  
  17.     }  
  18.   
  19.     static int GetGameLevel()  
  20.     {  
  21.         return m_nGameLevel;  
  22.     }  
  23.   
  24.     static int GetTankLevel()  
  25.     {  
  26.         return m_nTankLevel;  
  27.     }  
  28.   
  29.     static int GetTankNum()  
  30.     {  
  31.         return m_nTankNum;  
  32.     }  
  33.   
  34.     static int GetSumScore()  
  35.     {  
  36.         return m_nSumScore;  
  37.     }  
  38.   
  39.     static int GetTankSum()  
  40.     {  
  41.         return m_nTankSum;  
  42.     }  
  43.   
  44.     static bool m_bNewLevel;  
  45.   
  46. private:  
  47.     static int m_nLife; // 生命值  
  48.   
  49.     static int m_nGameLevel;    // 当前游戏关卡  
  50.     static int m_nTankLevel;    // 当前坦克级别  
  51.   
  52.     static int m_nTankNum;        // 当前坦克数  
  53.   
  54.     static int m_nSumScore;        // 总分  
  55.   
  56.     static int m_nTankScore;    // 击毁坦克得分  
  57.   
  58.     static int m_nTankSum;        // 共击毁坦克数  
  59. };  
  60.   
  61. #endif 

  在Setting类中,我们添加了一组static属性。同时,添加了访问这些参数的static接口。这里重点关注两个函数:

  NewGameLevel()函数,在每一关开始时初始化每一关的属性信息。TankDamaged()函数,在每次击毁一个坦克时调用,完成相关属性的数据更新。具体如下:

  Setting.cpp

  include "Setting.h"

C++代码
  1. bool Setting::m_bNewLevel = true;  
  2.   
  3. int Setting::m_nLife = 3;  
  4.   
  5. int Setting::m_nGameLevel = 0;  
  6. int Setting::m_nTankLevel = 1;  
  7.   
  8. int Setting::m_nTankNum = 5;  
  9.   
  10. int Setting::m_nSumScore = 0;  
  11.   
  12. int Setting::m_nTankScore = 5;  
  13.   
  14. int Setting::m_nTankSum = 0;  
  15.   
  16. void Setting::NewGameLevel()  
  17. {  
  18.     m_nGameLevel++;  
  19.   
  20.     m_nTankNum = 10 + 5 * (m_nGameLevel - 1);  
  21.     m_nTankScore += 5;  
  22. }  
  23.   
  24. void Setting::TankDamaged()  
  25. {  
  26.     m_nTankNum--;  
  27.     m_nSumScore += m_nTankScore;  
  28.   
  29.     m_nTankLevel = m_nSumScore / 150 + 1;  
  30.   
  31.     m_nTankSum++;  
  32.   
  33.     if (m_nTankNum == 0)  
  34.     {  
  35.         m_bNewLevel = true;  
  36.     }  
  37. }  

  前一部分是static属性的初始化,后面是两个函数的实现。相信大家一看就懂。这里的具体规则大家可以自行修改,制定规则才是游戏开发中最有乐趣的一部分。

  绘制成绩

  相关的数据我们需要绘制在屏幕的右半部分。我们在Graphic类中添加一个static函数:

C++代码
  1. static void ShowScore();  

  实现如下:

C++代码
  1. const int SCORE_LEFT = 810;  
  2. const int SCORE_TOP = 5;  
  3.   
  4. void Graphic::ShowScore()  
  5. {  
  6.     COLORREF fill_color_save = getfillcolor();  
  7.     COLORREF color_save = getcolor();  
  8.   
  9.     //setfillcolor(m_color);  
  10.     //setcolor(m_color);  
  11.   
  12.     rectangle(SCORE_LEFT, SCORE_TOP, SCORE_LEFT + 200, SCORE_TOP + 40);  
  13.   
  14.   
  15.     RECT r = { SCORE_LEFT, SCORE_TOP, SCORE_LEFT + 200, SCORE_TOP + 40 };  
  16.     wsprintf((LPWSTR)m_pArray, _T("第 %d 关"), Setting::GetGameLevel());  
  17.     drawtext((LPWSTR)m_pArray, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);  
  18.   
  19.     r.top += 50;  
  20.     r.bottom += 50;  
  21.     wsprintf((LPWSTR)m_pArray, _T("分  数  :  %d"), Setting::GetSumScore());  
  22.     drawtext((LPWSTR)m_pArray, &r, DT_VCENTER | DT_SINGLELINE);  
  23.   
  24.     r.top += 50;  
  25.     r.bottom += 50;  
  26.     wsprintf((LPWSTR)m_pArray, _T("级  别  :  %d"), Setting::GetTankLevel());  
  27.     drawtext((LPWSTR)m_pArray, &r, DT_VCENTER | DT_SINGLELINE);  
  28.   
  29.     r.top += 50;  
  30.     r.bottom += 50;  
  31.     wsprintf((LPWSTR)m_pArray, _T("生  命  :  %d"), Setting::GetLife());  
  32.     drawtext((LPWSTR)m_pArray, &r, DT_VCENTER | DT_SINGLELINE);  
  33.   
  34.     r.top += 50;  
  35.     r.bottom += 50;  
  36.     wsprintf((LPWSTR)m_pArray, _T("敌人数  :  %d"), Setting::GetTankNum());  
  37.     drawtext((LPWSTR)m_pArray, &r, DT_VCENTER | DT_SINGLELINE);  
  38.   
  39.     r.top += 50;  
  40.     r.bottom += 50;  
  41.   
  42.     line(SCORE_LEFT, r.bottom, SCREEN_WIDTH - 5, r.bottom);  
  43.   
  44.     r.top += 50;  
  45.     r.bottom += 50;  
  46.     wsprintf((LPWSTR)m_pArray, _T("共击毁敌人数  :  %d"), Setting::GetTankSum());  
  47.     drawtext((LPWSTR)m_pArray, &r, DT_VCENTER | DT_SINGLELINE);  
  48.   
  49.   
  50.     setcolor(color_save);  
  51.     setfillcolor(fill_color_save);  
  52. }  

  最后,需要把这些调用放在main函数中,这里不做说明,请大家自己试一下。如果自己写不出来请在我的GitHub中下载完整代码。

  执行效果就是文章开头的图片效果。

转自:简书   作者:天花板

除非特别注明,鸡啄米文章均为原创
转载请标明本文地址:http://www.jizhuomi.com/software/702.html
2017年3月8日
作者:鸡啄米 分类:软件开发 浏览: 评论:1