Box2D - 在运行时创建主体时,主体不会发生碰撞

时间:2012-02-21 21:17:16

标签: c++ box2d

我一直在开发具有可破坏环境的游戏,我想出了一个解决方案,我在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 个答案:

答案 0 :(得分:2)

两件不相互碰撞?看一下每个夹具最终得到的categoryBits和maskBits值 - 看起来每件都给出了相同的值。我的猜测是你只是忽略了这两种方式相互检查这些面具的事实,例如。来自Box2D源代码:

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

另一方面,如果你的意思是这些碎片根本没有任何东西碰撞而只是从地面掉下来并永远地掉下来,除了有些东西,那么我可能怀疑多边形缠绕不正确。

btw b2Filter只保存基元,因此您可以直接分配它们:

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

...另外,第一个SetTransform和第二个ResetMassData是多余的。