Box2d 看似随机创建特定的主体和夹具

Box2d creates specific body and fixture seemingly at random

我使用 Libgdx 和 Box2d 创建了一个类似于 Not Tetris 2 的 android 应用程序。

它可以成功地从世界中移除一个切片,这显然涉及复制多个物体和 destroying/creating fixtures。然而,看似随机地,一个带有 2x2 固定装置的物体会出现。 body 和 fixture 在创建时使用与其周围对象相关的信息显示,因此我将其创建范围缩小到以下功能:

Body duplicateBody(Body original){
    BodyDef d = new BodyDef();
    d.position.set(original.getPosition());
    d.angle = original.getAngle();
    d.linearVelocity.set(original.getLinearVelocity());
    d.angularVelocity = original.getAngularVelocity();

    Body dup = world.createBody(d);
    dup.setType(BodyDef.BodyType.DynamicBody);

    return dup;
}

我在 2 个不同的上下文中使用此函数:

  1. 如果 "slice" 将主体一分为二,则制作主体的副本 -- 然后我将下面的固定装置转移到它上面。
  2. 当夹具在线下方时,它会被添加到为下方的夹具创建的主体中
  3. 当固定装置组分开时制作主体的副本

我注释掉了负责第三个实例的代码,但仍然生成了 2x2 框,所以这里是与其他函数相关的函数:

...
if (below && !above) {
    //copy fixture, add copy to lower body and remove original
    Body top = fixture.getBody();
    FixtureDef n = new FixtureDef();
    PolygonShape s = new PolygonShape();
    s.set(getLocalVerticesOfFixture(fixture));
    n.shape = s;
    n.density = fixture.getDensity();
    //create lower body if a lower one doesn't already exist
    if (!topBottomPairs.containsKey(top)) {
        Body dup = duplicateBody(top);
        topBottomPairs.put(top, dup);
    }
    //delete fixture
    remove.add(fixture);
    Fixture f = topBottomPairs.get(top).createFixture(n);
    s.dispose();
}
...
if (below && above) {
    //copy fixture, add copy to lower body, but keep original on upper as it needs to split
    FixtureDef n = new FixtureDef();
    PolygonShape s = new PolygonShape();
    s.set(getLocalVerticesOfFixture(fixture));
    n.shape = s;
    n.density = fixture.getDensity();

    Body top = fixture.getBody();
    //create lower body if a lower one doesn't already exist
    if (!topBottomPairs.containsKey(top)) {
        Body dup = duplicateBody(top);
        topBottomPairs.put(top, dup);
    }
    Fixture second = topBottomPairs.get(top).createFixture(n);
    s.dispose();
}

....

private Vector2[] getLocalVerticesOfFixture(Fixture fixture) {
    PolygonShape shape = ((PolygonShape) fixture.getShape());
    Vector2[] localVertices = new Vector2[shape.getVertexCount()];
    for (int i = 0; i < shape.getVertexCount(); i++) {
        localVertices[i] = new Vector2();
        shape.getVertex(i, localVertices[i]);
    }
    return localVertices;
}

我还有这个删除夹具功能,它在我要删除的所有灯具上运行:

private void smartDeleteFixture(Fixture f){
    f.getBody().destroyFixture(f);
    if(f.getBody().getFixtureList().size == 0){
        world.destroyBody(f.getBody());
    }
}

我没有在任何地方创建顶点,更不用说 2x2 形状的固定装置了。我想知道这个复制函数是否有任何缺陷,或者我是否偶然发现了 box2d 使用的一些 "default shape"。

编辑:我删除了与 box2d 物体操作无关的任何内容。希望有帮助

删除了这个问题,因为我决定进行一次重大的重新编码,希望这能解决我的问题。它没有,但我找到了原因。

我查看了 box2d,在多边形形状中发现了几个与此类似的代码实例 class:

if (n < 3)
{
    // Polygon is degenerate.
    b2Assert(false);
    SetAsBox(1.0f, 1.0f);
    return;
}

这些实例在各种操作后检查顶点的数量,如果少于 3 个,则将形状变成 2x2 的框。这些操作之一使形状凸起。另一个检查顶点是否靠近(靠近 0.0025f),如果是则删除一个。

就我而言,问题很简单。我的一些顶点彼此之间的距离小于 0.0025f,导致它们被删除,顶点数下降到 3 以下,一个断言被忽略,然后我的形状变成了一个 2x2 的盒子。我希望这对某人有所帮助。