我在我的 iPhone 游戏中使用 cocos2d 和 box2d。
当两个球互相撞击时,我会通过 ContactListener 收到通知,并且我有两个身体的参考。
我可以摧毁他们两个,但我想推迟。
因此,两个球相互撞击,它们弹开,然后在一秒钟后消失。
我在我的 iPhone 游戏中使用 cocos2d 和 box2d。
当两个球互相撞击时,我会通过 ContactListener 收到通知,并且我有两个身体的参考。
我可以摧毁他们两个,但我想推迟。
因此,两个球相互撞击,它们弹开,然后在一秒钟后消失。
在 BeginContact 或 EndContact 中启动一个计时器,然后移除 Body。
我使用一个类(如下)进行碰撞处理,该类过滤掉重复的碰撞并通过消息传递系统向“实体”对象发送通知。
注意:这是更大代码库的一部分;如果您需要澄清,请随时提出任何问题,因为代码不在这里。
class EntityContactListener : public ContactListener
{
private:
GameWorld* _gameWorld;
EntityContactListener() {}
typedef struct
{
Entity* entA;
Entity* entB;
} CONTACT_PAIR_T;
vector<CONTACT_PAIR_T> _contactPairs;
public:
virtual ~EntityContactListener() {}
EntityContactListener(GameWorld* gameWorld) :
_gameWorld(gameWorld)
{
_contactPairs.reserve(128);
}
void NotifyCollisions()
{
Message* msg;
MessageManager& mm = GameManager::Instance().GetMessageMgr();
for(uint32 idx = 0; idx < _contactPairs.size(); idx++)
{
Entity* entA = _contactPairs[idx].entA;
Entity* entB = _contactPairs[idx].entB;
//DebugLogCPP("Contact Notification %s<->%s",entA->ToString().c_str(),entB->ToString().c_str());
msg = mm.CreateMessage();
msg->Init(entA->GetID(), entB->GetID(), Message::MESSAGE_COLLISION);
mm.EnqueueMessge(msg, 0);
msg = mm.CreateMessage();
msg->Init(entB->GetID(), entA->GetID(), Message::MESSAGE_COLLISION);
mm.EnqueueMessge(msg, 0);
}
_contactPairs.clear();
}
void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{
}
// BEWARE: You may get multiple calls for the same event.
void BeginContact(b2Contact* contact)
{
Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData();
Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData();
//DebugLogCPP("Begin Contact %s->%s",entA->ToString().c_str(),entB->ToString().c_str());
if(entA->GetGroupID() == entB->GetGroupID())
{ // Can't collide if they are in the same group.
return;
}
assert(entA != NULL);
assert(entB != NULL);
for(uint32 idx = 0; idx < _contactPairs.size(); idx++)
{
if(_contactPairs[idx].entA == entA && _contactPairs[idx].entB == entB)
return;
// Not sure if this is needed...
if(_contactPairs[idx].entA == entB && _contactPairs[idx].entA == entB)
return;
}
CONTACT_PAIR_T pair;
pair.entA = entA;
pair.entB = entB;
_contactPairs.push_back(pair);
}
// BEWARE: You may get multiple calls for the same event.
void EndContact(b2Contact* contact)
{
/*
Entity* entA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData();
Entity* entB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData();
DebugLogCPP("End Contact %s->%s",entA->ToString().c_str(),entB->ToString().c_str());
*/
}
};
一旦您的实体收到消息,每个实体都可以启动一个计时器并在需要时自行销毁。或者你可以让你的消息延迟排队,以便它们在你的游戏的消息处理阶段被销毁(如果你有的话)。这很好,因为它可以让您明确控制破坏发生的时间,并且不会在物理过程中发生,这确实会导致引擎出现问题。
这是解决您问题的完美演示