Collision Dont work

Discuss issues specific the Java port of Box2D
Ildelian
Posts: 3
Joined: Tue Mar 29, 2016 7:41 am

Collision Dont work

Postby Ildelian » Tue Mar 29, 2016 9:27 am

Hi to everyone.

I am doing a 2D platform game with Box2D and LibGdx.

I made a level with TiledMap and load it in box2D.

I can put players and create objects with no problem except when i import the objects from the tiled map, i can see the objects but my player can't collide with it.

My player, and the world:

Image

Image

The player simply pass throw the objects, but if I put a second static player player, the first player collide with it with no problem.

Image

My code:

The level:

Code: Select all


import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapRenderer;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.Contact;
import com.badlogic.gdx.physics.box2d.ContactImpulse;
import com.badlogic.gdx.physics.box2d.ContactListener;
import com.badlogic.gdx.physics.box2d.Manifold;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.physics.box2d.utils.Box2DBuild;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.larralde.GeometryConflict;
import com.larralde.config.Constantes;
import com.larralde.entities.EntityFactory;
import com.larralde.entities.PlayerContactListener;
import com.larralde.entities.PlayerEntity;
import com.larralde.entities.PlayerEntity2;
import com.larralde.entities.WorldEntity;
import com.larralde.entities.WorldEntity2;
import com.larralde.screens.BaseScreen;
import com.larralde.utils.TiledMapLoader;
import com.larralde.utils.TiledMapObject;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by Ildelian on 26/03/2016.
 */
public class Level_01_01 extends BaseScreen {

    private float SCREEN_X, SCREEN_Y;
    private Stage stage;
    private Skin skin;
    private OrthogonalTiledMapRenderer tiledMapRenderer;
    private TiledMap tiledMap;
    private PlayerEntity jugador;
    private PlayerEntity2 jugador2;
    private List<WorldEntity> floor;
    private World world;
    private Vector3 position;
    private List<TiledMapObject> tiledMapObjects;
    private List<WorldEntity2> actores;
    Box2DDebugRenderer debugger;
    boolean render;

    public Level_01_01(GeometryConflict game, String skinFile){
        super(game);

        render = true;
        SCREEN_X = game.getAppConfig().getScreenX();
        SCREEN_Y = game.getAppConfig().getScreenY();

        stage = new Stage(new FitViewport(SCREEN_X, SCREEN_Y));
        stage.setDebugAll(Constantes.SCENE2D_DEBUG);
        position = new Vector3(stage.getCamera().position);
        skin = new Skin(Gdx.files.internal(skinFile));

        world = new World(new Vector2(0, -10), true);
        world.setContactListener(new PlayerContactListener());

        tiledMap = new TmxMapLoader().load("levels/ACTO_01_01.tmx");
        tiledMapRenderer = new OrthogonalTiledMapRenderer(tiledMap);
        tiledMapRenderer.getBatch().disableBlending();
        tiledMapRenderer.setView((OrthographicCamera) stage.getCamera());

        tiledMapObjects = new ArrayList<TiledMapObject>();
        actores = new ArrayList<WorldEntity2>();
        floor = new ArrayList<WorldEntity>();

        world.setContactListener(new GameContactListener());
    }

    @Override
    public void show() {
        EntityFactory factory = new EntityFactory(game.getManager());

        //Creamos el jugador.
        jugador = factory.createPlayer(world, new Vector2(1f, 15f), game);

        //Creamos el suelo.
        floor.clear();
        for(MapObject oAux : tiledMap.getLayers().get("Objetos").getObjects()) {
            floor.add(factory.createWorld(world, oAux, game));
        }

        jugador2 = factory.createPlayer2(world, new Vector2(1f, 3f), game);

        /*for(MapObject oAux : tiledMap.getLayers().get("Objetos").getObjects()) {
            actores.add(factory.createFloor(world,oAux,32f));
        }*/


        ArrayList<TiledMapObject> sObjetos = TiledMapLoader.dameObjetos(tiledMap, 32f, world, "Objetos");

        /*for(TiledMapObject oAux : sObjetos){
            actores.add(factory.createFloor2(oAux));
        }*/


        /*for(WorldEntity2 aAux : actores){
            stage.addActor(aAux);
        }*/
        for(WorldEntity sAux : floor){
            stage.addActor(sAux);
        }
        stage.addActor(jugador);
        stage.addActor(jugador2);


        stage.getCamera().position.set(position);
        stage.getCamera().update();

        debugger = new Box2DDebugRenderer( true, true, true, true,true, true );

    }

