【问题标题】:How to handle Null Pointer Exception in libGDX's Box2D ContactListener?如何处理 libGDX 的 Box2D ContactListener 中的空指针异常?
【发布时间】:2013-07-27 19:39:16
【问题描述】:

大家怎么了,

我正在通过 libGDX 在 Box2D 中启发式地生成 Pong 克隆。 Null 指针异常源自我试图在其中实现分数逻辑的 ContactListener 的 beginContact() 方法。

Box2D 世界使用两个独立的 EdgeShape 作为传感器,用于在与球碰撞时增加分数变量(查看附图)。 Ball 与两个 EdgeShapes 之间的碰撞逻辑有效,但 Ball 与 Box2D 世界中的任何其他对象之间的碰撞会使程序崩溃。

堆栈跟踪:

Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.ckq3r.Pong.screens.GameScreen$2.beginContact(GameScreen.java:491)
at com.badlogic.gdx.physics.box2d.World.beginContact(World.java:876)
at com.badlogic.gdx.physics.box2d.World.jniStep(Native Method)
at com.badlogic.gdx.physics.box2d.World.step(World.java:602)
at com.ckq3r.Pong.screens.GameScreen.render(GameScreen.java:99)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.ckq3r.Pong.PongGame.render(PongGame.java:236)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:204)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:112)

有问题的代码:

    /**Box2D contact listener**/
private void createContactListener() {
    world.setContactListener(new ContactListener() {

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

            Gdx.app.log("beginContact", "between " + fixtureA.toString() + " and " + fixtureB.toString());

            if(fixtureA.getBody().getUserData().equals(1) && fixtureB.getBody().getUserData().equals(2) || fixtureA.getBody().getUserData().equals(2) && fixtureB.getBody().getUserData().equals(1)){
                Gdx.app.log("HIT", "goal1 contact");
                score1++;
                score1String = score1 + "";
            }

            if(fixtureA.getBody().getUserData().equals(1) && fixtureB.getBody().getUserData().equals(3) || fixtureA.getBody().getUserData().equals(3) && fixtureB.getBody().getUserData().equals(1)){
                Gdx.app.log("HIT", "goal2 contact");
                score2++;
                score2String = score2 + "";
            }
        }

        @Override
        public void endContact(Contact contact) {
            Fixture fixtureA = contact.getFixtureA();
            Fixture fixtureB = contact.getFixtureB();
            Gdx.app.log("endContact", "between " + fixtureA.toString() + " and " + fixtureB.toString());
        }

        @Override
        public void preSolve(Contact contact, Manifold oldManifold) {
        }

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

        });
} 

注意事项:

  1. 当我注释掉 beginContact() 方法中的两个条件语句时,代码运行。取消注释时,错误会重现。
  2. Ball 用户数据为 circleBody.setUserData(1);
  3. goal1 userData是goalBody.setUserData(2);
  4. goal2的userData是goalBody.setUserData(3);

【问题讨论】:

  • 以下一个或多个返回null:fixtureA.getBody() 或fixtureA.getBody().getUserData() 或等效的fixtureB 方法。 getBody() 或 getUserData() 是否应该总是返回一个值?如果它们返回 null 意味着什么?
  • @JosephBueno 第 491 行是 beginContact() 方法中的第一个 if 语句。感谢您的回复。
  • @HeatfanJohn 我解决了。感谢您的宝贵时间。
  • 我犯了一个菜鸟错误。我只是忘记设置世界上其他对象的用户数据。
  • 请尽可能发布您的修复作为答案。

标签: java android collision-detection libgdx game-physics


【解决方案1】:

为 Box2D 世界中的每个实体设置用户数据,以便您可以使用 ContactListener 中的条件逻辑来评估是否应处理碰撞。

重点在下面的paddleBody.setUserData(4); 行。您可以选择任何数字来设置单个对象的用户数据,只要该数字与您世界中其他对象的用户数据不同即可。

例如:

    /**paddle1**/
    BodyDef paddleDef = new BodyDef();
    paddleDef.type = BodyType.DynamicBody;
    paddleDef.position.set(width * 0.2f, height / 2);
    paddleDef.fixedRotation = true;

    Body paddleBody = world.createBody(paddleDef);
    paddleBody.setUserData(4);

    PolygonShape paddleShape = new PolygonShape();
    paddleShape.setAsBox(3.0f, 15.0f); //half-width and half-height

    FixtureDef paddleFD = new FixtureDef();
    paddleFD.shape = paddleShape;
    paddleFD.density = 10.0f;
    paddleFD.friction = 0.0f;
    paddleFD.restitution = 0.1f;

    paddleBody.createFixture(paddleFD);

    paddleShape.dispose();

    paddleBody.setLinearVelocity(0.0f, 0.0f);
    /**end paddle1**/

    /**paddle2**/
    BodyDef paddleDef2 = new BodyDef();
    paddleDef2.type = BodyType.DynamicBody;
    paddleDef2.position.set(width * 0.8f, height / 2);
    paddleDef2.fixedRotation = true;        

    Body paddleBody2 = world.createBody(paddleDef2);
    paddleBody2.setUserData(5);             

    PolygonShape paddleShape2 = new PolygonShape();
    paddleShape2.setAsBox(3.0f, 15.0f); //half-width and half-height

    FixtureDef paddleFD2 = new FixtureDef();
    paddleFD2.shape = paddleShape2;
    paddleFD2.density = 10.0f;
    paddleFD2.friction = 0.0f;
    paddleFD2.restitution = 0.1f;

    paddleBody2.createFixture(paddleFD2);

    paddleShape2.dispose();

    paddleBody2.setLinearVelocity(0.0f, 0.0f); // Move nowhere at a rate of x = 0.0f, y = 0.0f meters per second
    /**end paddle2**/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 2016-09-11
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    • 2015-03-20
    相关资源
    最近更新 更多