C++代碼訓練營 | 坦克大戰(zhàn)(6)

上一篇中,我們的主戰(zhàn)坦克發(fā)出的炮彈還沒有實際的作用,今天我們就讓它擁有擊毀敵軍坦克的功能。

新增基礎API

Rect類

在Rect類中,我們添加下面兩個新接口。

Point GetTRPoint() const; // Get Top Right Point
Point GetBLPoint() const; // Get Bottom Left Point

這兩個函數(shù)的作用是返回矩形右上角和左下角的兩個點。這樣方便我們在計算炮彈是否擊中坦克時使用。

實現(xiàn)如下:

Point Rect::GetTRPoint() const
{
    Point p = m_startPoint;
    p.SetX(m_endPoint.GetX());

    return p;
}

Point Rect::GetBLPoint() const
{
    Point p = m_startPoint;
    p.SetY(m_endPoint.GetY());

    return p;
}

Object類

在判斷炮彈是否擊中坦克時,我們需要通過勢力范圍m_rectSphere這個屬性。我們?yōu)镺bject類中添加下面這個虛函數(shù)函數(shù):

virtual Rect GetSphere() = 0;

在所有的繼承類中,都要對這個函數(shù)進行實現(xiàn),實現(xiàn)方法很簡單就是返回m_rectSphere屬性即可。

Rect GetSphere()
{
    return m_rectSphere;
}

Tank類

在坦克類中,我們需要添加一個設置坦克消失的接口,當坦克被擊中時,我們通過這個接口把m_bDisappear屬性設為true。

void SetDisappear()
{
    m_bDisappear = true;
}

位置判斷

在游戲設計中,有個概念叫做“碰撞檢測”,用來判斷兩個元素是否碰在一起。比如我們的坦克大戰(zhàn)中,如何判斷炮彈是否擊中了坦克。另外,一些格斗類游戲中,人物出拳或踢腿是否擊中目標都需要有相應的算法來判斷。

網上有一些開源的庫可以幫助我們完成一些復雜形狀間的碰撞檢測。在這里,我們把炮彈和坦克之間的碰撞檢測簡化為兩個形狀勢力范圍是否重疊的判斷。也就是判斷兩個矩形是否重疊。

我們創(chuàng)建一個目錄Utils來存放一些功能性的代碼,里面先創(chuàng)建下面一組文件。

Shape.h

#ifndef __SHAPE_H__
#define __SHAPE_H__

#include "../Model/Rect.h"

class Shape
{
public:
    static bool CheckPointInRect(Point& point, Rect& rect);
    static bool CheckIntersect(Rect& rectA, Rect& rectB);
};

#endif

Shape是一個靜態(tài)類,里面有兩個靜態(tài)成員函數(shù)。

CheckPointInRect函數(shù)負責判斷一個點是否在一個矩形的范圍內。CheckInterSect函數(shù)負責判斷兩個矩形是否重合。

Shape.cpp

#include "Shape.h"

bool Shape::CheckPointInRect(Point& point, Rect& rect)
{
    if (point.GetX() < rect.GetStartPoint().GetX() || point.GetX() > rect.GetEndPoint().GetX() ||
        point.GetY() < rect.GetStartPoint().GetY() || point.GetY() > rect.GetEndPoint().GetY())
    {
        return false;
    }
    else
    {
        return true;
    }
}

bool Shape::CheckIntersect(Rect& rectA, Rect& rectB)
{
    if (CheckPointInRect(rectA.GetStartPoint(), rectB) ||
        CheckPointInRect(rectA.GetEndPoint(), rectB) ||
        CheckPointInRect(rectA.GetTRPoint(), rectB) ||
        CheckPointInRect(rectA.GetBLPoint(), rectB))
    {
        return true;
    }
    else
    {
        return false;
    }
}

判斷兩個矩形是否重合的方法很簡單,只要判斷第一個矩形的四個頂點是否在第二個矩形的范圍內即可。

功能實現(xiàn)

在main.cpp中,添加一個函數(shù)來實時判斷是否有炮彈擊中坦克的情況。

void CheckCrash()
{
    for (list<Object*>::iterator it = lstMainTankBullets.begin(); it != lstMainTankBullets.end(); it++)
    {
        for (list<Tank*>::iterator itt = lstTanks.begin(); itt != lstTanks.end(); itt++)
        {
            if (Shape::CheckIntersect((*it)->GetSphere(), (*itt)->GetSphere()))
            {
                (*itt)->SetDisappear();
                (*it)->SetDisappear();
            }
        }
    }
}

分別遍歷主戰(zhàn)坦克的炮彈list和坦克list,兩兩進行碰撞檢測,發(fā)現(xiàn)有相交的就通過接口把兩個元素都設置為消失。后面的工作交給展示階段完成。

炮彈失效的動作我們已經在上一篇實現(xiàn)了,在這里只需要添加坦克銷售的動作。

for (list<Tank*>::iterator it = lstTanks.begin(); it != lstTanks.end();)
{
    (*it)->Move();

    if ((*it)->IsDisappear())
    {
        // Add a bomb
        (*it)->Boom(lstBombs);

        // Delete the tank
        delete *it;
        it = lstTanks.erase(it);
        continue;
    }

    (*it)->Display();

    it++;
}

繪制坦克時,發(fā)現(xiàn)失效后添加一個爆炸的對象,之后刪除這個坦克。

需要注意的是,在實現(xiàn)坦克的Boom接口時,我們創(chuàng)建的是一個大的爆炸。

void Boom(list<Object*>& lstBombs)
{
    lstBombs.push_back(new Bomb(m_pos, LARGE));
}

一看代碼大家就應該明白了。

好了,運行一下程序看看效果是不是和文章開頭相同呢?

項目源碼托管在GitHub上,請大家自行下載。

我是天花板,讓我們一起在軟件開發(fā)中自我迭代。
如有任何問題,歡迎與我聯(lián)系。


上一篇:C++代碼訓練營 | 坦克大戰(zhàn)(5)
下一篇:C++代碼訓練營 | 坦克大戰(zhàn)(7)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 這一篇中,我們繼續(xù)繼續(xù)進行我們的坦克大戰(zhàn)。 位置信息數(shù)據結構 在游戲設計過程中,需要記錄大量的位置信息,如果僅僅使...
    天花板閱讀 7,535評論 14 25
  • 上一篇中我們給主戰(zhàn)坦克添加了發(fā)射炮彈的功能。不過有一個問題,炮彈飛到戰(zhàn)場邊緣時,自動消失的感覺不太好。我們今天來給...
    天花板閱讀 3,539評論 4 9
  • 上一篇中,我們添加了可以自動行駛的敵人坦克,今天我們給主戰(zhàn)坦克添加最核心的功能——開炮。 第一次重構 既然要開炮,...
    天花板閱讀 4,147評論 1 13
  • 現(xiàn)在我們的游戲已經初具規(guī)模,但如果主戰(zhàn)坦克一直是無敵狀態(tài)那也很無趣。今天我們來讓敵人的炮火發(fā)揮作用。 主戰(zhàn)坦克被擊...
    天花板閱讀 2,750評論 1 8
  • 目前我們的主戰(zhàn)坦克已經能夠開炮擊毀敵人坦克了,但敵人坦克不會開炮貌似比較欺負人。今天我們讓敵人坦克也擁有開炮功能。...
    天花板閱讀 5,238評論 8 6