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

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

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. python中decorator

    先讲一下python中的@符号 看下面代码 @f @f2 def fun(args, args2, args3, args4, ……): pass 上面代码相当于 def fun(args, args ...

  2. WebSphere优化

    优化WebSphere WebSphere里的profile刚配完,一般默认的heapsize即Xms与Xmx值只有256mb,而IBM WAS是几个J2EE服务器中最吃内存的机器,在布署一些EAR应 ...

  3. 设计模式值六大原则——里氏替换原则(LSP)

    里氏替换原则(Liskov Substitution Principel)是解决继承带来的问题. 继承的优点: 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性: 提高代码的重用性: 子类 ...

  4. 建立dblink,clob

    建立dblink的方法, 如果有个测试库A,要访问生产库里的数据,那么可以直接在测试库A里建立一个dblink,然后数据库A就可以直接访问测试库B的数据了. -- 删除已有的dblink drop d ...

  5. 浅谈Linux ftp服务器相关配置

    首先我们需要在Linux系统下安装FTP服务器  Ubuntu sudo apt-get install.......  centos yun....... 然后,我们要配置vsftpd.conf文件 ...

  6. 405 HTTP method GET is not supported by this URL

    孙鑫java web开发详解P285里面提交Get网站弹出提示405 HTTP method GET is not supported by this URL 原因父类doGet()方法未覆盖. 应写 ...

  7. 命名空间“System.Web.Mvc”中不存在类型或命名空间“Ajax”(是否缺少程序集引用?)

    原文  http://www.cnblogs.com/LJP-JumpAndFly/p/4109602.html 好吧,非常激动的说,这个问题搞了我一个晚上,网上的帖子太少了,好像不超过2篇,而且说得 ...

  8. mysql基础(mysql数据库导入到处) 很基础很实用

    一.MYSQL的命令行模式的设置:桌面->我的电脑->属性->环境变量->新建->PATH=“:path\mysql\bin;”其中path为MYSQL的安装路径.二.简 ...

  9. Outlook Anywhere 每次要输入密码

    客户端加入域Exchange OutlookAnywhere使用NTLM验证 2007 2010:

  10. QT学习 之 事件与事件过滤器(分为五个层次)

    事件 在Qt中,事件是作为对象处理的,所有事件对象继承自抽象类QEvent.此类用来表示程序内部发生或者来自于外部但应用程序应该知道的动作.事件能够能过被 QObject 的子类接受或者处理,但是通常 ...