最新文章
Cocos2d-x游戏开发实例详解7:对象释放时机
03-25 13:59
Cocos2d-x游戏开发实例详解6:自动释放池
03-25 13:55
Cocos2d-x游戏开发实例详解5:神奇的自动释放
03-25 13:49
Cocos2d-x游戏开发实例详解4:游戏主循环
03-25 13:44
Cocos2d-x游戏开发实例详解3:无限滚动地图
03-25 13:37
Cocos2d-x游戏开发实例详解2:开始菜单续
03-25 13:32
cocos2dx 多个物体碰撞检测
在一个场景中,若存在多个敌人和子弹,且子弹可以击中敌人,碰撞后子弹和敌人都会消失,我们可以使用 cocos2dx 实现多个物体的碰撞检测。以下是详细步骤:
1. 追踪敌人和子弹
为了区分敌人和子弹,我们可以为这两种物体添加 tag。给敌人添加 tag = 1,给子弹添加 tag = 2。由于 CCSprite 继承自 CCNode,已经具备 setTag 和 getTag 方法,通过这种方式能够区分不同的精灵。
在 HelloWorldScene.h 中添加两个成员对象,分别用于存储存在的敌人和子弹:
protected:
cocos2d::CCArray *_targets;
cocos2d::CCArray *_projectiles;
在 cocos2dx 中,需要在构造函数中初始化这两个变量,在 init() 函数中进行 new 操作,在析构函数中进行 release 操作:
// 构造函数
HelloWorld::HelloWorld()
: _targets(NULL)
, _projectiles(NULL)
{
}
// init 函数
// 初始化
_targets = new CCArray;
_projectiles = new CCArray;
// 析构函数
HelloWorld::~HelloWorld()
{
if (_targets)
{
_targets->release();
_targets = NULL;
}
if (_projectiles)
{
_projectiles->release();
_projectiles = NULL;
}
// cpp 不需要调用 super 释放,虚析构函数将会做这些事
}
2. 添加敌人和子弹到数组
添加敌人
更改 addTarget() 函数,将新的敌人添加到 targets 数组中,并将其 tag 设置为 1:
// 添加到数组中
target->setTag(1);
_targets->addObject(target);
添加子弹
更改 ccTouchesEnded() 函数,将新的子弹添加到 projectiles 数组中,并将其 tag 设置为 2:
// 添加到 _projectiles 数组中
projectile->setTag(2);
_projectiles->addObject(projectile);
3. 移除精灵
更改 spriteMoveFinished() 函数,从相应的数组中移除一些精灵:
void HelloWorld::spriteMoveFinished(CCNode* sender)
{
CCSprite *sprite = (CCSprite *)sender;
this->removeChild(sprite, true);
if (sprite->getTag() == 1) // target
{
_targets->removeObject(sprite);
}
else if (sprite->getTag() == 2) // projectile
{
_projectiles->removeObject(sprite);
}
}
4. 碰撞检测
update() 函数会每帧执行一次,通常用于检测碰撞,并移除碰撞的子弹和敌人。在 HelloWorldScene.h 中声明该函数,在 HelloWorldScene.cpp 中定义:
void HelloWorld::update(float dt)
{
CCArray *projectilesToDelete = new CCArray;
CCArray* targetsToDelete = new CCArray;
CCObject* it = NULL;
CCObject* jt = NULL;
CCARRAY_FOREACH(_projectiles, it)
{
CCSprite *projectile = dynamic_cast<CCSprite*>(it);
CCRect projectileRect = CCRectMake(
projectile->getPosition().x - (projectile->getContentSize().width / 2),
projectile->getPosition().y - (projectile->getContentSize().height / 2),
projectile->getContentSize().width,
projectile->getContentSize().height);
CCARRAY_FOREACH(_targets, jt)
{
CCSprite *target = dynamic_cast<CCSprite*>(jt);
CCRect targetRect = CCRectMake(
target->getPosition().x - (target->getContentSize().width / 2),
target->getPosition().y - (target->getContentSize().height / 2),
target->getContentSize().width,
target->getContentSize().height);
if (projectileRect.intersectsRect(targetRect))
{
targetsToDelete->addObject(target);
projectilesToDelete->addObject(projectile);
}
}
}
CCARRAY_FOREACH(targetsToDelete, jt)
{
CCSprite *target = dynamic_cast<CCSprite*>(jt);
_targets->removeObject(target);
this->removeChild(target, true);
}
CCARRAY_FOREACH(projectilesToDelete, it)
{
CCSprite* projectile = dynamic_cast<CCSprite*>(it);
_projectiles->removeObject(projectile);
this->removeChild(projectile, true);
}
projectilesToDelete->release();
targetsToDelete->release();
}
5. 调用 update 函数
最后,将 update() 函数添加到计时器中,使其每帧被调用一次。一般在 onEnter() 函数中添加以下代码:
void HelloWorld::onEnter()
{
CCLayer::onEnter();
this->schedule(schedule_selector(HelloWorld::update));
}
至此,一个简单的 cocos2dx 多个物体碰撞检测模型就建立好了。