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

  上一篇中设计出了关卡和分数,但每新开始一个新的关卡时没有任何提示信息,这样略显突兀。我们需要在每一个关卡开始之前给出一个提示信息,同时让玩家有休息的时间。

  绘制提示信息

  我们要在Battle区域中,显示一个矩形,中间打印关卡号。效果如下:

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

  实现起来也很容易,在Graphic类中添加一个ShowGameLevel函数:

C++代码
  1. void Graphic::ShowGameLevel(int nLevel)  
  2. {  
  3.     COLORREF fill_color_save = getfillcolor();  
  4.     COLORREF color_save = getcolor();  
  5.   
  6.     rectangle(BATTLE_GROUND_X1 + 100, BATTLE_GROUND_Y1 + 200, BATTLE_GROUND_X1 + 700, BATTLE_GROUND_Y1 + 380);  
  7.   
  8.     LOGFONT fontBak;  
  9.     gettextstyle(&fontBak);               // 获取当前字体设置  
  10.   
  11.     LOGFONT f = fontBak;  
  12.     f.lfHeight = 48;                      // 设置字体高度为 48  
  13.     _tcscpy_s(f.lfFaceName, _T("黑体"));  // 设置字体为“黑体”  
  14.     f.lfQuality = ANTIALIASED_QUALITY;    // 设置输出效果为抗锯齿    
  15.     settextstyle(&f);                     // 设置字体样式  
  16.     wsprintf((LPWSTR)m_pArray, _T("第 %d 关"), nLevel);  
  17.     outtextxy(BATTLE_GROUND_X1 + 300, BATTLE_GROUND_Y1 + 250, (LPWSTR)m_pArray);  
  18.   
  19.     f.lfHeight = 18;  
  20.     settextstyle(&f);  
  21.     wsprintf((LPWSTR)m_pArray, _T("按 Enter 键开始"), nLevel);  
  22.     outtextxy(BATTLE_GROUND_X1 + 550, BATTLE_GROUND_Y1 + 350, (LPWSTR)m_pArray);  
  23.   
  24.     settextstyle(&fontBak);  
  25.   
  26.     setcolor(color_save);  
  27.     setfillcolor(fill_color_save);  
  28. }  

  这里需要注意,我们使用了特殊字体和大小,因此在绘制完成后需要恢复默认字体。如果注释掉函数退出前的settextstyle(&fontBak);语句,界面上其他地方的字体会发生错乱。大家可以试试。

  显示提示信息

  在main函数中,我们要在每一关结束之后调用这个函数,同时让程序暂停。代码如下:

