删除后联系处理程序中的Box2D Null Fixture

时间:2014-05-22 18:53:06

标签: java libgdx box2d

我正在使用Libgdx的box2d实现。

我从世界中删除了一个正文后遇到空指针错误。我已将问题跟踪到我的联系人监听器,我正在测试夹具的过滤器与另一个夹具,以查看是否应该处理碰撞。问题是其中一个灯具是空的。最初你会想,好吧所以只处理非空夹具的碰撞,但是如果我不知道夹具是什么结束了接触,就不可能知道什么是和非接触非空夹具。

在我进入代码之前,我保证通过将主体添加到稍后要处理的队列中来使实际的world.destroyBody(body)调用物理步骤之外。此外,主体在更新循环中排队,这发生在world.step()

之前

(注意:实体基本上是主体的包装器)

这是主要的更新循环

@Override
public void render() {
    processDestroyQueue();

    sm.update();   //Calls entity update functions, where the entity is added to the q
    camera.update();


    //Step
    world.step(STEP, 6, 2); //Step == 1/60f

    //... removed rendering stuff
}

这是add to queue function和processDestroyQueue()

public void destroy(Entity ent){
    destroyQueue.add(ent);
}

private void processDestroyQueue(){
    Entity ent;
    while((ent = destroyQueue.poll()) != null){
        world.destroyBody(ent.body());
        ent.dispose();
        entities.remove(ent);
    }
}

最后这里是联系处理程序

public class ContactHandler implements ContactListener {

@Override
public void beginContact(Contact contact) {
    Fixture fixA = contact.getFixtureA();
    Fixture fixB = contact.getFixtureB();

    parseContact(true, fixA, fixB, contact);
}

@Override
public void endContact(Contact contact) {
    Fixture fixA = contact.getFixtureA();
    Fixture fixB = contact.getFixtureB();

    parseContact(false, fixA, fixB, contact);
}

@Override
public void preSolve(Contact contact, Manifold oldManifold) {
    // TODO Auto-generated method stub

}

@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
    // TODO Auto-generated method stub

}

public void parseContact(boolean begin, Fixture fixA, Fixture fixB, Contact contact){
    System.out.println("FixtureA: " + fixA);
    System.out.println("FixtureB: " + fixB);
    if( (fixA.getFilterData().categoryBits & fixB.getFilterData().maskBits) != 0 ){
        sendContact(begin, fixA, fixB, contact);
        sendContact(begin, fixB, fixA, contact);
    }else if( (fixB.getFilterData().categoryBits & fixA.getFilterData().maskBits) != 0 ){
        sendContact(begin, fixA, fixB, contact);
        sendContact(begin, fixB, fixA, contact);
    }
}

public void sendContact(boolean begin, Fixture fixA, Fixture fixB, Contact contact){
    Object dataA = fixA.getUserData();
    Object dataB = fixB.getUserData();

    if(dataA instanceof FixtureData && dataB instanceof FixtureData){
        FixtureData fixtureDataB = (FixtureData)dataB;
        FixtureData fixtureDataA = (FixtureData)dataA;
        fixtureDataA.contact(fixB, contact, begin);
        fixtureDataB.contact(fixA, contact, begin);
    }
}

}

最后是错误:

Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.gearworks.game.ContactHandler.parseContact(ContactHandler.java:42)
at com.gearworks.game.ContactHandler.endContact(ContactHandler.java:24)
at com.badlogic.gdx.physics.box2d.World.endContact(World.java:903)
at com.badlogic.gdx.physics.box2d.World.jniDestroyBody(Native Method)
at com.badlogic.gdx.physics.box2d.World.destroyBody(World.java:322)
at com.gearworks.Client.processDestroyQueue(Client.java:189)
at com.gearworks.Client.render(Client.java:118)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:206)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:114)

从它的外观来看,Box2D只是擦除了夹具,然后调度它的结束接触事件。我需要该夹具才能最终接触,以便我知道哪个夹具已完成其接触。我的实施错了吗?或者这就是box2D如何工作,我需要弄清楚其他一些方法?

1 个答案:

答案 0 :(得分:1)

这确实是libgdx中的一个错误:

https://github.com/libgdx/libgdx/issues/1381

https://github.com/libgdx/libgdx/pull/1837

我认为您只需要更新版本的源代码。