上篇文章实现了坦克与地图碰撞的检测,

这篇我们继续完成子弹和地图的碰撞检测。

1.先设计一个子弹类Bullet,如下所示:

class Bullet : public CCSprite
{
public:
Bullet();
~Bullet(); static Bullet* createBulletWithTank(Tank* tank);
void initBulletWithTank(Tank* tank);
bool fire();
virtual void update(float delta);
void bulletBoom(); private:
bool isFlying;
Tank* mTank;
TileMapInfo* mTileMapInfo;
float stepX, stepY;
};

在上面

static Bullet* createBulletWithTank(Tank* tank);
void initBulletWithTank(Tank* tank);

分别是创建子弹的静态方法和初始化子弹的方法,他们都有一个共同参数tank,

用来表示他们所属的坦克。

fire()方法用来被坦克开火的时候调用,

然后在update方法中控制子弹移动以及碰撞检测。

在撞击后通过调用bulletBoom来引爆子弹,炸毁周围的砖块等。

2.在构造函数中初始化

Bullet::Bullet() :isFlying(false)
{
}

isFlying指示子弹是否在飞行中,初始为false表示没有飞行。

3.void Bullet::initBulletWithTank(Tank* tank)函数的实现:

void Bullet::initBulletWithTank(Tank* tank)
{
mTank = tank;
mTileMapInfo = mTank->getTileMapInfo(); initWithSpriteFrameName("bullet.png");
mTileMapInfo->getTileMap()->addChild(this);
setVisible(false);
}

在Bullet类中我们用mTank成员变量存储了他所属的坦克,

用mTIleMapInfo存储了他所属的地图。

用bullet.png精灵帧初始化了精灵。

然后把子弹加入了地图层中

然后把子弹设置为不可见。

4.继续实现静态方法Bullet* Bullet::createBulletWithTank(Tank* tank)

Bullet* Bullet::createBulletWithTank(Tank* tank)
{
Bullet* bullet = new Bullet();
bullet->initBulletWithTank(tank);
bullet->autorelease(); return bullet;
}

可以看到实现非常简单,创建一个Bullet类实例,然后用tank参数初始化,

最后加入自动释放列表,然后返回子弹类指针。

5.是先fire()函数,控制子弹运动方向等:

bool Bullet::fire()
{
if (!isFlying)
{
isFlying = true;
setVisible(true);
setPosition(mTank->getPosition());
//设置子弹运行方向
int Rotation = mTank->getRotation();
switch (Rotation)
{
case 0:
stepX = 0.0f, stepY = 2.0f;
break;
case 90:
stepX = 2.0f, stepY = 0.0f;
break;
case 180:
stepX = 0.0f, stepY = -2.0f;
break;
case 270:
stepX = -2.0f, stepY = 0.0f;
break;
default:
break;
}
scheduleUpdate();
} return isFlying;
}

可以看到,先判断子弹是否在飞行中,如果不在飞行中被调用了,

则先设置飞行状态isFlying为飞行中。

然后设置子弹初始位置为坦克所在的位置,

然后根据坦克旋转的方向,来设置子弹的运行方向分量——stepX和stepY。

最后调用scheduleUpdate()启动update定时器。这样显示每一帧动画的时候,

就会调用我们的update()函数。

6.下面看看怎么实现update()函数:

void Bullet::update(float delta)
{
CCSprite::update(delta);
//设置移动后的位置
setPosition(ccp(getPositionX() + stepX, getPositionY() + stepY)); //检测是否有碰撞
CCRect rect = boundingBox();
if (mTileMapInfo->collisionTest(rect))
{
unscheduleUpdate();
setVisible(false);
isFlying = false;
//引爆子弹
bulletBoom();
}
}

上面先设置了子弹根据分量stepX和stepY移动后的位置。

然后获取自己在地图上的CCRect,然后传入地图信息类中的碰撞检测函数。

如果碰撞了,就调用unscheduleUpdate()来取消update()定时器,

然后设置子弹为不可见,飞行状态设置为false,调用bulletBoom()来引爆子弹。

7.下面实现Bullet类中最后一个成员函数bulletBoom(),来看看它怎么引爆子弹的:

