Home Java Working with ContactListenerfrom Box2d in Libgdx

Working with ContactListenerfrom Box2d in Libgdx

by admin

As a continuation of last week’s article about Using Box2d in Libgdx Decided to consider working with the class ContactListener
It is obvious from the name of the class that it should be used to handle collisions.Let’s look at a couple of practical examples.
Working with ContactListenerfrom Box2d in Libgdx
ContactListener – interface that you can implement in your class for later use in the game world.
You need to implement 4 methods : beginContact , endContact , preSolve , postSolve
Our class will look something like this :

public class MyContactListener implements ContactListener{@Overridepublic void endContact(Contact contact) {}@Overridepublic void beginContact(Contact contact) {}@Overridepublic void preSolve(Contact contact, Manifold oldManifold){}@Overridepublic void postSolve(Contact contact, ContactImpulse impulse){}}

To use it, you must assign it to the game world.

world.setContactListener(new MyContactListener());

beginContact

Works when two objects start overlapping. Only works within a step.

endContact

Triggers when two objects stop touching. Can be triggered when the body is destroyed, so this event can take place outside the time step.

preSolve

Triggers after a collision is detected, but before it is processed. This allows us to somehow change the contact before it is processed. For example, we can make the contact inactive. Let’s take an example from the last article. We used a moving platform. Suppose you want to make a character walk through it. Then preSolve will look like this :

@Overridepublic 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") is used to identify the object. Recall that the method used to create the platform is platform.getFixtureList().get(0).setUserData("p")

postSolve

The method allows you to implement game logic that changes 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, causing an error.
There’s a tricky thing here – you can’t just delete an object, because it might be being processed somewhere at the moment, and you’ll end up with an error :
java.lang.NullPointerException
at com.badlogic.gdx.physics.box2d.World.contactFilter

And so, in the method we will remove the blocks we encountered.

@Overridepublic void postSolve (Contact contact, ContactImpulse impulse){Body body = null;if(contact.getFixtureA() != null amp;amp; contact.getFixtureA().getUserData() != null amp;amp; contact.getFixtureA().getUserData().equals("b"))body = contact.getFixtureA().getBody();if(contact.getFixtureB() != null amp;amp; contact.getFixtureB().getUserData() != null amp;amp; 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 getFixtureList().get(0).setUserData("b") will be destroyed. I wrote above that there would be an error with normal deletion. But, if you make the object inactive before deleting body.setActive(false) , there will be no error.

Source code

You can download the sources from blog They are quite crude, really. But it will help to understand how they work.

You may also like