【问题标题】:Box2D - When creating a body at runtime, the body does not collideBox2D - 在运行时创建身体时,身体不会发生碰撞
【发布时间】:2012-03-12 05:17:23
【问题描述】:

我一直在开发一个具有可破坏环境的游戏,并且我想出了一个解决方案,我可以检查我的ContactListener 对象中可能存在的破坏。显然,因为这是在Step() 内进行的,所以我将销毁处理推迟到该步骤之后的那一刻。我通过汇集需要在联系人侦听器中处理的“破坏事件”来做到这一点,然后在Step() 之后立即调用contactListener->processDestructionEvents(); 之类的东西。

我这样做的方法是在 beginContact 事件中捕获碰撞的灯具,然后确定撞击的角度,然后使用该角度对灯具本身进行光线投射。然后我从夹具的b2PolygonShape 中抓取顶点,然后生成两个新形状,它们根据光线的冲击点和出口点进行分割。原来的fixture在body上被销毁,然后为第一个新的shape生成一个新的fixture,加入到原来的body上。对于第二个形状,会生成一个新的实体并将该形状添加到这个新实体中。

无论如何,一切都很好,在调试视图中,我可以看到新形状已经生成并且全部到位,它们应该是。但是,此时我的行为真的很糟糕。一旦这个过程完成,原始物体和新生成的物体都不会与任何物体发生碰撞。如果我启用连续物理,有时动态对象会与这些物体/固定装置的边缘之一发生碰撞,但并非总是如此。我想知道我在运行时重建车身/夹具的方法是否做错了。这是生成新对象的代码,任何帮助将不胜感激。

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);

   }

【问题讨论】:

  • 可以肯定的是,任何物体都不会与任何东西发生碰撞,这意味着它们会从地面坠落到深渊......?还是只是两个物体不相互碰撞?
  • 没错,它们根本不会与任何东西发生碰撞。如果我将它们设置为静态,则什么都没有。如果我将它们设置为动态,它们就会掉入深渊。

标签: c++ box2d


【解决方案1】:

这两块不会互相碰撞?看看每个夹具最终得到的 categoryBits 和 maskBits 值 - 看起来每件作品都被赋予了相同的值。我的猜测是你只是忽略了这些掩码是双向检查的事实,例如。来自 Box2D 源代码:

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

另一方面,如果您的意思是碎片完全没有碰撞并且只是从地面永远掉下来,除了有时,那么我可能会怀疑多边形缠绕不正确。

顺便说一句,b2Filter 只包含原语,因此您可以直接分配它们:

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

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

【讨论】:

  • 谢谢,我会尽快回复您。我意识到我的示例中包含垃圾代码,这几乎只是我随机尝试不同内容的复制和粘贴,因为我完全没有想法哈哈。
  • P.S. - 如果多边形缠绕不好,那不会是错误吗?我认为 box2D 中有一个 assert() 语句在运行时在调试中检查了这一点。
  • 你是对的,非常感谢。这是一个曲折的问题。我正在将 box2D 论坛上关于可破坏物体的旧帖子中的代码移植到最新的 box2D 中,在我使用的代码中,这些检查仅限于三角体。我正在使用四边形。解决方案是使用来自 SVN 的 box2D 扩展 byPolygon 和 DecomposeConvexAndAddTo(poly, body, def);方法。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-25
  • 2013-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多