在上篇我们加上了简单的坦克之间的碰撞检测,这篇我们继续加上子弹之间,

子弹与坦克之间的碰撞检测,对于上一篇碰撞处理不太完美的地方我们继续改进。

1.子弹之间的碰撞

	//玩家子弹和敌方子弹之间的碰撞
CCObject* pObj;
CCARRAY_FOREACH(mEnemyTanks, pObj)
{
Bullet* enemyBullet = ((Tank*)pObj)->getBullet();
if (playerBullet->getFlyState() && enemyBullet->getFlyState())
{
if (IsRectIntersect(playerBullet->getMovedRect(), enemyBullet->getMovedRect()))
{
enemyBullet->stopFire();
playerBullet->stopFire();
break;
}
}
}

我们通过玩家子弹playerBullet与敌人子弹之间的碰撞检测,如果碰撞了调用了子弹的stopFire函数。

2.如果子弹相撞了,当然是子弹直接消失,然后设置子弹飞行状态为false,我们来看看stopFire的函数具体实现:

bool Bullet::stopFire()
{
if (mFlyState == true)
{
mFlyState = false;
setVisible(false);
unscheduleUpdate(); return true;
} return false;
}

其中mFlyState表示飞行状态,然后设置了不可见,取消了定时器,不再做子弹运动的计算。

3.我们再添加玩家子弹和敌人坦克的碰撞:

	//玩家子弹和敌方坦克的碰撞
CCARRAY_FOREACH(mEnemyTanks, pObj)
{
if (playerBullet->getFlyState())
{
Tank* enemyTank = (Tank*)pObj;
if (IsRectIntersect(playerBullet->getMovedRect(), enemyTank->getMovedRect()))
{
mEnemyTanks->removeObject(pObj);
enemyTank->remove();
playerBullet->stopFire();
break;
}
}
}

可以看到检测碰撞后从敌人坦克数组中移除了坦克对象,然后调用了坦克的remove命令,

来释放此坦克对象占用的内存,然后调用了玩家子弹的stopFire。

4.下面看看坦克对象的remove实现:

void Tank::remove()
{
mTileMapInfo->getTileMap()->removeChild(this);
}

他简单的调用了地图的removeChild函数,将自己从地图中移除了。

5.最后看看敌人子弹和玩家坦克的碰撞处理:

	//敌人子弹和玩家的碰撞
CCARRAY_FOREACH(mEnemyTanks, pObj)
{
Bullet* enemyBullet = ((Tank*)pObj)->getBullet();
if (enemyBullet->getFlyState())
{
if (IsRectIntersect(enemyBullet->getMovedRect(), mTank->getMovedRect()))
{
mTank->setVisible(false);
enemyBullet->stopFire();
break;
}
}
}

发生碰撞后,简单的将玩家坦克设置为不可见,然后停止敌人子弹开火。

6.碰撞函数基本上全部修改完毕,看看最后碰撞函数整体:

void EnemyAI::collisionTest()
{
Bullet* playerBullet = mTank->getBullet(); //坦克之间的碰撞
CCArray* ccTmpArray = CCArray::create();
ccTmpArray->addObjectsFromArray(mEnemyTanks);
ccTmpArray->addObject(mTank);
CCObject* pObjSrc;
CCARRAY_FOREACH(ccTmpArray, pObjSrc)
{
Tank* tankSrc = (Tank*)pObjSrc;
CCObject* pObjdst;
CCARRAY_FOREACH(ccTmpArray, pObjdst)
{
Tank* tankDst = (Tank*)pObjdst;
if (tankSrc != tankDst)
{
CCRect rectDst;
if (ccTmpArray->indexOfObject(pObjSrc) > ccTmpArray->indexOfObject(pObjdst))
{
//之前的坦克已经确定了要移动的位置
rectDst = tankDst->getMovedRect();
}
else
{
//还没有确定要移动的坦克
rectDst = tankDst->boundingBox();
}
if (IsRectIntersect(tankSrc->getMovedRect(), rectDst))
{
//确保在移动之前没有重合
if (!IsRectIntersect(tankSrc->boundingBox(), rectDst))
{
tankSrc->setBlock(true);
}
}
}
}
} //玩家子弹和敌方子弹之间的碰撞
CCObject* pObj;
CCARRAY_FOREACH(mEnemyTanks, pObj)
{
Bullet* enemyBullet = ((Tank*)pObj)->getBullet();
if (playerBullet->getFlyState() && enemyBullet->getFlyState())
{
if (IsRectIntersect(playerBullet->getMovedRect(), enemyBullet->getMovedRect()))
{
enemyBullet->stopFire();
playerBullet->stopFire();
break;
}
}
} //玩家子弹和敌方坦克的碰撞
CCARRAY_FOREACH(mEnemyTanks, pObj)
{
if (playerBullet->getFlyState())
{
Tank* enemyTank = (Tank*)pObj;
if (IsRectIntersect(playerBullet->getMovedRect(), enemyTank->getMovedRect()))
{
mEnemyTanks->removeObject(pObj);
enemyTank->remove();
playerBullet->stopFire();
break;
}
}
} //敌人子弹和玩家的碰撞
CCARRAY_FOREACH(mEnemyTanks, pObj)
{
Bullet* enemyBullet = ((Tank*)pObj)->getBullet();
if (enemyBullet->getFlyState())
{
if (IsRectIntersect(enemyBullet->getMovedRect(), mTank->getMovedRect()))
{
mTank->setVisible(false);
enemyBullet->stopFire();
break;
}
}
}
}

