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

上一篇中,我们的主战坦克发出的炮弹还没有实际的作用,今天我们就让它拥有击毁敌军坦克的功能。

新增基础API

Rect类

在Rect类中,我们添加下面两个新接口。

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

这两个函数的作用是返回矩形右上角和左下角的两个点。这样方便我们在计算炮弹是否击中坦克时使用。

实现如下:

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这个属性。我们为Object类中添加下面这个虚函数函数:

virtual Rect GetSphere() = 0;

在所有的继承类中,都要对这个函数进行实现,实现方法很简单就是返回m_rectSphere属性即可。

Rect GetSphere()
{
    return m_rectSphere;
}

Tank类

在坦克类中,我们需要添加一个设置坦克消失的接口,当坦克被击中时,我们通过这个接口把m_bDisappear属性设为true。

void SetDisappear()
{
    m_bDisappear = true;
}

位置判断

在游戏设计中,有个概念叫做“碰撞检测”,用来判断两个元素是否碰在一起。比如我们的坦克大战中,如何判断炮弹是否击中了坦克。另外,一些格斗类游戏中,人物出拳或踢腿是否击中目标都需要有相应的算法来判断。

网上有一些开源的库可以帮助我们完成一些复杂形状间的碰撞检测。在这里,我们把炮弹和坦克之间的碰撞检测简化为两个形状势力范围是否重叠的判断。也就是判断两个矩形是否重叠。

我们创建一个目录Utils来存放一些功能性的代码,里面先创建下面一组文件。

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是一个静态类,里面有两个静态成员函数。

CheckPointInRect函数负责判断一个点是否在一个矩形的范围内。CheckInterSect函数负责判断两个矩形是否重合。

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;
    }
}

判断两个矩形是否重合的方法很简单,只要判断第一个矩形的四个顶点是否在第二个矩形的范围内即可。

功能实现

在main.cpp中,添加一个函数来实时判断是否有炮弹击中坦克的情况。

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();
            }
        }
    }
}

分别遍历主战坦克的炮弹list和坦克list,两两进行碰撞检测,发现有相交的就通过接口把两个元素都设置为消失。后面的工作交给展示阶段完成。

炮弹失效的动作我们已经在上一篇实现了,在这里只需要添加坦克销售的动作。

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++;
}

绘制坦克时,发现失效后添加一个爆炸的对象,之后删除这个坦克。

需要注意的是,在实现坦克的Boom接口时,我们创建的是一个大的爆炸。

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

一看代码大家就应该明白了。

好了,运行一下程序看看效果是不是和文章开头相同呢?

项目源码托管在GitHub上,请大家自行下载。

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


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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • 这一篇中,我们继续继续进行我们的坦克大战。 位置信息数据结构 在游戏设计过程中,需要记录大量的位置信息,如果仅仅使...
    天花板阅读 7,465评论 14 25
  • 上一篇中我们给主战坦克添加了发射炮弹的功能。不过有一个问题,炮弹飞到战场边缘时,自动消失的感觉不太好。我们今天来给...
    天花板阅读 3,472评论 4 9
  • 上一篇中,我们添加了可以自动行驶的敌人坦克,今天我们给主战坦克添加最核心的功能——开炮。 第一次重构 既然要开炮,...
    天花板阅读 4,065评论 1 13
  • 现在我们的游戏已经初具规模,但如果主战坦克一直是无敌状态那也很无趣。今天我们来让敌人的炮火发挥作用。 主战坦克被击...
    天花板阅读 2,679评论 1 8
  • 目前我们的主战坦克已经能够开炮击毁敌人坦克了,但敌人坦克不会开炮貌似比较欺负人。今天我们让敌人坦克也拥有开炮功能。...
    天花板阅读 5,095评论 8 6