战场范围

  之前我们的坦克从战场的一边走出之后会从另一边重新进入战场。这样不符合我们游戏的定义。我们需要把它们改成遇到战场边就不能再继续向前走了。

  主战坦克

  修改MainTank.cpp中的Move方法,如下:

C++代码
  1. void MainTank::Move()  
  2. {  
  3.     switch (m_dir)  
  4.     {  
  5.     case UP:  
  6.         m_pos.SetY(m_pos.GetY() - m_step);  
  7.         if (m_rectSphere.GetStartPoint().GetY() < Graphic::GetBattleGround().GetStartPoint().GetY())  
  8.             m_pos.SetY(m_pos.GetY() + m_step);  
  9.         break;  
  10.     case DOWN:  
  11.         m_pos.SetY(m_pos.GetY() + m_step);  
  12.         if (m_rectSphere.GetEndPoint().GetY() > Graphic::GetBattleGround().GetEndPoint().GetY())  
  13.             m_pos.SetY(m_pos.GetY() - m_step);  
  14.         break;  
  15.     case LEFT:  
  16.         m_pos.SetX(m_pos.GetX() - m_step);  
  17.         if (m_rectSphere.GetStartPoint().GetX() < Graphic::GetBattleGround().GetStartPoint().GetX())  
  18.             m_pos.SetX(m_pos.GetX() + m_step);  
  19.         break;  
  20.     case RIGHT:  
  21.         m_pos.SetX(m_pos.GetX() + m_step);  
  22.         if (m_rectSphere.GetEndPoint().GetX() > Graphic::GetBattleGround().GetEndPoint().GetX())  
  23.             m_pos.SetX(m_pos.GetX() - m_step);  
  24.         break;  
  25.     default:  
  26.         break;  
  27.     }  
  28.   
  29.     CalculateSphere();  
  30. }

  敌人坦克

  敌人坦克也是一样,Move方法完全相同。修改EnemyTank.cpp中的Move方法,如下:

C++代码
  1. void EnemyTank::Move()  
  2. {  
  3.     switch (m_dir)  
  4.     {  
  5.     case UP:  
  6.         m_pos.SetY(m_pos.GetY() - m_step);  
  7.         if (m_rectSphere.GetStartPoint().GetY() < Graphic::GetBattleGround().GetStartPoint().GetY())  
  8.             m_pos.SetY(m_pos.GetY() + m_step);  
  9.         break;  
  10.     case DOWN:  
  11.         m_pos.SetY(m_pos.GetY() + m_step);  
  12.         if (m_rectSphere.GetEndPoint().GetY() > Graphic::GetBattleGround().GetEndPoint().GetY())  
  13.             m_pos.SetY(m_pos.GetY() - m_step);  
  14.         break;  
  15.     case LEFT:  
  16.         m_pos.SetX(m_pos.GetX() - m_step);  
  17.         if (m_rectSphere.GetStartPoint().GetX() < Graphic::GetBattleGround().GetStartPoint().GetX())  
  18.             m_pos.SetX(m_pos.GetX() + m_step);  
  19.         break;  
  20.     case RIGHT:  
  21.         m_pos.SetX(m_pos.GetX() + m_step);  
  22.         if (m_rectSphere.GetEndPoint().GetX() > Graphic::GetBattleGround().GetEndPoint().GetX())  
  23.             m_pos.SetX(m_pos.GetX() - m_step);  
  24.         break;  
  25.     default:  
  26.         break;  
  27.     }  
  28.   
  29.     CalculateSphere();  
  30. }

  运行一下程序,效果如下:

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

  问题大家肯定看到了,坦克运行到战场边就停止了,这样游戏没法进行下去了。我们要修改敌人的坦克,让它们自己会调整方向。

  自动转向的敌人坦克

  敌人坦克的自动转向包括两个部分:

  • 坦克遇到战场边后随机调转方向

  • 坦克每走10步随机调转方向

  代码如下:

  EnemyTank.h

