1

一个我无法追踪的奇怪错误。我已经实现了一个ContactListener类来处理我的 Android 游戏中的碰撞。在该beginContact(Contact arg0)方法中,我可以看到其中的两个物体在arg0那里,并被推到堆栈上。调用后立即world.step()运行我自己的handleCollisions()方法,在其中弹出Contact对象并执行一些游戏逻辑。但是,偶尔当我弹出 a 时Contact,它的一个或两个主体都为空。

Contact其主体放在堆栈中,但它以空主体出现。我不知道为什么会发生这种情况,更重要的是,我找不到发生这种情况的时间。据我所知,我在其他地方的任何代码都没有删除尸体,但是再次出现我不知道的副作用。这并不总是发生,这无济于事。通常它发生在发生多次碰撞时。

有人对什么可以移除尸体有任何想法吗?或者,有没有人知道跟踪尸体以确定它们何时变为空的方法?

以下是一些可能有用也可能没有帮助的代码:

public class ConcreteContactListener implements ContactListener
{
    private Stack<Contact> contacts;

    public ConcreteContactListener()
    {
        contacts = new Stack<Contact>();
    }

    @Override
    public void beginContact(Contact arg0)
    {
        contacts.push(arg0);
        System.out.println("push: " + arg0.m_fixtureA.m_body);
    }


public int handleCollisions(ArrayList<Ball> balls, World world, ArrayList<Ball> smears, SoundEffects sfx, Combos combos)
{
    int score = 0;

    while (!contacts.isEmpty())
    {
        Contact contact = contacts.pop();
        System.out.println("Contact: " + contact.m_fixtureA.m_body);
        int a = -1;
        int b = -1;

        for (int i = 0; i < balls.size(); i++)
        {
            System.out.println("Ball: " + balls.get(i).getBody());
            if (contact.m_fixtureA.m_body.equals(balls.get(i).getBody()))
                 a = i;
            else if (contact.m_fixtureB.m_body.equals(balls.get(i).getBody()))
                b = i;
        }

        ...

    }

}
4

1 回答 1

2

联系人被汇集和重复使用,所以我不建议使用这种方法。相反,我只会缓冲您需要的信息(可能是两个机构)。jbox2d 测试台以​​这种方式处理它:

首先我们有一个联络点:

public class ContactPoint {
    public Fixture fixtureA;
    public Fixture fixtureB;
    public final Vec2 normal = new Vec2();
    public final Vec2 position = new Vec2();
    public PointState state;
}

然后我们像这样听:

public void beginContact(Contact contact) {
}

public void endContact(Contact contact) {
}

public void postSolve(Contact contact, ContactImpulse impulse) {
}

private final PointState[] state1 = new PointState[Settings.maxManifoldPoints];
private final PointState[] state2 = new PointState[Settings.maxManifoldPoints];
private final WorldManifold worldManifold = new WorldManifold();

public void preSolve(Contact contact, Manifold oldManifold) {
    Manifold manifold = contact.getManifold();

    if (manifold.pointCount == 0) {
        return;
    }

    Fixture fixtureA = contact.getFixtureA();
    Fixture fixtureB = contact.getFixtureB();

    Collision.getPointStates(state1, state2, oldManifold, manifold);

    contact.getWorldManifold(worldManifold);

    for (int i = 0; i < manifold.pointCount
            && pointCount < MAX_CONTACT_POINTS; i++) {
        ContactPoint cp = points[pointCount];
        cp.fixtureA = fixtureA;
        cp.fixtureB = fixtureB;
        cp.position.set(worldManifold.points[i]);
        cp.normal.set(worldManifold.normal);
        cp.state = state2[i];
        ++pointCount;
    }
}

出于您的目的,这可能有点矫枉过正,因为它为每个联系人执行此逻辑。相反,您可以使用beginContact()andendContact()方法并缓冲一些与您的游戏更优化的内容,例如仅存储碰撞体或其他内容。

于 2012-02-12T03:09:21.310 回答