JBox2D Body 曾经存在,现在为空?

发布于 2025-01-05 01:34:50 字数 1677 浏览 1 评论 0原文

一个我无法追踪的奇怪错误。我已经实现了一个 ContactListener 类来处理 Android 游戏中的碰撞。在 beginContact(Contact arg0) 方法中,我可以看到 arg0 中的两个实体在那里,并被压入堆栈。在调用 world.step() 之后,我运行自己的 handleCollisions() 方法,在该方法中弹出 Contact 对象并执行一些游戏逻辑。然而,有时当我弹出一个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;
        }

        ...

    }

}

A strange bug I can't track down. I've implemented a ContactListener class for handling collisions in my Android game. In the beginContact(Contact arg0) method I can see that the two bodies in arg0 is there, and pushed onto a stack. Right after calling world.step() I run my own handleCollisions() method, where I pop off the Contact objects and do some game logic. However, occasionally when I pop off a Contact, one or both of its bodies are null.

The Contact goes in the stack with its bodies there, but it comes out with null bodies. I don't know why this is occurring, and more importantly, I can't find when this is occurring. To my knowledge, none of my code elsewhere is removing the bodies, but then again there could be side effects I'm unaware of. It doesn't help that this doesn't always happen. Typically it occurs when there's several collisions occurring.

Anyone have any ideas on what might remove the bodies? Or, does anyone know of a way to track the bodies to determine when they become null?

Below is some code which may or may not be helpful:

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

        ...

    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

失去的东西太少 2025-01-12 01:34:50

联系人会被集中并重复使用,因此我不建议使用这种方法。相反,我只会缓冲您需要的信息(可能是两个实体)。 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() 方法并缓冲一些针对您的游戏进行更优化的内容,例如仅存储碰撞体或其他内容。

Contacts are pooled and re-used, so I would not recommend using this approach. Instead I would buffer only the information you need (which is probably the two bodies). The jbox2d testbed handles it this way:

First we have a contact point:

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

And then we listen like so:

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

This would probably be a bit overkill for your purposes, as it executes this logic for every single contact. Instead you can use the beginContact() and endContact() methods and buffer something a little more optimized with your game, like just storing the colliding bodies or something.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文