
Working with ContactListener from Box2d in Libgdx
- Tutorial
In continuation of the last article about using Box2d in Libgdx, I decided to consider working with the class
From the name of the class, it is obvious that it should be used to handle collisions. Consider a couple of practical examples.

It is necessary to implement 4 methods:
Our class will look something like this:
To use it, you must assign it to the game world.
Fires when two objects begin to overlap. It only works as part of a step.
Fires when two objects stop touching. It can be triggered when the body is destroyed, so this event can take place outside the time step.
It works after a collision is detected, but before it is processed. This allows us to somehow change the contact before processing it. For example, you can make a contact inactive. Take an example from a previous article. We used a moving platform. Suppose you want to make the character go through it. Then it
The method allows you to implement the logic of the game, which changes the physics after contact. For example, deform or destroy an object after contact. However, Box2D does not allow you to change the physics in the method, because you could destroy the objects that Box2D is currently processing, resulting in an error.
There is one subtlety here - you cannot just delete an object, since it can be processed somewhere at the moment, and as a result you will get an error: And so, in the method we will delete the blocks that we encountered.
Now, in a collision, the blocks for which the set
You can download the source from the blog . They are pretty damp, really. But to understand the principles of work will help.
ContactListener
. From the name of the class, it is obvious that it should be used to handle collisions. Consider a couple of practical examples.

ContactListener
- An interface that can be implemented in its class for future use in the game world. It is necessary to implement 4 methods:
beginContact
, endContact
, preSolve
, postSolve
. Our class will look something like this:
public class MyContactListener implements ContactListener{
@Override
public void endContact(Contact contact) {
}
@Override
public void beginContact(Contact contact) {
}
@Override
public void preSolve (Contact contact, Manifold oldManifold){
}
@Override
public void postSolve (Contact contact, ContactImpulse impulse){
}
}
To use it, you must assign it to the game world.
world.setContactListener(new MyContactListener());
beginContact
Fires when two objects begin to overlap. It only works as part of a step.
endContact
Fires when two objects stop touching. It can be triggered when the body is destroyed, so this event can take place outside the time step.
preSolve
It works after a collision is detected, but before it is processed. This allows us to somehow change the contact before processing it. For example, you can make a contact inactive. Take an example from a previous article. We used a moving platform. Suppose you want to make the character go through it. Then it
preSolve
will look like this: @Override
public void preSolve (Contact contact, Manifold oldManifold){
WorldManifold manifold = contact.getWorldManifold();
for(int j = 0; j < manifold.getNumberOfContactPoints(); j++){
if(contact.getFixtureA().getUserData() != null && contact.getFixtureA().getUserData().equals("p"))
contact.setEnabled(false);
if(contact.getFixtureB().getUserData() != null && contact.getFixtureB().getUserData().equals("p"))
contact.setEnabled(false);
}
}
contact.getFixtureA().getUserData().equals("p")
used to identify an object. Let me remind you that when creating the platform, the method is used platform.getFixtureList().get(0).setUserData("p")
.postSolve
The method allows you to implement the logic of the game, which changes the physics after contact. For example, deform or destroy an object after contact. However, Box2D does not allow you to change the physics in the method, because you could destroy the objects that Box2D is currently processing, resulting in an error.
There is one subtlety here - you cannot just delete an object, since it can be processed somewhere at the moment, and as a result you will get an error: And so, in the method we will delete the blocks that we encountered.
java.lang.NullPointerException
at com.badlogic.gdx.physics.box2d.World.contactFilter
@Override
public void postSolve (Contact contact, ContactImpulse impulse){
Body body = null;
if(contact.getFixtureA() != null && contact.getFixtureA().getUserData() != null && contact.getFixtureA().getUserData().equals("b"))
body = contact.getFixtureA().getBody();
if(contact.getFixtureB() != null && contact.getFixtureB().getUserData() != null && contact.getFixtureB().getUserData().equals("b"))
body = contact.getFixtureB().getBody();
if(body != null){
body.setActive(false);
world.destroyBody(body);
}
}
Now, in a collision, the blocks for which the set
getFixtureList().get(0).setUserData("b")
will be destroyed. I wrote from above that there will be an error with a normal deletion. But, if you make the object inactive before deleting body.setActive(false)
, then there will be no error.Source code
You can download the source from the blog . They are pretty damp, really. But to understand the principles of work will help.