I'm using libgdx and its physic engine Box2d. My question is : how could I make my box2d body go through a block , ignore the first collison than make the block active so the ball can fall onto it. A good example is doodle jump.

Set a flag whenever collisions are detected.
Something like this:
method Ball.onCollisionWith(block) { if (block == self.dontCollide) { self.dontCollide = block -- Do nothing else, passing through collision } else { -- Reset flag so next collision will pass again self.dontCollide = nil resolveCollision(self, block) } } The Ball will then ignore every second collision due to its dontCollide flag being set.
I've had a similar problem in the past, have a look at this Tutorial. I found it answered my question. Its not for java but the code was very easy to copy over
I finally made it :)
Here's my code :
public void preSolve(Contact contact, Manifold oldManifold) { fixtureA = contact.getFixtureA(); fixtureB = contact.getFixtureB(); if(fixtureA.getBody().getUserData() == "platform" && fixtureB.getBody().getUserData() == "ball"|| fixtureA.getBody().getUserData() == "ball" && fixtureB.getBody().getUserData() == "platform"){ if (fixtureA.getBody().getUserData() == "platform") { platform_y = fixtureA.getBody().getPosition().y; ball_y = fixtureB.getBody().getPosition().y; } else if(fixtureA.getBody().getUserData() == "ball") { ball_y = fixtureA.getBody().getPosition().y; platform_y = fixtureB.getBody().getPosition().y; } if(ball_y < platform_y + 1.5F) { //the ball is below contact.setEnabled(false); } } } I used your solution but instead of using getUserData I set up category bits on my platforms and player. The ground has different category bits to platforms so that only the platforms can be passed through. You can define category bits in your main game class as follows:
public static final short GROUND_BIT = 1; public static final short PLATFORM_BIT = 2; public static final short PLAYER_BIT = 4; Next, in your Presolve we only want to pass through platforms, so we add this code to check if Fixture A and B are either the Player or Platforms:
@Override public void preSolve(Contact contact, Manifold oldManifold) { //THIS SHOULD ALLOW PLAYER TO PASS THROUGH PLATFORMS AND COLLIDE ON THE WAY DOWN Fixture fixtureA = contact.getFixtureA(); Fixture fixtureB = contact.getFixtureB(); float platform_y; float player_y; platform_y = fixtureA.getBody().getPosition().y; player_y = fixtureB.getBody().getPosition().y; if(fixtureA.getFilterData().categoryBits == Engine.PLAYER_BIT && fixtureB.getFilterData().categoryBits == Engine.PLATFORM_BIT || fixtureA.getFilterData().categoryBits == Engine.PLATFORM_BIT && fixtureB.getFilterData().categoryBits == Engine.PLAYER_BIT ) { //Gdx.app.log("Player Y ", "" + player_y); if (fixtureA.getBody().getUserData() == "platform") { platform_y = fixtureA.getBody().getPosition().y; player_y = fixtureB.getBody().getPosition().y; } else if(fixtureA.getBody().getUserData() == "player") { player_y = fixtureA.getBody().getPosition().y; platform_y = fixtureB.getBody().getPosition().y; } if(player_y < platform_y + 0.22f) { //the player is below platform contact.setEnabled(false); } else { contact.setEnabled(true); } } } When I build my level the Platforms use this loop to build them from a Tiled map, and set the Category bits to the fixtures:
////////////////////////////////////////////////////////////////////////// //Platform Layers - with category bit PLATFORM_BIT for(MapObject object : map.getLayers().get(2).getObjects().getByType(RectangleMapObject.class)) { Rectangle rect = ((RectangleMapObject) object).getRectangle(); bdef.type = BodyDef.BodyType.StaticBody; bdef.position.set((rect.getX() + rect.getWidth() / 2) / Engine.PPM, (rect.getY() + rect.getHeight() / 2) / Engine.PPM); body = world.createBody(bdef); shape.setAsBox(rect.getWidth()/2 / Engine.PPM, rect.getHeight()/2 / Engine.PPM); fdef.shape = shape; //Set the category Bits to Platform fdef.filter.categoryBits = Engine.PLATFORM_BIT; body.createFixture(fdef); } My Player also has category bits set and the maskBits define what he can collide with:
fdef.filter.categoryBits = Engine.PLAYER_BIT; fdef.filter.maskBits = Engine.GROUND_BIT | Engine.PLATFORM_BIT; This should be all you need to get it working.
The only issue is trying to work out what the value here should be:
if(player_y < platform_y + 0.22f) { //the player below The 0.22f in my case makes sure tht the player gets a certain height above the platform before checking. If you set this too high or too low, the player may not land on the platform at all. I have not worked out what the .22f is in relation to my world coordinates or sprite size yet, but will update if I can replace this with a value derived from the Player's height for example.
Hope this helps a little.
GIT