    @Override
    public void hide() {
        stage.clear();

        jugador.detach();

    }

    @Override
    public void dispose() {
        // Dispose assets.
        stage.dispose();
        skin.dispose();
    }

    @Override
    public void render(float delta) {
        Gdx.gl.glClearColor(0, 0, 0, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
            stage.getCamera().translate(-32, 0, 0);
            //jugador.setPosition(jugador.getX() - 32, jugador.getY());
        }
        if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
            stage.getCamera().translate(32, 0, 0);
            //jugador.setPosition(jugador.getX() + 32, jugador.getY());
        }
        if(Gdx.input.isKeyPressed(Input.Keys.UP)){
            stage.getCamera().translate(0, 32, 0);
            //jugador.setPosition(jugador.getX(), jugador.getY() + 32);
        }
        if(Gdx.input.isKeyPressed(Input.Keys.DOWN)){
            stage.getCamera().translate(0, -32, 0);
        }

        if(Gdx.input.isKeyPressed(Input.Keys.NUMPAD_5)){
            stage.getCamera().lookAt(floor.get(0).getX(),floor.get(0).getY(),0);
        }

        tiledMapRenderer.setView((OrthographicCamera) stage.getCamera());
        tiledMapRenderer.render();

        debugger.render( world, stage.getCamera().combined);

        stage.act();
        world.step(delta, 6, 2);


        /*if (jugador.getX() > 150 && jugador.isAlive()) {
            float speed = Constantes.PLAYER_SPEED * delta * Constantes.PIXELS_IN_METER;
            stage.getCamera().translate(speed, 0, 0);
        }*/
        stage.draw();
    }

    private class GameContactListener implements ContactListener {

        private boolean areCollided(Contact contact, Object userA, Object userB) {
            Object userDataA = contact.getFixtureA().getUserData();
            Object userDataB = contact.getFixtureB().getUserData();

            if (userDataA == null || userDataB == null) {
                return false;
            }

            return (userDataA.equals(userA) && userDataB.equals(userB)) ||
                    (userDataA.equals(userB) && userDataB.equals(userA));
        }

        @Override
        public void beginContact(Contact contact) {
            // The player has collided with the floor.
            if (areCollided(contact, "player", "floor")) {
                jugador.setJumping(false);

                // If the screen is still touched, you have to jump again.
                if (Gdx.input.isTouched()) {
                    //jumpSound.play();

                    // You just can't add a force here, because while a contact is being handled
                    // the world is locked. Therefore you have to find a way to remember to make
                    // the player jump AFTER the collision has been handled. Here I update the
                    // flag value mustJump. This will make the player jump on next frame.
                    jugador.setMustJump(true);
                }
            }

            // The player has collided with something that hurts.
            if (areCollided(contact, "player", "spike")) {

                // Check that is alive. Sometimes you bounce, you don't want to die more than once.
                if (jugador.isAlive()) {
                    jugador.setAlive(false);

                    // Sound feedback.
                    //backgroundMusic.stop();
                    //dieSound.play();

                    // Add an Action. Actions are cool because they let you add animations to your
                    // game. Here I add a sequence action so that two actions happens one after
                    // the other. One action is a delay action. It just waits for 1.5 seconds.
                    // The second actions is a run action. It executes some code. Here, we go
                    // to the game over screen when we die.
                    stage.addAction(
                            Actions.sequence(
                                    Actions.delay(1.5f),
                                    Actions.run(new Runnable() {

                                        @Override
                                        public void run() {
                                            //game.setScreen(game.gameOverScreen);
                                        }
                                    })
                            )
                    );
                }
            }
        }

        /**
         * This method is executed when a contact has finished: two fixtures are no more colliding.
         */
        @Override
        public void endContact(Contact contact) {
            // The player is jumping and it is not touching the floor.
            if (areCollided(contact, "player", "floor")) {
                if (jugador.isAlive()) {
                    //jumpSound.play();
                }
            }
        }

        // Here two lonely methods that I don't use but have to override anyway.
        @Override public void preSolve(Contact contact, Manifold oldManifold) { }
        @Override public void postSolve(Contact contact, ContactImpulse impulse) { }
    }

}



