我一直在尝试使用Ray Wenderlich教程在cocos2d中进行碰撞检测,但每当我试图销毁b2Body时,只要对象发生碰撞,我就会得到inline b2Body* b2Fixture::GetBody() { return m_body; }
。我看过类似的问题,但似乎没有一个对我有用。这是我的tick方法;问题始于" std :: vector",它运行正常之前的代码,只是检测两个物体之间的碰撞并且每次都破坏b2Bodies会给我一个错误:
`
(void)tick:(ccTime) dt {
_world->Step(dt, 10, 10);
...some code that works fine...then here when trying to delete the bodies:
std::set<b2Body *>toDestroy;
std::set<MyContact>::iterator pos;
for(pos = _contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
bodyA = contact.fixtureA->GetBody();
bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
spriteA = (__bridge CCSprite *) bodyA->GetUserData();
spriteB = (__bridge CCSprite *) bodyB->GetUserData();
if (((spriteA.tag == 411 || spriteA.tag == 412) && spriteB.tag == 8))
{
//Remove CCSprites
[self removeBall];
for(CCSprite *tile4 in row4){
[self removeTiles];
[row4 removeObject:tile4];
[childrenToDestroy addObject:tile4];
}
//Remove b2bodies by adding them to array
toDestroy.insert(bodyA);
toDestroy.insert(bodyB);
}
}
}
std::set<b2Body *>::iterator pos2;
for(pos2 = toDestroy.begin(); pos2 != toDestroy.end(); ++pos2) {
b2Body *body = *pos2;
if (body->GetUserData() != NULL)
{
body->SetActive(false);
_world->DestroyBody(body);
}
}
这部分代码看起来正确,但后来我在样板文件中得到错误&#34; stl_function.h&#34;说&#34;二进制表达式的操作数无效(&#39; const MyContact&#39;和&#39; const MyContact&#39;)&#34;它说它在我的联系人监听文件中找到了:
#import "MyContactListener.h"
MyContactListener::MyContactListener() : _contacts() {
}
MyContactListener::~MyContactListener() {
}
void MyContactListener::BeginContact(b2Contact* contact) {
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
_contacts.insert(myContact); <------------//Says "7.In instantiation of member function 'std::set<MyContact, std::less<MyContact>, std::allocator<MyContact> >::insert' requested here"
}
void MyContactListener::EndContact(b2Contact* contact) {
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
std::set<MyContact>::iterator pos;
pos = std::find(_contacts.begin(), _contacts.end(), myContact);
if (pos != _contacts.end()) {
_contacts.erase(pos);
}
}
void MyContactListener::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) {
}
void MyContactListener::PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) {
}
答案 0 :(得分:0)
仅在两个步骤之间移除实体。在时间步长期间调用碰撞回调,因此您应该记住要移除的某些实体(例如,添加到全局数组),然后在下一步销毁它们。更多细节there。
答案 1 :(得分:0)
为了使用std :: set,您的元素将由键(如地图)存储。所以你需要定义&lt;运营商。 Look for more information.
类似的东西:
struct Data
{
int x;
int y;
bool operator<(const Data& rhs) const
{
return x < rhs.x;
}
};
void InsertData(const Data& data)
{
std::set<Data> dataSet;
dataSet.insert(data);
}
我发现联系人监听器在冲突解决期间在同一个主体上给出了多个“命中”。这导致了一些问题,因为实体多次收到有关冲突的通知,多次被破坏,睡眠丢失等等。
我写了一个联系人监听器(下面),它自动检查重复项并排除它们。这按预期工作:
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());
*/
}
};
在这个代码库中,有一个“MessageManager”接收在物理之后调用的消息,并处理冲突消息,并将它们传递给实体。如果您愿意,可以将NotifyCollisions代码修改为您的销毁。
这有用吗?