void Bullet::bulletBoom()
{
CCRect rect = boundingBox();
CCSize mapSize = mTileMapInfo->getTileMap()->getContentSize(); if (rect.getMinX() < 0 || rect.getMaxX() >= mapSize.width ||
rect.getMinY() < 0 || rect.getMaxY() >= mapSize.height)
return ; CCTMXLayer* tmxLayer = mTileMapInfo->getTileMap()->layerNamed("layer_0");
CCSize tileSize = tmxLayer->getMapTileSize(); //调整Y轴位tmx地图中的Y轴
float MinY = mapSize.height - rect.getMinY();
float MaxY = mapSize.height - rect.getMaxY(); //将与子弹碰撞的墙壁tileWall图块删除
CCPoint pt = ccp((int)rect.getMinX() / tileSize.width,(int)(MinY / tileSize.height));
if (gidToTileType[tmxLayer->tileGIDAt(pt)] == tileWall)
tmxLayer->setTileGID(gidToTileType[tileNone], pt); pt = ccp((int)rect.getMinX() / tileSize.width,(int)(MaxY / tileSize.height));
if (gidToTileType[tmxLayer->tileGIDAt(pt)] == tileWall)
tmxLayer->setTileGID(gidToTileType[tileNone], pt); pt = ccp((int)rect.getMaxX() / tileSize.width,(int)(MinY / tileSize.height));
if (gidToTileType[tmxLayer->tileGIDAt(pt)] == tileWall)
tmxLayer->setTileGID(gidToTileType[tileNone], pt); pt = ccp((int)rect.getMaxX() / tileSize.width,(int)(MaxY / tileSize.height));
if (gidToTileType[tmxLayer->tileGIDAt(pt)] == tileWall)
tmxLayer->setTileGID(gidToTileType[tileNone], pt);
}

先获取了自己的位置rect和地图的尺寸mapSIze。

首先判断了自己是否跑到了地图外边。如果在地图外边就直接返回。

然后获取了layer_0层的地图信息,将屏幕中的Y轴转换成tmx地图中的Y轴,

然后判断子弹四个角所接触的图块,如果图块是墙壁,那么获取墙壁的GID都设置成tileNone,这样就相当于炸毁墙壁图块。

8.最后我们需要在Tank类型初始化我们的子弹才能看到子弹运行效果,在坦克类中:

void Tank::initTankWithTankType(const char* tankTypeName, TileMapInfo* tileMapInfo)
{
initWithSpriteFrameName(tankTypeName);
mTileMapInfo = tileMapInfo; //将坦克放入地图层中
mTileMapInfo->getTileMap()->addChild(this); //缩放到合适大小
CCTMXTiledMap* tmxTileMap = mTileMapInfo->getTileMap();
CCSize tileSize = tmxTileMap->getTileSize();
CCSize tankSize = getContentSize();
//比地图上砖块小一点
setScale((tileSize.height * 2-4) / (tankSize.height)); //初始化坦克的子弹
mBullet = Bullet::createBulletWithTank(this);
}

可以看到很简单在最下面一行,给mBullet成员函数调用Bullet::createBulletWithTank(this)初始化了子弹。

然后我们还要在Tank类的命中响应函数中调用开火命令:

void Tank::command(enumOrder order)
{
float stepX = 0.0f;
float stepY = 0.0f;
static float fRotation = 0.0f; switch (order)
{
case cmdNothing:
break;
case cmdGoUP:
stepY = 1.0f;
fRotation = 0.0f;
break;
case cmdGoDown:
stepY = -1.0f;
fRotation = 180.0f;
break;
case cmdGoLeft:
stepX = -1.0f;
fRotation = 270.0f;
break;
case cmdGoRight:
stepX = 1.0f;
fRotation = 90.0f;
break;
case cmdFire:
//调用子弹开火
mBullet->fire();
break;
default:
break;
} //检测地图上的碰撞
CCRect rect = this->boundingBox();
if (!mTileMapInfo->collisionTest(CCRectMake(rect.getMinX() + stepX,
rect.getMinY() + stepY, rect.size.width, rect.size.height)))
{
setPositionX(getPositionX() + stepX);
setPositionY(getPositionY() + stepY);
} //根据运行方向旋转坦克
setRotation(fRotation);
}

case cmdFire:
//调用子弹开火
mBullet->fire();
break;

容易看到,只加上这一句就能实现开火效果了。

下面我们编译运行程序,看看效果:

完整实现的代码下载地址如下:

http://download.csdn.net/detail/yincheng01/6760931

