0
votes

i am testing collision between two bodies in box2D using contactListener

this is my whole contactListener class i used world.setContactListener(new Box2DWorld(this)) to add it

 public class Box2DWorld implements ContactListener{

World world;
GameScreen gameScreen;
Car car;

public enum BodyName{
    frontWheel,rearWheel,carShell,ground,finishSensor
}

/**
 * this class handles collisions and body userdata
 * @param gameScreen
 */
public Box2DWorld(GameScreen gameScreen) {  
    this.gameScreen = gameScreen;
    world = gameScreen.world;
    this.car = gameScreen.car;
}


/*
 * the debug should be like 
 * 
 * BEGONCONTACT,preSolve,postSolve,......postsolve,ENDCONTACT,BEGINCONTACT,preSolve,postSolve
 * 
 * but i am getting debug like
 * 
 * BEGINCONTACT,preSolve,postSolve,......postsolve,BEGINCONTACT,presolve,ENDCONTACT,preSolve,postSolve...
 * 
 * i can't understand why begincontact appears twice without endcontact in between and also bodies are in contact
 *  even after endcontact
 * 
 */

@Override
public void beginContact(Contact contact) {
    BodyName bodyA = (BodyName) contact.getFixtureA().getBody().getUserData();
    BodyName bodyB = (BodyName) contact.getFixtureB().getBody().getUserData();


    if((bodyA == BodyName.frontWheel && bodyB == BodyName.ground )||(bodyA == BodyName.ground && bodyB == BodyName.frontWheel)){
        car.frontWheel.onGround = true;
        System.out.println("begin contact");
    }


}   

@Override
public void endContact(Contact contact) {
    BodyName bodyA = (BodyName) contact.getFixtureA().getBody().getUserData();
    BodyName bodyB = (BodyName) contact.getFixtureB().getBody().getUserData();

    if((bodyA == BodyName.frontWheel && bodyB == BodyName.ground )||(bodyA == BodyName.ground && bodyB == BodyName.frontWheel)){
        car.frontWheel.onGround = false;
        System.out.println("contact end");  
    }

}

@Override
public void preSolve(Contact contact, Manifold oldManifold) {

    BodyName bodyA = (BodyName) contact.getFixtureA().getBody().getUserData();
    BodyName bodyB = (BodyName) contact.getFixtureB().getBody().getUserData();

    if((bodyA == BodyName.frontWheel && bodyB == BodyName.ground )||(bodyA == BodyName.ground && bodyB == BodyName.frontWheel)){
        System.out.println("PreSolve"); 
    }


}

@Override
public void postSolve(Contact contact, ContactImpulse impulse) {

    BodyName bodyA = (BodyName) contact.getFixtureA().getBody().getUserData();
    BodyName bodyB = (BodyName) contact.getFixtureB().getBody().getUserData();

    if((bodyA == BodyName.frontWheel && bodyB == BodyName.ground )||(bodyA == BodyName.ground && bodyB == BodyName.frontWheel)){
        System.out.println("postSolve");    
    }

}

my dedub goes like this

beginContact preSolve postSolve . . . . . . preSolve postSolve beginContact preSolve endcontact postSolve presolve . . . .

i can't understand why begincontact is appearing before endcontact

both ground and frontWheel bodies have only 1 fixture each

i can't figure out this from a week pls help me

1
You are not checking the case where bodyA == Y and bodyB == Xiforce2d
i am checking that i just didn;t add that herekr15hna
How about you add it then, so that people don't waste their time and yours by giving you suggestions for things you have already done. I think there must be something else you "didn't add here" because it would be a huge bug in Box2D if a pair of bodies had two BeginContact events before the EndContact happened.iforce2d
i am really srry that i didn't add that, i have no experience in asking questions ,please forgive me . i like your blog very much , you have been a great help to me and a lot of peoplekr15hna
@iforce2d i edited my question now , i don't know whether i should be adding more pls say me if i am missing anythigkr15hna

1 Answers

0
votes

Remember that a contact is between two fixtures, not two bodies.

I would guess that your ground is made from many fixtures, and they are all on the same ground body right? As the wheel rolls over the fixtures it can touch more than one fixture at a time, so you can get begin(fixture1), begin(fixture2), end(fixture1) in that order. It's quite normal. I think if you print out the ground fixture involved in each contact event, you would see what I mean.

If you want to know when the wheel is touching the ground, you need to track the total number of fixtures currently touching. You can do that by incrementing a counter when you get a 'begin' event, and decrement it when you get an 'end' event. Then you can check the counter any time, if it is more than zero the wheel is touching the ground.