C++代码
  1. #ifndef __ENEMY_TANK__  
  2. #define __ENEMY_TANK__  
  3.   
  4. #include "Tank.h"  
  5.   
  6. #define MAX_STEP 10  
  7.   
  8. class EnemyTank : public Tank  
  9. {  
  10. public:  
  11.     EnemyTank()  
  12.     {  
  13.         RandomTank();  
  14.     }  
  15.   
  16.     ~EnemyTank(){}  
  17.   
  18.     void Display();  
  19.     void Move();  
  20.   
  21. protected:  
  22.     void CalculateSphere();  
  23.     void RandomTank();  
  24.     // 随机产生坦克方向 type: 1, 新方向必须与之前方向不同 2, 任意一个新方向  
  25.     void RandomDir(int type);  
  26.   
  27.     int m_stepCnt;  
  28. };  
  29.   
  30. #endif  

  EnemyTank类中添加了一个m_stepCnt属性,用来记录坦克当前行驶的步数。又定义了一个MAX_STEP宏定义最大的行驶步数。

  RandomDir()用来随即地产生坦克方向,参数type为1时产生一个和当前方向不同的新方向,参数type为0时,产生任意一个新方向。

  EnemyTank.cpp

  这个文件中只有三个函数有变化。

C++代码
  1. void EnemyTank::RandomTank()  
  2. {  
  3.     m_pos.SetX(rand() % Graphic::GetBattleGround().GetWidth());  
  4.     m_pos.SetY(rand() % Graphic::GetBattleGround().GetHeight());  
  5.     m_color = WHITE;  
  6.     m_dir = (Dir)(Dir::UP + (rand() % 4));  
  7.     m_step = 2;  
  8.     m_stepCnt = rand() % MAX_STEP;  
  9. }  

  这个函数在初始化变量的时候为m_stepCnt随机产生一个当前步数。为什么要在这里用随即数呢?如果每个坦克的当前步数相同的话,那么到第十歩的时候所有的坦克会集体转向,这样会很奇怪。不信大家可以试试。

C++代码
  1. void EnemyTank::RandomDir(int type)  
  2. {  
  3.     if (type == 1)  
  4.     {  
  5.         Dir dir;  
  6.         while ((dir = (Dir)(Dir::UP + (rand() % 4))) == m_dir)  
  7.         {  
  8.             // Do nothing  
  9.         }  
  10.   
  11.         m_dir = dir;  
  12.     }  
  13.     else  
  14.     {  
  15.         m_dir = (Dir)(Dir::UP + (rand() % 4));  
  16.     }  
  17. }  

  这个函数的功能刚才已经介绍过了,实现方式也很简单。

C++代码
  1. void EnemyTank::Move()  
  2. {  
  3.     switch (m_dir)  
  4.     {  
  5.     case UP:  
  6.         m_pos.SetY(m_pos.GetY() - m_step);  
  7.         if (m_rectSphere.GetStartPoint().GetY() < Graphic::GetBattleGround().GetStartPoint().GetY())  
  8.         {  
  9.             m_pos.SetY(m_pos.GetY() + m_step);  
  10.             this->RandomDir(1);  
  11.         }  
  12.         break;  
  13.     case DOWN:  
  14.         m_pos.SetY(m_pos.GetY() + m_step);  
  15.         if (m_rectSphere.GetEndPoint().GetY() > Graphic::GetBattleGround().GetEndPoint().GetY())  
  16.         {  
  17.             m_pos.SetY(m_pos.GetY() - m_step);  
  18.             this->RandomDir(1);  
  19.         }  
  20.         break;  
  21.     case LEFT:  
  22.         m_pos.SetX(m_pos.GetX() - m_step);  
  23.         if (m_rectSphere.GetStartPoint().GetX() < Graphic::GetBattleGround().GetStartPoint().GetX())  
  24.         {  
  25.             m_pos.SetX(m_pos.GetX() + m_step);  
  26.             this->RandomDir(1);  
  27.         }  
  28.         break;  
  29.     case RIGHT:  
  30.         m_pos.SetX(m_pos.GetX() + m_step);  
  31.         if (m_rectSphere.GetEndPoint().GetX() > Graphic::GetBattleGround().GetEndPoint().GetX())  
  32.         {  
  33.             m_pos.SetX(m_pos.GetX() - m_step);  
  34.             this->RandomDir(1);  
  35.         }  
  36.         break;  
  37.     default:  
  38.         break;  
  39.     }  
  40.   
  41.     CalculateSphere();  
  42.   
  43.     m_stepCnt++;  
  44.     if (m_stepCnt >= MAX_STEP)  
  45.     {  
  46.         m_stepCnt = 0;  
  47.         this->RandomDir(0);  
  48.     }  
  49. }  

  Move()函数中,一旦遇到战场边就调用RandomDir()函数随机出一个新的方向。每次移动都用m_stepCnt属性计步一次,每走10歩就做一次随机改变方向。

  下面就是执行效果:

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

  这篇文章的相关代码已经上传至GitHub

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