Box2D - при создании тела во время выполнения тело не сталкивается - PullRequest
1 голос
/ 22 февраля 2012

Я работал над игрой с разрушаемым окружением, и я нашел решение, в котором я проверяю возможное разрушение в моем ContactListener объекте. Очевидно, потому что это происходит в Step(), я откладываю обработку уничтожения до момента после шага. Я делаю это путем объединения «событий уничтожения», которые необходимо обработать в обработчике контактов, а затем сразу после Step() вызова чего-то вроде contactListener->processDestructionEvents();.

Способ, которым я это делаю, - это захватить встречные приборы в событии beginContact, а затем определить угол удара, а затем использовать этот угол для радиопередачи на самом приборе. Затем я собираю вершины из b2PolygonShape прибора, а затем генерирую две новые фигуры, которые разделяются на основе точек удара и выхода луча. Исходный прибор уничтожается на теле, а затем генерируется новый прибор для первой новой формы и добавляется к исходному телу. Для второй фигуры генерируется новое тело, и эта фигура добавляется к этому новому телу.

В любом случае все работает отлично, в режиме отладки я вижу, что новые фигуры созданы и все на месте, как и должно быть. Тем не менее, я получаю действительно испорченное поведение в этой точке. Как только этот процесс завершится, ни оригинальное, ни вновь сгенерированное тело ни с чем не столкнется. Если я включу непрерывную физику, ИНОГДА динамический объект столкнется с одним из краев этих тел / приборов, но не всегда. Мне интересно, если я что-то не так делаю в своем подходе к восстановлению кузовов / приборов во время выполнения. Вот код для генерации новых объектов, любая помощь будет принята с благодарностью.

void PhysicsContactListener::processDestructionEvents() {
   if(!hasDestructionEvents) {return;}

   for(destructionEventsIterator = destructionEvents.begin(); destructionEventsIterator != destructionEvents.end(); ++destructionEventsIterator) {

      b2Filter f1, f2;
      f1.groupIndex = destructionEventsIterator->originalFixture->GetFilterData().groupIndex;
      f1.categoryBits = destructionEventsIterator->originalFixture->GetFilterData().categoryBits;
      f1.maskBits = destructionEventsIterator->originalFixture->GetFilterData().maskBits;

      f2.groupIndex = destructionEventsIterator->originalFixture->GetFilterData().groupIndex;
      f2.categoryBits = destructionEventsIterator->originalFixture->GetFilterData().categoryBits;
      f2.maskBits = destructionEventsIterator->originalFixture->GetFilterData().maskBits;

      b2PolygonShape newShape0 = destructionEventsIterator->newFixtures[0];

      b2FixtureDef fixture0Def;
      fixture0Def.shape = &newShape0;
      fixture0Def.density = 1.0f;
      fixture0Def.restitution = 0.2f;

      b2Fixture* fixture1 = destructionEventsIterator->hostBody->CreateFixture(&fixture0Def);
      fixture1->SetFilterData(f1);
      //destructionEventsIterator->hostBody->SetAwake(true);
      destructionEventsIterator->hostBody->ResetMassData();
      //destructionEventsIterator->hostBody->SetActive(true);
      destructionEventsIterator->hostBody->SetTransform(destructionEventsIterator->hostBody->GetPosition(), destructionEventsIterator->hostBody->GetAngle());

      b2BodyDef bd;
      bd.position = destructionEventsIterator->hostBody->GetPosition();
      bd.angle = destructionEventsIterator->hostBody->GetAngle();
      bd.type = destructionEventsIterator->hostBody->GetType();

      b2Body* newBody = destructionEventsIterator->hostBody->GetWorld()->CreateBody(&bd);
      b2PolygonShape* newShape1 = (b2PolygonShape*)(&destructionEventsIterator->newFixtures[1]);
      b2Fixture* fixture2 = newBody->CreateFixture(newShape1, destructionEventsIterator->hostBodyDensity);
      fixture2->SetFilterData(f2);
      newBody->SetAngularVelocity(destructionEventsIterator->hostBody->GetAngularVelocity());
      newBody->SetLinearVelocity(destructionEventsIterator->hostBody->GetLinearVelocity());
      //newBody->SetAwake(true);
      newBody->ResetMassData();
      //newBody->SetActive(true);
      newBody->SetTransform(destructionEventsIterator->hostBody->GetPosition(), destructionEventsIterator->hostBody->GetAngle());

      destructionEventsIterator->hostBody->DestroyFixture(destructionEventsIterator->originalFixture);

   }

1 Ответ

2 голосов
/ 22 февраля 2012

Две части не сталкиваются друг с другом? Посмотрите на значения categoryBits и maskBits, которые заканчиваются на каждом приборе - похоже, что каждому фрагменту даны одинаковые значения для них. Я думаю, вы просто упускаете из виду тот факт, что эти маски проверяются друг против друга в обоих направлениях, например. из исходного кода Box2D:

bool collide =
      (filterA.maskBits & filterB.categoryBits) != 0 &&
      (filterA.categoryBits & filterB.maskBits) != 0;

С другой стороны, если вы имеете в виду, что кусочки вообще ни с чем не сталкиваются и просто падают сквозь землю и падают навсегда, кроме ИНОГДА, то я могу заподозрить неправильную обмотку многоугольника.

btw a b2Filter содержит только примитивы, поэтому вы можете назначить их напрямую:

b2Filter f1 = destructionEventsIterator->originalFixture->GetFilterData();

... также, первый SetTransform и второй ResetMassData являются избыточными.

...