Reputation: 308
What's up everyone,
I am heuristically producing a Pong clone in Box2D via libGDX. The Null Pointer Exception is originating in the ContactListener's beginContact() method in which I am trying to implement score logic.
The Box2D world uses two separate EdgeShapes as sensors for incrementing a score variable upon collision with the Ball (view attached image). The collision logic between the Ball and the two EdgeShapes works, but collision between the Ball and anything else in the Box2D world crashes the program.
The stack trace:
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)
The problematic code:
/**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) {
}
});
}
Notes:
Upvotes: 1
Views: 1985
Reputation: 308
Set the userdata for each body in the Box2D world so that you can use conditional logic within the ContactListener to assess whether or not the collision should be handled.
With the emphasis being on the line paddleBody.setUserData(4);
below. You can pick any number to set to the userdata of the individual object, so long as the number is unique from the userdata of the other objects within your world.
For example:
/**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**/
Upvotes: 1