The objects with the collide problem:

Code: Select all

package com.larralde.entities;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.objects.CircleMapObject;
import com.badlogic.gdx.maps.objects.PolygonMapObject;
import com.badlogic.gdx.maps.objects.PolylineMapObject;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.Shape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.larralde.GeometryConflict;
import com.larralde.config.Constantes;

import static com.larralde.config.Constantes.PIXELS_IN_METER;

/**
 * Created by Ildelian on 26/03/2016.
 */
public class WorldEntity extends Actor {

    private Texture texture;

    private World world;

    private Body body;

    private Fixture fixture;

    public boolean alive = true;

    private boolean jumping = false;

    private boolean mustJump = false;

    private float ppt = 32f;


    public WorldEntity(World world, Texture texture, MapObject mapObject, GeometryConflict game){
        this.world =  world;
        this.texture = texture;

        Shape shape;

        if (mapObject instanceof RectangleMapObject) {
            //shape = getRectangle((RectangleMapObject) object,tiledAux);
            RectangleMapObject rectangleObject = (RectangleMapObject) mapObject;
            Rectangle rectangle = rectangleObject.getRectangle();

            Vector2 size = new Vector2((rectangle.x + rectangle.width * 0.5f) / ppt,(rectangle.y + rectangle.height * 0.5f ) / ppt);

            Vector2 position = new Vector2(0,0);
            rectangle.getPosition(position);

            //position = new Vector2(rectangle.x / ppt,rectangle.y / ppt);
            //Definimos el cuerpo del Jugador.
            BodyDef def = new BodyDef();
            def.position.set(position.x,position.y);
            def.type = BodyDef.BodyType.StaticBody;
            body = world.createBody(def);

            //Le damos forma al jugador.
            PolygonShape polygon = new PolygonShape();
            //polygon.setAsBox(0.5f, 0.5f);
            polygon.setAsBox(rectangle.width * 0.5f / ppt,rectangle.height * 0.5f / ppt,size,0.0f);
            fixture = body.createFixture(polygon, 3);
            fixture.setUserData("player");
            polygon.dispose();

            //setPosition(position.x, position.y);
            setSize(rectangle.width, rectangle.height);
            //setSize(Constantes.PIXELS_IN_METER, Constantes.PIXELS_IN_METER);


        }
        else if (mapObject instanceof PolygonMapObject) {
            //shape = getPolygon((PolygonMapObject)object,tiledAux);
        }
        else if (mapObject instanceof PolylineMapObject) {
            //shape = getPolyline((PolylineMapObject)object,tiledAux);
        }
        else if (mapObject instanceof CircleMapObject) {
            //shape = getCircle((CircleMapObject)object,tiledAux);
        }


    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        //setPosition((body.getPosition().x - 0.5f) * PIXELS_IN_METER,(body.getPosition().y - 0.5f) * PIXELS_IN_METER);
        setPosition((body.getPosition().x - 0.5f) / PIXELS_IN_METER,(body.getPosition().y - 0.5f) / PIXELS_IN_METER);
        setPosition(body.getPosition().x,body.getPosition().y);
        batch.draw(texture, getX(), getY(), getWidth(), getHeight());
    }

    @Override
    public void act(float delta) {
        if (Gdx.input.justTouched()) {
            jump();
        }

        if (mustJump) {
            mustJump = false;
            jump();
        }

        if (alive) {
            //body.setLinearVelocity(Constantes.PLAYER_SPEED, speedY);
        }

        if (jumping) {
            body.applyForceToCenter(0, -Constantes.IMPULSE_JUMP * 1.15f, true);
        }
    }

    public void jump() {
        // The player must not be already jumping and be alive to jump.
        if (!jumping && alive) {
            jumping = true;

            // Apply an impulse to the player. This will make change the velocity almost
            // at the moment unlike using forces, which gradually changes the force used
            // during the jump. We get the position becase we have to apply the impulse
            // at the center of mass of the body.
            Vector2 position = body.getPosition();
            body.applyLinearImpulse(0, Constantes.IMPULSE_JUMP, position.x, position.y, true);
        }
    }

    public void detach() {
        body.destroyFixture(fixture);
        world.destroyBody(body);
    }

    public void setAlive(boolean alive){
        this.alive = alive;
    }

    public boolean isAlive() {
        return alive;
    }