C++代码
  1. void main()  
  2. {  
  3.     Init();  
  4.   
  5.     bool loop = true;  
  6.     bool skip = false;  
  7.     while (loop)  
  8.     {  
  9.         if (kbhit())  
  10.         {  
  11.              int key = getch();  
  12.             if (skip && key != 13)  
  13.             {  
  14.                 continue;  
  15.             }  
  16.   
  17.             switch (key)  
  18.             {  
  19.             // Up  
  20.             case 72:  
  21.                 mainTank.SetDir(Dir::UP);  
  22.                 break;  
  23.             // Down  
  24.             case 80:   
  25.                 mainTank.SetDir(Dir::DOWN);  
  26.                 break;  
  27.             // Left  
  28.             case 75:   
  29.                 mainTank.SetDir(Dir::LEFT);  
  30.                 break;  
  31.             // Right  
  32.             case 77:   
  33.                 mainTank.SetDir(Dir::RIGHT);  
  34.                 break;  
  35.             case 224: // 方向键高8位  
  36.                 break;  
  37.             // Esc  
  38.             case 27:  
  39.                 loop = false;  
  40.                 break;  
  41.             // Space  
  42.             case 32:  
  43.                 mainTank.Shoot(lstMainTankBullets);  
  44.                 break;  
  45.             // Enter  
  46.             case 13:  
  47.                 if (skip)  
  48.                     skip = false;  
  49.                 else  
  50.                     skip = true;  
  51.                 break;  
  52.             default:   
  53.                 break;  
  54.             }  
  55.         }  
  56.   
  57.         if (!skip)  
  58.         {  
  59.             // Draw Background  
  60.             cleardevice();  
  61.             Graphic::DrawBattleGround();  
  62.             Graphic::ShowScore();  
  63.   
  64.             // New Game Level  
  65.             if (Setting::m_bNewLevel)  
  66.             {  
  67.                 Setting::m_bNewLevel = false;  
  68.   
  69.                 Setting::NewGameLevel();  
  70.   
  71.                 Graphic::ShowGameLevel(Setting::GetGameLevel());  
  72.   
  73.                 for (int i = 0; i < Setting::GetTankNum(); i++)  
  74.                 {  
  75.                     EnemyTank* p = new EnemyTank();  
  76.                     lstTanks.push_back(p);  
  77.                 }  
  78.   
  79.                 // 设置暂停,按Enter开始  
  80.                 skip = true;  
  81.                 continue;  
  82.             }  
  83.   
  84.             CheckCrash();  
  85.   
  86.             mainTank.Move();  
  87.             mainTank.Display();  
  88.   
  89.             /* Draw Tanks */  
  90.             for (list<Tank*>::iterator it = lstTanks.begin(); it != lstTanks.end();)  
  91.             {  
  92.                 (*it)->Move();  
  93.   
  94.                 if ((*it)->IsDisappear())  
  95.                 {  
  96.                     Setting::TankDamaged();  
  97.   
  98.                     // Add a bomb  
  99.                     (*it)->Boom(lstBombs);  
  100.   
  101.                     // Delete the tank  
  102.                     delete *it;  
  103.                     it = lstTanks.erase(it);  
  104.                     continue;  
  105.                 }  
  106.   
  107.                 (*it)->Display();  
  108.   
  109.                 if ((*it)->NeedShoot())  
  110.                 {  
  111.                     EnemyTank* p = (EnemyTank*)*it;  
  112.                     p->Shoot(lstBullets);  
  113.                 }  
  114.                 it++;  
  115.             }  
  116.   
  117.             /* Draw Bullets */  
  118.             for (list<Object*>::iterator it = lstMainTankBullets.begin(); it != lstMainTankBullets.end();)  
  119.             {  
  120.                 (*it)->Move();  
  121.   
  122.                 if ((*it)->IsDisappear())  
  123.                 {  
  124.                     // Add a bomb  
  125.                     (*it)->Boom(lstBombs);  
  126.   
  127.                     // Delete the bullet  
  128.                     delete *it;  
  129.                     it = lstMainTankBullets.erase(it);  
  130.                     continue;  
  131.                 }  
  132.   
  133.                 (*it)->Display();  
  134.                 it++;  
  135.             }  
  136.   
  137.             for (list<Object*>::iterator it = lstBullets.begin(); it != lstBullets.end();)  
  138.             {  
  139.                 (*it)->Move();  
  140.   
  141.                 if ((*it)->IsDisappear())  
  142.                 {  
  143.                     // Add a bomb  
  144.                     (*it)->Boom(lstBombs);  
  145.   
  146.                     // Delete the bullet  
  147.                     delete *it;  
  148.                     it = lstBullets.erase(it);  
  149.                     continue;  
  150.                 }  
  151.   
  152.                 (*it)->Display();  
  153.                 it++;  
  154.             }  
  155.   
  156.             /* Draw Bombs */  
  157.             for (list<Object*>::iterator it = lstBombs.begin(); it != lstBombs.end();)  
  158.             {  
  159.                 (*it)->Move();  
  160.   
  161.                 if ((*it)->IsDisappear())  
  162.                 {  
  163.                     delete *it;  
  164.                     it = lstBombs.erase(it);  
  165.                     continue;  
  166.                 }  
  167.   
  168.                 (*it)->Display();  
  169.                 it++;  
  170.             }  
  171.         }  
  172.   
  173.         Sleep(100);  
  174.     }  
  175.   
  176.     // Destroy  
  177.     Dispose();  
  178. }  

  重点看这里,当程序通过Setting::m_bNewLevel属性判断出到了新的一关时,执行下面这段代码:

C++代码
  1. if (Setting::m_bNewLevel)  
  2. {  
  3.     Setting::m_bNewLevel = false;  
  4.   
  5.     Setting::NewGameLevel();  
  6.   
  7.     Graphic::ShowGameLevel(Setting::GetGameLevel());  
  8.   
  9.     for (int i = 0; i < Setting::GetTankNum(); i++)  
  10.     {  
  11.         EnemyTank* p = new EnemyTank();  
  12.         lstTanks.push_back(p);  
  13.     }  
  14.   
  15.     // 设置暂停,按Enter开始  
  16.     skip = true;  
  17.     continue;  
  18. }  

  这段代码完成了下面几个动作:

  • 初始化新一关的相关变量

  • 绘制刚才的提示信息

  • 创建新关卡中的敌人坦克

  • 通过设置skip变量将程序暂停

  玩家需要通过按下Enter键来继续游戏。是不是很简单呢。

  重点

  这一篇的内容不多,但重点是如何在main函数中通过代码控制程序的流程。大家可以试试在不同的位置添加控制代码,会得到不同的效果。

  至于main函数中的程序流程如何安排更好,请大家仔细思考一下。这一篇涉及的代码请在GitHub中下载。

  下一篇中,我们开始让敌人的坦克发挥出应有的威力。游戏的难度该来了。

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