可以看到上面的坦克和坦克之间的碰撞检测,相比较上一篇中的坦克间的碰撞检测更加精确,

解决了上篇文章中坦克之间可能卡死的状况。

7.对于坦克行为的控制也做了少许修改:

void EnemyAI::tankAction(float delta)
{
CCObject* pObj;
CCARRAY_FOREACH(mEnemyTanks, pObj)
{
Tank* tank = (Tank*)pObj; //坦克按照上次的方向一直往前走
int Rotation = tank->getRotation();
tank->command((enumOrder)(Rotation / 90 + 1)); //坦克每隔一秒开一次火
tank->setBulletDelta(tank->getBulletDelta() + delta);
if (tank->getBulletDelta() > 1)
{
//开火后,如果子弹在飞行中,归零计时
if (tank->command(cmdFire))
{
tank->setBulletDelta(0.0);
}
}
}
//检测坦克之间的碰撞
collisionTest();
move();
}

上面函数在控制玩坦克行为后,检测了是否发生了碰撞,最后才调用move来移动坦克位置。

看看move函数的实现:

void EnemyAI::move()
{
mTank->move();
CCObject* pObj;
CCARRAY_FOREACH(mEnemyTanks, pObj)
{
Tank* tank = (Tank*)pObj;
//如果坦克阻塞,换个方向
if (tank->getBlock())
tank->setRotation((int)(CCRANDOM_0_1() * 3.8) * 90);
//如果上面的判断完成后,坦克根据自己的阻塞状态移动
tank->move();
}
}

move函数在检测了坦克是否阻塞,如果阻塞则随机切换坦克运行方向,

然后调用了坦克自身的move函数移动到相应位置。

最后我们来看看运行效果:

完整代码下载地址:

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

cocos2d-x游戏开发系列教程-坦克大战游戏之子弹的碰撞检测处理的更多相关文章

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

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

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

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

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

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

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

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

  5. cocos2d-x游戏开发系列教程-坦克大战游戏之子弹和地图碰撞

    上篇文章实现了坦克与地图碰撞的检测, 这篇我们继续完成子弹和地图的碰撞检测. 1.先设计一个子弹类Bullet,如下所示: class Bullet : public CCSprite { publi ...

  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. JavaSE学习总结第18天_集合框架4

      18.01 Map集合概述和特点 Map接口概述:将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值 Map接口和Collection接口的不同 1.Map是双列的,Coll ...

  2. 个人自建网店(WordPress WooCommerce on SAE)集成支付宝支付

    插件: Alipay For WooCommerce 到支付宝账户的商家服务提出申请: https://b.alipay.com/order/serviceIndex.htm 在"在线签约- ...

  3. CXF 开发 WebService

    什么是CXF: Apache CXF = Celtix + Xfire 支持多种协议: SOAP1.1,1.2 XML/HTTP CORBA(Common Object Request Broker ...

  4. background-position 个人理解

    background-position这里先说像素  百分比比较复杂background-position:xxpx xxpx  这里第一个值指的是x轴坐标  第二个值是y轴坐标这里使用的坐标系和数学 ...

  5. Netflix

    2009年Netflix举办了一场Netflix大奖赛.他们公开一批匿名数据,允许参赛团队使用以得出更好的算法.他们从获胜的团队中得到了现有算法10.06%的提升.Netflix本想再举行一场Netf ...

  6. VS2010/MFC对话框三:创建对话框类和添加控件变量

    创建对话框类和添加控件变量 前两讲中讲解了如何创建对话框资源.创建好对话框资源后要做的就是生成对话框类了.生成对话框类主要包括新建对话框类.添加控件变量和控件的消息处理函数等. 例程Addition是 ...

  7. 多线程wait()和sleep()以及InterruptedException异常

    1.核心区别: sleep用于线程控制,wait用于线程间的通信. sleep是Thread类的方法,是让线程休息一段时间,然后自动恢复运行,与其他线程无关,与同步无关,也与锁无关(拿锁时不会释放锁) ...

  8. stm32之PWM

    PWM是pulse width modulation的缩写,即脉冲宽度调制.其通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形: 1.PWM是一种对模拟信号电平进行数字编码的方法.通过高分辨率计 ...

  9. Swing布局管理器

    在Swing中使用的所有布局管理器都可以实现LayoutManager接口.Swing中有五种常见的布局管理器分别为FlowLayout.BorderLayout.GridLayout.CardLay ...

  10. 性能测试工具:AB

    ###################################################################################格式:ab -n 请求次数 -c ...