    public void setJumping(boolean jumping) {
        this.jumping = jumping;
    }

    public void setMustJump(boolean mustJump) {
        this.mustJump = mustJump;
    }
}


The objects with no problem:

Code: Select all

package com.larralde.entities;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.larralde.GeometryConflict;
import com.larralde.config.Constantes;

import static com.larralde.config.Constantes.PIXELS_IN_METER;

/**
 * Created by Ildelian on 26/03/2016.
 */
public class PlayerEntity extends Actor {

    private Texture texture;

    private World world;

    private Body body;

    private Fixture fixture;

    public boolean alive = true;

    private boolean jumping = false;

    private boolean mustJump = false;


    public PlayerEntity( World world, Texture texture, Vector2 position, GeometryConflict game){
        this.world =  world;
        this.texture = texture;

        //Definimos el cuerpo del Jugador.
        BodyDef def = new BodyDef();
        def.position.set(position);
        def.type = BodyDef.BodyType.DynamicBody;
        body = world.createBody(def);

        //Le damos forma al jugador.
        PolygonShape polygon = new PolygonShape();
        polygon.setAsBox(0.5f, 0.5f);
        fixture = body.createFixture(polygon, 3);
        fixture.setUserData("player");
        polygon.dispose();

        setSize(Constantes.PIXELS_IN_METER, Constantes.PIXELS_IN_METER);
    }

    @Override
    public void draw(Batch batch, float parentAlpha) {
        setPosition((body.getPosition().x - 0.5f) * PIXELS_IN_METER,(body.getPosition().y - 0.5f) * PIXELS_IN_METER);
        batch.draw(texture, getX(), getY(), getWidth(), getHeight());
    }

    @Override
    public void act(float delta) {
        if (Gdx.input.justTouched()) {
            jump();
        }

        if (mustJump) {
            mustJump = false;
            jump();
        }

        if (alive) {
            //body.setLinearVelocity(Constantes.PLAYER_SPEED, speedY);
        }

        if (jumping) {
            body.applyForceToCenter(0, -Constantes.IMPULSE_JUMP * 1.15f, true);
        }
    }

    public void jump() {
        // The player must not be already jumping and be alive to jump.
        if (!jumping && alive) {
            jumping = true;

            // Apply an impulse to the player. This will make change the velocity almost
            // at the moment unlike using forces, which gradually changes the force used
            // during the jump. We get the position becase we have to apply the impulse
            // at the center of mass of the body.
            Vector2 position = body.getPosition();
            body.applyLinearImpulse(0, Constantes.IMPULSE_JUMP, position.x, position.y, true);
        }
    }

    public void detach() {
        body.destroyFixture(fixture);
        world.destroyBody(body);
    }

    public void setAlive(boolean alive){
        this.alive = alive;
    }

    public boolean isAlive() {
        return alive;
    }

    public void setJumping(boolean jumping) {
        this.jumping = jumping;
    }

    public void setMustJump(boolean mustJump) {
        this.mustJump = mustJump;
    }
}


30/03/2016 UPDATE_01:

I have done this tests: – Ildelian 29 mins ago

1 -> Load all the "RectangleMapObject" from the map and draw all with the same position and size, result:

Image

-> All the objects is in the same position and Physics works.

2 -> Load all the "RectangleMapObject" from the map and draw all with distinct position (Setting Manually) and same size, result:

Image

-> All the objects is in different position and Physics works.

3 -> Load all the "RectangleMapObject" from the map and draw all with distinct position (Reading position from RectangleMapObject.posision) and same size, result:

Image

-> Where are my objects?
-> What are the points pink ?

4 -> Load all the "RectangleMapObject" from the map and draw all with distinct position (Setting Manually) and distinct size (read from the RectangleMapObject), result:

Image

-> What the hell is this? XD

5 -> Here, I have all the Box2D and Scene 2D loaded with the correct size and position, buy physics don't work:

Image

Ildelian
Posts: 3
Joined: Tue Mar 29, 2016 7:41 am

Re: Collision Dont work

Postby Ildelian » Sun Apr 03, 2016 5:04 am

I have found the problem.

TiledMAp is in Pixels. Box2D works in Meters. Scene2D works in Piexles

I need to convert the Units between meters and Pixels.


Return to “Java”



Who is online

Users browsing this forum: No registered users and 2 guests