How to know which side of a ChainShape is being collided with?

23 views Asked by At

I'm learning LibGDX and trying to use Box2D for collision and movement. I'm making a simple Pong game. When the ball hits the left or right wall (i.e. the other side scores), I want the ball's body to be destroyed and replaced with a new one in the center of the screen. Obviously this should not happen when the ball hits the top or bottom.

I have created a body with a ChainShape fixture to represent the game's border. This chain has 4 vertexes and forms a loop. I've also created a ContactListener, where the collision between border and ball is handled. The question is: how can I trigger the desired behavior only when the left or right wall is involved in the collision?

It seems to me that somehow the left or right wall should be isolated, perhaps as an EdgeShape. But I can't find any way to do that. The Contact, Fixture and ChainShape all seem to have no relevant methods for this. I also can't find any info about this online.

Below is the code I currently have for the ContactListener:

public final class CollisionListener implements ContactListener {
  @Override
  public void beginContact(Contact contact) {
    var fixtureA = contact.getFixtureA();
    var fixtureB = contact.getFixtureB();
    
    if (fixtureA.getUserData() != "border" && fixtureB.getUserData() != "border") {
      return;
    }

    //TODO: Only trigger for left and right walls

    var object = fixtureA.getUserData() == "border" ? fixtureB : fixtureA;
    Entity entity = (Entity)object.getUserData();

    // Logic for creating new body
  }
}

And the ChainShape:

  private void createBorders() {
    var bodyDef = new BodyDef();
    bodyDef.type = BodyType.StaticBody
    bodyDef.position.set(0, 0);

    var body = world.createBody(bodyDef);

    var chain = new ChainShape();
    chain.createLoop(
      new Vector2[] {
        new Vector2(Constants.VIEWPORT_MAX_X, Constants.VIEWPORT_MAX_Y),
        new Vector2(Constants.VIEWPORT_MAX_X, Constants.VIEWPORT_MIN_Y),
        new Vector2(Constants.VIEWPORT_MIN_X, Constants.VIEWPORT_MIN_Y),
        new Vector2(Constants.VIEWPORT_MIN_X, Constants.VIEWPORT_MAX_Y)
      }
    );

    body.createFixture(chain, 0f);
    body.setUserData("border");
    chain.dispose();
  }
1

There are 1 answers

0
londonBadger On

You could check the x position of the ball on contact i.e. ballX < minX+margin for left and ballX >maxX-margin for right.