1

追跡できない奇妙なバグ。ContactListenerAndroid ゲームで衝突を処理するためのクラスを実装しました。このbeginContact(Contact arg0)メソッドでは、2 つのボディarg0がそこにあり、スタックにプッシュされていることがわかります。呼び出した直後world.step()に独自のhandleCollisions()メソッドを実行し、そこでContactオブジェクトを取り出してゲーム ロジックを実行します。ただし、 をポップするContactと、ボディの一方または両方が null になることがあります。

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

連絡先はプールされて再利用されるため、このアプローチの使用はお勧めしません。代わりに、必要な情報 (おそらく 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()代わりに、およびメソッドを使用してendContact()、衝突するボディなどを格納するなど、ゲームに合わせてもう少し最適化されたものをバッファリングできます。

于 2012-02-12T03:09:21.310 に答える