cocos2dx碰撞检测实现

时间:2021-08-24 23:33:22

本文由qinning199原创,转载请注明:http://www.cocos2dx.net/?p=146

在此场景中,我们假设有很多敌人和子弹,其中子弹可以击中敌人,并且碰撞后子弹和敌人都会随之消失。

首先,我们需要去追踪这些敌人和子弹。

我们可以为这两种物体添加tag,在这里我们给敌人添加tag=1,给子弹添加tag=2,。因为CCSprite继承自CCNode,因为已经有了setTag和getTag方法;我们可以通过这种方式来区分不同的精灵。

添加两个成员对象在HelloWorldScene.h中。用来分别存储存在的敌人和子弹。

[cpp] view plain copy
  1. protected:  
  2.     cocos2d::CCArray *_targets;  
  3.     cocos2d::CCArray *_projectiles;  

在cocos2dx中,在构造函数中初始化这两个变量,在init()函数中new,在析构函数中release。

[cpp] view plain copy
  1.  // 初始化  
  2.  _targets = new CCArray;  
  3.  _projectiles = new CCArray;  
  4.   
  5.  HelloWorld::~HelloWorld()  
  6.  {  
  7.   if (_targets)  
  8.   {  
  9.     _targets->release();  
  10.     _targets = NULL;  
  11.   }  
  12.   
  13.   if (_projectiles)  
  14.   {  
  15.     _projectiles->release();  
  16.     _projectiles = NULL;  
  17.   }  
  18.   // cpp不需要调用super释放,虚析构函数将会做这些事  
  19. }  
  20.   
  21. HelloWorld::HelloWorld()  
  22. :_targets(NULL)  
  23. ,_projectiles(NULL)  
  24. {  
  25. }  

现在更改addTarget()来添加一个新的敌人到targets数组中,并且把它的tag设置为1.

[cpp] view plain copy
  1. // 添加到数组中  
  2. target->setTag(1);  
  3. _targets->addObject(target);  

更改一下ccTouchesEnded()来添加一个新的子弹到bullets数组中,并且设置它的tag为2.

[cpp] view plain copy
  1. // 添加到_projectiles数组中  
  2. projectile->setTag(2);  
  3. _projectiles->addObject(projectile);  


接下来,更改如下的spriteMoveFinished()函数。这里我们将从相应的数组中移除一些精灵。

[cpp] view plain copy
  1.  void HelloWorld::spriteMoveFinished(CCNode* sender)  
  2.  {  
  3.    CCSprite *sprite = (CCSprite *)sender;  
  4.    this->removeChild(sprite, true);  
  5.   
  6.    if (sprite->getTag() == 1)  // target  
  7.    {  
  8.      _targets->removeObject(sprite);  
  9.   }  
  10.   else if (sprite->getTag() == 2) // projectile  
  11.   {  
  12.     _projectiles->removeObject(sprite);  
  13.   }  
  14. }  

下面的函数update()将会每帧被执行到一次,一般用来检测碰撞检测,可以移除掉碰撞的子弹和敌人。

在HelloWorldScene.h中声明它,在HelloWorldScene.cpp.定义它。

[cpp] view plain copy
  1. void HelloWorld::update(float dt)  
  2. {  
  3.     CCArray *projectilesToDelete = new CCArray;  
  4.     CCArray* targetsToDelete =new CCArray;  
  5.     CCObject* it = NULL;  
  6.     CCObject* jt = NULL;  
  7.   
  8.     CCARRAY_FOREACH(_bullet, it)  
  9.    {  
  10.        CCSprite *projectile = dynamic_cast<CCSprite*>(it);  
  11.        CCRect projectileRect = CCRectMake(  
  12.                                           projectile->getPosition().x - (projectile->getContentSize().width/2),  
  13.                                           projectile->getPosition().y - (projectile->getContentSize().height/2),  
  14.                                           projectile->getContentSize().width,  
  15.                                           projectile->getContentSize().height);  
  16.   
  17.        CCARRAY_FOREACH(_target, jt)  
  18.        {  
  19.            CCSprite *target = dynamic_cast<CCSprite*>(jt);  
  20.            CCRect targetRect = CCRectMake(  
  21.                                           target->getPosition().x - (target->getContentSize().width/2),  
  22.                                           target->getPosition().y - (target->getContentSize().height/2),  
  23.                                           target->getContentSize().width,  
  24.                                           target->getContentSize().height);  
  25.   
  26.            if (projectileRect.intersectsRect(targetRect))  
  27.            {  
  28.                targetsToDelete->addObject(target);  
  29.                projectilesToDelete->addObject(projectile);  
  30.            }  
  31.        }  
  32.    }  
  33.   
  34.    CCARRAY_FOREACH(targetsToDelete, jt)  
  35.    {  
  36.        CCSprite *target = dynamic_cast<CCSprite*>(jt);  
  37.        _target->removeObject(target);  
  38.        this->removeChild(target, true);  
  39.    }  
  40.   
  41.    CCARRAY_FOREACH(projectilesToDelete, it)  
  42.    {  
  43.        CCSprite* projectile = dynamic_cast<CCSprite*>(it);  
  44.        _bullet->removeObject(projectile);  
  45.        this->removeChild(projectile, true);  
  46.    }  
  47.   
  48.    projectilesToDelete->release();  
  49.    targetsToDelete->release();  

好了,最后的事情我们将要做的就是添加update()到计时器中,来让它每帧被调用一次,一般在onEnter()函数中添加此行代码。

[cpp] view plain copy
  1. void HelloWorld::onEnter()  
  2. {  
  3.     CCLayer::onEnter();  
  4.       
  5.     this->schedule( schedule_selector(HelloWorld::update) );  
  6.       
  7. }  

一个简单的碰撞检测模型就建立好啦~