0
votes

Hy guys,

I am developing a game for android using libgdx. I am completely stuck at the part of detecting collision between two bodies. I have a player which I create through the function below

public Body createPlayer(String file_path, String fixture_name) {
    // 0. Create a loader for the file saved from the editor.
    BodyEditorLoader loader = new BodyEditorLoader(Gdx.files.internal(file_path));

    // 1. Create a BodyDef, as usual.
    BodyDef bd = new BodyDef();
    bd.type = BodyDef.BodyType.DynamicBody;

    // 2. Create a FixtureDef, as usual.
    FixtureDef fd = new FixtureDef();
    fd.density = 1;
    fd.friction = 0.5f;
    fd.restitution = 0.3f;

    // 3. Create a Body, as usual.
    body= world.createBody(bd);
    //body.setBullet(true);

    // 4. Create the body fixture automatically by using the loader.
    loader.attachFixture(body, fixture_name, fd, 1);
    body.setUserData(this);

    return body;

}

and an enemy that I create with the same function of the player where I change only the file_path and the fixture_name. The file_path points to a .json file that I created with box2d editor (site: http://www.aurelienribon.com/blog/projects/physics-body-editor/). After the creation of the body I draw the player and the enemy with two similar functions ( I only post one):

private void drawPlayer(){
    player_sprite = new Sprite(player_TR);
    player_sprite.setSize(player.getWidth(), player.getHeight());
    player_sprite.setPosition(player.getX(), player.getY());
    player_sprite.setOrigin(0, 0);
    player_sprite.draw(sb);
}

If I start the game everything is drawn where it should be. Obviously if the player touches the enemy nothing happen. So i started trying to search how to make the two bodies collides but I don't really understand how to use ContactListener and beginContact. beginContact wants as input a Contact but what is a Contact? I have found this code online which appears to solve my problem but I don't know how to use it:

worldbox.setContactListener(new ContactListener() {

        @Override
        public void beginContact(Contact contact) {

            if(contact.getFixtureA().getBody().getUserData()== "body1" &&
                    contact.getFixtureB().getBody().getUserData()== "body2")
                Colliding = true;
            System.out.println("Contact detected");
        }

Can you help me (if it is possible through some code) to solve my problem? Thanks in advance, Francesco

Update of my question Here is my render method:

public class GameRenderer{

private GameWorld myWorld;
private ShapeRenderer shapeRenderer;
private SpriteBatch sb;
private Camera camera;
private Constants constant;
private Rectangle viewport;

//dichiaro le variabili per caricare gli asset
private Player player;
private ScrollHandler scroller;
private Bordo frontBordoSX_1, backBordoSX_1, frontBordoSX_2, backBordoSX_2;
private Bordo frontBordoDX_1, backBordoDX_1, frontBordoDX_2, backBordoDX_2;

/*
private Ostacolo ob1_sx, ob2_sx, ob3_sx;
private Ostacolo ob4_dx, ob5_dx, ob6_dx;
*/

private TextureRegion player_TR;
private TextureRegion bordoSX_1, bordoSX_2;
private TextureRegion bordoDX_1, bordoDX_2;
private TextureRegion obstacleSX, obstacleSX_flip;
private TextureRegion obstacleDX, obstacleDX_flip;
private TextureRegion enemyS;
private TextureRegion blackBar;

//box2dpart
private World worldbox;
private Sprite fbDx_1,fbDx_2,fbSx_1,fbSx_2;
private Sprite player_sprite;
private Body player_body, bordo_destro;
private MyContactListener contactListener;

public GameRenderer(GameWorld world) {

    myWorld = world;
    constant = new Constants();
    camera = new OrthographicCamera(constant.getWidth(), constant.getHeight());
    shapeRenderer = new ShapeRenderer();
    shapeRenderer.setProjectionMatrix(camera.combined);
    sb = new SpriteBatch();
    sb.setProjectionMatrix(camera.combined);

    contactListener = new MyContactListener();
    worldbox= new World(new Vector2(0,-10),true);
    worldbox.setContactListener(contactListener);


    //initialize objects and assets
    initGameObjects();
    initAssets();

}

private void initGameObjects(){
    player = myWorld.getPlayer();
    scroller = myWorld.getScroller();
    frontBordoSX_1 = scroller.getFrontBordoSX_1();
    backBordoSX_1 = scroller.getBackBordoSX_1();
    frontBordoSX_2 = scroller.getFrontBordoSX_2();
    backBordoSX_2 = scroller.getBackBordoSX_2();
    frontBordoDX_1 = scroller.getFrontBordoDX_1();
    backBordoDX_1 = scroller.getBackBordoDX_1();
    frontBordoDX_2 = scroller.getFrontBordoDX_2();
    backBordoDX_2 = scroller.getBackBordoDX_2();

    /* other objects
    ob1_sx = scroller.getOb1_sx();
    ob2_sx = scroller.getOb2_sx();
    ob3_sx = scroller.getOb3_sx();
    ob4_dx = scroller.getOb4_dx();
    ob5_dx = scroller.getOb5_dx();
    ob6_dx = scroller.getOb6_dx();
    */
}

private void initAssets(){

    player_TR = AssetLoader.player;
    bordoSX_1 = AssetLoader.bordoSX;
    bordoSX_2 = AssetLoader.bordoSX;
    bordoDX_1 = AssetLoader.bordoDX;
    bordoDX_2 = AssetLoader.bordoDX;
    obstacleDX = AssetLoader.obstacleDX;
    obstacleSX = AssetLoader.obstacleSX;
    obstacleDX_flip = AssetLoader.obstacleDX_flip;
    obstacleSX_flip = AssetLoader.obstacleSX_flip;
    enemyS = AssetLoader.enemyS;
    blackBar = AssetLoader.blackBar;

    //box2d part

}

private void drawMargin(){

    //bordo SX

    /*
    sb.draw(bordoSX_1, frontBordoSX_2.getX(), frontBordoSX_2.getY(), frontBordoSX_2.getWidth(),
            frontBordoSX_2.getHeight());
    sb.draw(bordoSX_2, frontBordoSX_1.getX(), frontBordoSX_1.getY(), frontBordoSX_1.getWidth(),
            frontBordoSX_1.getHeight());
    */

    fbSx_1 = new Sprite(bordoSX_1);
    fbSx_1.setSize(frontBordoSX_1.getWidth(),frontBordoSX_1.getHeight());
    fbSx_1.setPosition(frontBordoSX_1.getX(), frontBordoSX_1.getY());
    fbSx_1.setOrigin(0, 0);
    fbSx_1.draw(sb);

    fbSx_2 = new Sprite(bordoSX_2);
    fbSx_2.setSize(frontBordoSX_2.getWidth(),frontBordoSX_2.getHeight());
    fbSx_2.setPosition(frontBordoSX_2.getX(), frontBordoSX_2.getY());
    fbSx_2.setOrigin(0, 0);
    fbSx_2.draw(sb);

    fbDx_1 = new Sprite(bordoDX_1);
    fbDx_1.setSize(frontBordoDX_1.getWidth(),frontBordoDX_1.getHeight());
    fbDx_1.setPosition(frontBordoDX_1.getX(), frontBordoDX_1.getY());
    fbDx_1.setOrigin(0, 0);
    fbDx_1.draw(sb);

    fbDx_2 = new Sprite(bordoDX_2);
    fbDx_2.setSize(frontBordoDX_2.getWidth(),frontBordoDX_2.getHeight());
    fbDx_2.setPosition(frontBordoDX_2.getX(), frontBordoDX_2.getY());
    fbDx_2.setOrigin(0, 0);
    fbDx_2.draw(sb);

    sb.draw(blackBar,-constant.getWidth()/2,-constant.getHeight()/2,
            (float) (0.573913)*(constant.getWidth()/6),constant.getHeight());
    sb.draw(blackBar,(float)(constant.getWidth()/2-(0.573913)*(constant.getWidth()/6)),-constant.getHeight()/2,
            (float)(0.573913)*(constant.getWidth()/6),constant.getHeight());


}

private void drawPlayer(){
    player_sprite = new Sprite(player_TR);
    player_sprite.setSize(player.getWidth(), player.getHeight());
    player_sprite.setPosition(player.getX(), player.getY());
    player_sprite.setOrigin(0, 0);
    player_sprite.draw(sb);
}

/*
private void drawOstacoli(){

    sb.draw(obstacleSX_flip,ob1_sx.getX(),ob1_sx.getY(),ob1_sx.getWidth(),ob1_sx.getHeight());
    sb.draw(obstacleSX,ob2_sx.getX(),ob2_sx.getY(),ob2_sx.getWidth(),ob2_sx.getHeight());
    sb.draw(obstacleSX_flip,ob3_sx.getX(),ob3_sx.getY(),ob3_sx.getWidth(),ob3_sx.getHeight());
    sb.draw(obstacleDX,ob4_dx.getX()+constant.getWidth()/2-ob4_dx.getWidth(),ob4_dx.getY(),ob4_dx.getWidth(),ob4_dx.getHeight());
    sb.draw(obstacleDX_flip,ob5_dx.getX()+constant.getWidth()/2-ob5_dx.getWidth(),ob5_dx.getY(),ob5_dx.getWidth(),ob5_dx.getHeight());
    sb.draw(obstacleDX,ob6_dx.getX()+constant.getWidth()/2-ob6_dx.getWidth(),ob6_dx.getY(),ob6_dx.getWidth(),ob6_dx.getHeight());

}
*/

public void render(float runTime) {



    Box2D.init();
    int width = constant.getWidth();
    int height = constant.getHeight();
    float ratio = constant.getRatio();

    //viewport
    float aspectRatio = (float) width / (float) height;
    float scale = 1f;
    Vector2 crop = new Vector2(0f, 0f);

    if(aspectRatio > ratio)
    {
        scale = (float)height/(float)height;
        crop.x = (width - width * scale) / 2f;
    } else if (aspectRatio < ratio) {
        scale = (float)width/(float)width;
        crop.y = (height - height*scale)/2f;
    }
    else
    {
        scale = (float) width / (float) width;
    }

    float w = (float) width * scale;
    float h = (float) height * scale;

    viewport = new Rectangle(crop.x, crop.y, w, h);


    // update camera
    camera.update();

    // clear previous frame
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);

    // Draw Background color
    shapeRenderer.setColor(255 / 255.0f, 255 / 255.0f, 250 / 255.0f, 1);
    shapeRenderer.rect(-constant.getWidth() / 2, -constant.getHeight() / 2, constant.getWidth(),
            constant.getHeight());

    // End ShapeRenderer
    shapeRenderer.end();


    // set viewport
    Gdx.gl.glViewport((int) viewport.x, (int) viewport.y,
            (int) viewport.width, (int) viewport.height);

    // Begin SpriteBatch
    sb.begin();

    // The player needs transparency, so we enable that again.
    sb.enableBlending();

    // Draw player at its coordinates.
    drawPlayer();

    //draw right and left side
    drawMargin();

    // End SpriteBatch
    sb.end();

    worldbox.step(1 / 60f, 6, 2);

}

}

And if I start the program my view is my player in the middle and to margins ,one on the left and one on the right. (unfortunatly I cannot post images of my view because I don't have enough rep).

Everithing is fine. I move my player with the accelerometer and it works fine without any problem. The only problem is that if I move the player near the margin the two entities overlap instead of colliding and I don't understand why. I also fixed the line:

loader.attachFixture(body, fixture_name, fd, 1);

to loader.attachFixture(body, fixture_name, fd, player_width);

but nothing changes.

1
why do you say nothing happen? what do you have in the render() method? I though that box2d by default have activated the collisionsAlex Sifuentes

1 Answers

2
votes

First, from here, the object Contact manages contact between two shapes, and from here, the listener ContactListener will be called when two fixtures begin to touch.

So, to make your code work, you should set a custom object to your bodies with the method: setUserData(Object userData). Usually this method is used to link the sprite or the actor with the physic body, but for example purpose you could just send a simple ID (like a string).

So in this part:

// 3. Create a Body, as usual.
body= world.createBody(bd);
//body.setBullet(true);

You could add an identificator to your object like this:

body.setUserData("player");

to idenfity your object, and then, when the listener get fired, you could retrieve this value:

    @Override
    public void beginContact(Contact contact) {
        String userDataA = contact.getFixtureA().getBody().getUserData().toString();
        String userDataB = contact.getFixtureB().getBody().getUserData().toString();

        if(userDataA.equals("player") && userDataB.equals("otherEntity")){
            colliding = true;
            //do stuffs when collision has started
        } else if(userDataB.equals("player") && userDataA.equals("otherEntity")){
            colliding = true;
            //do stuffs when collision has started
        }
        System.out.println("Contact detected");
    }

After that, you could be able to do whatever you want to do with this collision.

Hope you find this useful!