cocos2d-x游戏开发系列教程-坦克大战游戏之子弹和地图碰撞的更多相关文章

  1. cocos2d-x游戏开发系列教程-坦克大战游戏启动界面的编写

    用前面介绍的方法,创建一个cocos2d-x项目,可以看到新项目内容如下图:

  2. cocos2d-x游戏开发系列教程-坦克大战游戏之敌方坦克AI的编写

    在上篇我们完成了子弹和地图碰撞的检测,在这篇我们将完成敌方坦克AI的编写. 具体思路是屏幕中保持有四个敌方坦克,然后坦克随机方向运动,并且子弹消失后1秒发射一次 1.我们新建一个敌方坦克的AI类来控制 ...

  3. cocos2d-x游戏开发系列教程-坦克大战游戏之子弹的碰撞检测处理

    在上篇我们加上了简单的坦克之间的碰撞检测,这篇我们继续加上子弹之间, 子弹与坦克之间的碰撞检测,对于上一篇碰撞处理不太完美的地方我们继续改进. 1.子弹之间的碰撞 //玩家子弹和敌方子弹之间的碰撞 C ...

  4. cocos2d-x游戏开发系列教程-坦克大战游戏之所有坦克之间的碰撞检测

    上篇我们完成了简单的AI编写,但是各个坦克移动时之间是可以重合的, 这节课我们来完成坦克之间的碰撞检测,还是在上篇的EnemyAI中完成. 1.我先现在坦克类Tank中添加两个成员变量: CC_SYN ...

  5. cocos2d-x游戏开发系列教程-坦克大战游戏之虚拟手柄控制坦克移动

    上篇显示了控制手柄,但是还不能用来控制坦克, 这篇将会讲手柄和坦克的移动结合起来. 1.先在CityScene场景中实现场景的虚函数virtual void onEnter(); onEnter在进入 ...

  6. cocos2d-x游戏开发系列教程-坦克大战游戏之坦克和地图碰撞的检测下

    上篇我们完成了地图的信息获取和碰撞检测,这篇我们整合到程序中. 在这之前我们改造一下Tank类,使它更加模块化,共容易理解: 1.改造后的Tank类声明如下: class Tank : public ...

  7. cocos2d-x游戏开发系列教程-坦克大战游戏之虚拟手柄的显示

    上篇文章我们有了坦克,但是没有手柄,无法控制坦克. 1.这篇我们编写虚拟手柄来控制坦克.头文件大致内容如下: #define RES_PADDLE_LEFT "paddle/left.png ...

  8. cocos2d-x游戏开发系列教程-坦克大战游戏之坦克的显示

    1.先定义坦克的一些属性 class Tank : public CCSprite { public : Tank(); ~Tank(); static Tank* createTankWithTan ...

  9. cocos2d-x游戏开发系列教程-坦克大战游戏加载地图的编写

    上节课写了关卡选择场景,那么接下来写关卡内容,先写最基本的地图的加载 我们新建一个场景类,如下所示: class CityScene : public cocos2d::CCLayer { publi ...

随机推荐

  1. ;(function($,window,undefined){})(jQuery,window)详细解析————借助B5教程解析自己整理了一下

    在jquery插件中我们经常看到以下这段代码 ;(function ( $, window, document, undefined ){ //函数体内具体代码 })(jQuery, window,d ...

  2. A.归并排序

    归并排序 (求逆序数) 归并排序:递归+合并+排序 时间复杂度:O(n logn)    空间复杂度:O(n) 用途:1.排序  2.求逆序对数 Description In this problem ...

  3. 进度记录 和 安装imagick时Cannot locate header file MagickWand.h错误的解决

    修改php.ini文件,已使php支持扩展的功能 [root@localhost imagick-2.2.2]# ./configure --with-php-config=/usr/local/ph ...

  4. 多线程下载工具-Axel

    1.安装: apt-get install axel 2.用法: axel 参数 文件下载地址 3.常用参数: -n 指定线程数 -o 指定文件存储位置(如不指定,默认存在当前位置(pwd)) -q ...

  5. Subsets 【dfs】

    Given a set of distinct integers, nums, return all possible subsets. Note: Elements in a subset must ...

  6. AnsiString 在 Delphi 中虽然不可用,但是,在 C++ 中可以用

    [C++] C++ Builder 中 Ansi 编码的字符串在Android/iOS程序中显示的问题 呃,这个问题说起来,其实也不麻烦,C++ Builder 本身在 TEncoding 做了处理, ...

  7. F#实现的单链表(函数式的思想)

    // 在 http://fsharp.net 上了解有关 F# 的更多信息 // 请参阅“F# 教程”项目以获取更多帮助. type list = | Nil | Cons of int * list ...

  8. 【Cavali风格/优质羊毛混纺面料/高密抗静电里衬/撞色拼皮/立领/绿色/便装单西】玛萨玛索男装网购商城

    [Cavali风格/优质羊毛混纺面料/高密抗静电里衬/撞色拼皮/立领/绿色/便装单西]玛萨玛索男装网购商城 Cavali风格/优质羊毛混纺面料/高密抗静电里衬/撞色拼皮/立领/绿色/便装单西

  9. Linux下的定时器

    以下摘自linux下的man文件:(man  getitimer) #include  <sys/time.h> int  getitimer(int which,  struct iti ...

  10. 如何去掉IE控件的垂直滚动条(使用QAxWidget加载IE控件)

    如果使用MFC的CHtmlView或Qt的QAxWidget加载IE控件,载入html文件后都会自动带一个垂直滚动条,我们不想要这个滚动条,改怎么办呢?搜索了一下“隐藏IE控件滚动条”,发现在 htt ...