在上篇我们加上了简单的坦克之间的碰撞检测,这篇我们继续加上子弹之间,
子弹与坦克之间的碰撞检测,对于上一篇碰撞处理不太完美的地方我们继续改进。
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; } } }
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