美文网首页技术宅C/C++程序员
C++代码训练营 | 坦克大战(8)

C++代码训练营 | 坦克大战(8)

作者: 天花板 | 来源:发表于2017-02-15 20:48 被阅读583次

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

    void Graphic::ShowGameLevel(int nLevel)
    {
        COLORREF fill_color_save = getfillcolor();
        COLORREF color_save = getcolor();
    
        rectangle(BATTLE_GROUND_X1 + 100, BATTLE_GROUND_Y1 + 200, BATTLE_GROUND_X1 + 700, BATTLE_GROUND_Y1 + 380);
    
        LOGFONT fontBak;
        gettextstyle(&fontBak);               // 获取当前字体设置
    
        LOGFONT f = fontBak;
        f.lfHeight = 48;                      // 设置字体高度为 48
        _tcscpy_s(f.lfFaceName, _T("黑体"));  // 设置字体为“黑体”
        f.lfQuality = ANTIALIASED_QUALITY;    // 设置输出效果为抗锯齿  
        settextstyle(&f);                     // 设置字体样式
        wsprintf((LPWSTR)m_pArray, _T("第 %d 关"), nLevel);
        outtextxy(BATTLE_GROUND_X1 + 300, BATTLE_GROUND_Y1 + 250, (LPWSTR)m_pArray);
    
        f.lfHeight = 18;
        settextstyle(&f);
        wsprintf((LPWSTR)m_pArray, _T("按 Enter 键开始"), nLevel);
        outtextxy(BATTLE_GROUND_X1 + 550, BATTLE_GROUND_Y1 + 350, (LPWSTR)m_pArray);
    
        settextstyle(&fontBak);
    
        setcolor(color_save);
        setfillcolor(fill_color_save);
    }
    

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

    显示提示信息

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

    void main()
    {
        Init();
    
        bool loop = true;
        bool skip = false;
        while (loop)
        {
            if (kbhit())
            {
                int key = getch();
                if (skip && key != 13)
                {
                    continue;
                }
    
                switch (key)
                {
                // Up
                case 72:
                    mainTank.SetDir(Dir::UP);
                    break;
                // Down
                case 80: 
                    mainTank.SetDir(Dir::DOWN);
                    break;
                // Left
                case 75: 
                    mainTank.SetDir(Dir::LEFT);
                    break;
                // Right
                case 77: 
                    mainTank.SetDir(Dir::RIGHT);
                    break;
                case 224: // 方向键高8位
                    break;
                // Esc
                case 27:
                    loop = false;
                    break;
                // Space
                case 32:
                    mainTank.Shoot(lstMainTankBullets);
                    break;
                // Enter
                case 13:
                    if (skip)
                        skip = false;
                    else
                        skip = true;
                    break;
                default: 
                    break;
                }
            }
            
            if (!skip)
            {
                // Draw Background
                cleardevice();
                Graphic::DrawBattleGround();
                Graphic::ShowScore();
    
                // New Game Level
                if (Setting::m_bNewLevel)
                {
                    Setting::m_bNewLevel = false;
    
                    Setting::NewGameLevel();
    
                    Graphic::ShowGameLevel(Setting::GetGameLevel());
    
                    for (int i = 0; i < Setting::GetTankNum(); i++)
                    {
                        EnemyTank* p = new EnemyTank();
                        lstTanks.push_back(p);
                    }
    
                    // 设置暂停,按Enter开始
                    skip = true;
                    continue;
                }
                
                CheckCrash();
                
                mainTank.Move();
                mainTank.Display();
    
                /* Draw Tanks */
                for (list<Tank*>::iterator it = lstTanks.begin(); it != lstTanks.end();)
                {
                    (*it)->Move();
    
                    if ((*it)->IsDisappear())
                    {
                        Setting::TankDamaged();
    
                        // Add a bomb
                        (*it)->Boom(lstBombs);
    
                        // Delete the tank
                        delete *it;
                        it = lstTanks.erase(it);
                        continue;
                    }
    
                    (*it)->Display();
    
                    if ((*it)->NeedShoot())
                    {
                        EnemyTank* p = (EnemyTank*)*it;
                        p->Shoot(lstBullets);
                    }
                    it++;
                }
    
                /* Draw Bullets */
                for (list<Object*>::iterator it = lstMainTankBullets.begin(); it != lstMainTankBullets.end();)
                {
                    (*it)->Move();
    
                    if ((*it)->IsDisappear())
                    {
                        // Add a bomb
                        (*it)->Boom(lstBombs);
    
                        // Delete the bullet
                        delete *it;
                        it = lstMainTankBullets.erase(it);
                        continue;
                    }
    
                    (*it)->Display();
                    it++;
                }
    
                for (list<Object*>::iterator it = lstBullets.begin(); it != lstBullets.end();)
                {
                    (*it)->Move();
                
                    if ((*it)->IsDisappear())
                    {
                        // Add a bomb
                        (*it)->Boom(lstBombs);
    
                        // Delete the bullet
                        delete *it;
                        it = lstBullets.erase(it);
                        continue;
                    }
    
                    (*it)->Display();
                    it++;
                }
    
                /* Draw Bombs */
                for (list<Object*>::iterator it = lstBombs.begin(); it != lstBombs.end();)
                {
                    (*it)->Move();
    
                    if ((*it)->IsDisappear())
                    {
                        delete *it;
                        it = lstBombs.erase(it);
                        continue;
                    }
                    
                    (*it)->Display();
                    it++;
                }
            }
    
            Sleep(100);
        }
        
        // Destroy
        Dispose();
    }
    

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

    if (Setting::m_bNewLevel)
    {
        Setting::m_bNewLevel = false;
    
        Setting::NewGameLevel();
    
        Graphic::ShowGameLevel(Setting::GetGameLevel());
    
        for (int i = 0; i < Setting::GetTankNum(); i++)
        {
            EnemyTank* p = new EnemyTank();
            lstTanks.push_back(p);
        }
    
        // 设置暂停,按Enter开始
        skip = true;
        continue;
    }
    

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

    • 初始化新一关的相关变量
    • 绘制刚才的提示信息
    • 创建新关卡中的敌人坦克
    • 通过设置skip变量将程序暂停

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

    重点

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

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

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

    我是天花板,让我们一起在软件开发中自我迭代。
    如有任何问题,欢迎与我联系。


    上一篇:C++代码训练营 | 坦克大战(7)
    下一篇:C++代码训练营 | 坦克大战(9)

    相关文章

      网友评论

      本文标题:C++代码训练营 | 坦克大战(8)

      本文链接:https://www.haomeiwen.com/subject/otxcwttx.html