Box2D обнаружение столкновений
У меня есть некоторые проблемы с обнаружением столкновений. Дело в том, что столкновение обнаружено слишком поздно, когда два сталкивающихся тела перекрывают друг друга. Движется только одно тело, остальные статические. Тело перемещается с помощью функции SetTransform() и копирует движения спрайта. Вот мой код из метода scheduleUpdate и класса ContactListener
- (void)update:(ccTime)deltaTime {
std::vector<b2Body *>toDestroy;
std::vector<MyContact>::iterator pos;
for (pos=_contactListener->_contacts.begin();
pos != _contactListener->_contacts.end(); ++pos) {
MyContact contact = *pos;
b2Body *bodyA = contact.fixtureA->GetBody();
b2Body *bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() != NULL && bodyB->GetUserData() != NULL) {
CCSprite *spriteA = (CCSprite *) bodyA->GetUserData();
CCSprite *spriteB = (CCSprite *) bodyB->GetUserData();
// Contact detected between spriteA and spriteB
}
}
}
ContactListener.h
#import "Box2D.h"
#import <vector>
#import <algorithm>
struct MyContact {
b2Fixture *fixtureA;
b2Fixture *fixtureB;
bool operator==(const MyContact& other) const
{
return (fixtureA == other.fixtureA) && (fixtureB == other.fixtureB);
}
};
class MyContactListener : public b2ContactListener {
public:
std::vector<MyContact>_contacts;
MyContactListener();
~MyContactListener();
virtual void BeginContact(b2Contact* contact);
virtual void EndContact(b2Contact* contact);
virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse);
};
ContactListener.mm
#import "MyContactListener.h"
MyContactListener::MyContactListener() : _contacts() {
}
MyContactListener::~MyContactListener() {
}
void MyContactListener::BeginContact(b2Contact* contact) {
// We need to copy out the data because the b2Contact passed in
// is reused.
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
_contacts.push_back(myContact);
}
void MyContactListener::EndContact(b2Contact* contact) {
MyContact myContact = { contact->GetFixtureA(), contact->GetFixtureB() };
std::vector<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) {
}
2 ответа
Я бы не рекомендовал использовать setTransform
для движущихся тел. Чтобы все работало нормально, тела должны двигаться, применяя forces/impulses
им. Странные вещи могут случиться, если вы "вручную" меняете положение тела.
Тем не менее, трудно понять, что происходит, не пытаясь на самом деле ваш код, но при условии, что код в порядке (и это setTransform
не имеет ничего общего) проблема может быть в самих телах; Я бы начал проверять, что все ваши фигуры convex polygons
,
Да, вы не должны использовать setTransform для перемещения тел, вместо этого используйте силы и импульсы, как сказал ssantos. То, что также может произойти, - в случае столкновения двух динамических тел столкновение обнаруживается после перекрытия приборов. Чтобы избежать этого, вы можете установить тело как "пулю", которое включает CCD, Непрерывное обнаружение столкновений. Это дороже, так как столкновение оценивается для этого тела постоянно, а не только тогда, когда два AABB перекрываются.