1
\$\begingroup\$

I have a collision problem in Box2D.

I am trying to do a simple platform game with Libgdx, Box2D and TiledMap.

I have a map made with TiledMap:

I load the map in my Android game. I read all the "objects" from the map and draw it on the screen with no problem:

But when I add a player made with Box2D , the player not collides with map objects. He simply passes through:

enter image description here

enter image description here

I have spent two days in this and I can't see my mistake.

Here is my level code:

package com.larralde.screens.gamescreens;

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.maps.Map;
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.Body;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Stage;
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.WorldEntity;
import com.larralde.screens.BaseScreen;
import com.larralde.utils.TiledMapLoader;
import com.larralde.utils.TiledMapObject;

import java.util.ArrayList;


public class Level_01_01 extends BaseScreen {

    private float SCREEN_X, SCREEN_Y;
    private Stage stage;
    private Skin skin;
    private TiledMapRenderer tiledMapRenderer;
    private TiledMap tiledMap;
    private PlayerEntity jugador;
    private World world;
    private Vector3 position;
    ArrayList<TiledMapObject> tiledMapObjects;
    private ArrayList<WorldEntity> actores;

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

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

        stage = new Stage(new FitViewport(SCREEN_X, SCREEN_Y));
        stage.setDebugAll(true);
        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);

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

    @Override
    public void show() {
        EntityFactory factory = new EntityFactory(game.getManager());
        //Gdx.input.setInputProcessor(stage);
        jugador = factory.createPlayer(world, new Vector2(1f, 15f),game);
        stage.addActor(jugador);

        //Cargamos los objetos del mapa
        tiledMapObjects.clear();
        tiledMapObjects.addAll(TiledMapLoader.dameObjetos(tiledMap, 32f, world, "Objetos"));

        //Metemos los objetos en el mundo.
        actores.clear();
        for(TiledMapObject oAux : tiledMapObjects){
            actores.add(new WorldEntity(oAux,world));
        }

        for(WorldEntity aAux : actores){
            stage.addActor(aAux);
        }

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

    @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);
            jugador.setPosition(jugador.getX(), jugador.getY() - 32);

        }*/

        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);
        }*/
        tiledMapRenderer.setView((OrthographicCamera) stage.getCamera());
        tiledMapRenderer.render();

        stage.draw();
    }

}

And the Class that load the objects from the Map:

 package com.larralde.utils;

import com.badlogic.gdx.maps.MapObject;
import com.badlogic.gdx.maps.MapObjects;
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.maps.objects.TextureMapObject;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.math.Circle;
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.ChainShape;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.Shape;
import com.badlogic.gdx.physics.box2d.World;
import com.larralde.config.Constantes;

import java.util.ArrayList;

public class TiledMapLoader {

    //El tamaño de los tiles. Ejemplo, si es 16x16 sera 16f. Siempre cuadrados¡¡
    private static float ppt = 0f;

    public static ArrayList<TiledMapObject> dameObjetos(TiledMap map, float pixels, World world, String layerName){
        ppt = pixels;

        MapObjects objects = map.getLayers().get(layerName).getObjects();


        ArrayList<TiledMapObject> tiledMapObjects =  new ArrayList<TiledMapObject>();

        for(MapObject object : objects) {

            if (object instanceof TextureMapObject) {
                continue;
            }

            //Creamos el objeto
            TiledMapObject tiledAux = new TiledMapObject();

            Shape shape;

            if (object instanceof RectangleMapObject) {
                shape = getRectangle((RectangleMapObject) object,tiledAux);
            }
            else if (object instanceof PolygonMapObject) {
                shape = getPolygon((PolygonMapObject)object,tiledAux);
            }
            else if (object instanceof PolylineMapObject) {
                shape = getPolyline((PolylineMapObject)object,tiledAux);
            }
            else if (object instanceof CircleMapObject) {
                shape = getCircle((CircleMapObject)object,tiledAux);
            }
            else {
                continue;
            }

            BodyDef bd = new BodyDef();
            bd.position.set(tiledAux.getX(),tiledAux.getY());
            bd.type = BodyDef.BodyType.StaticBody;
            Body body = world.createBody(bd);
            body.createFixture(shape, 1);

            tiledAux.setBody(body);
            tiledMapObjects.add(tiledAux);

            shape.dispose();
        }

        return tiledMapObjects;

    }

    private static PolygonShape getRectangle(RectangleMapObject rectangleObject,TiledMapObject tiledAux) {
        Rectangle rectangle = rectangleObject.getRectangle();
        PolygonShape polygon = new PolygonShape();
        Vector2 size = new Vector2((rectangle.x + rectangle.width * 0.5f) / ppt,(rectangle.y + rectangle.height * 0.5f ) / ppt);
        polygon.setAsBox(rectangle.width * 0.5f / ppt,rectangle.height * 0.5f / ppt,size,0.0f);

        //Obtenemos la posicion
        Vector2 posicion = new Vector2(0,0);
        rectangle.getPosition(posicion);
        tiledAux.setX(posicion.x);
        tiledAux.setY(posicion.y);
        tiledAux.setHeight(rectangle.getHeight());
        tiledAux.setWidth(rectangle.getWidth());
        tiledAux.setTipoFigura(Constantes.FIGURA_CUADRADO);
        return polygon;
    }

    private static CircleShape getCircle(CircleMapObject circleObject,TiledMapObject tiledAux) {
        Circle circle = circleObject.getCircle();
        CircleShape circleShape = new CircleShape();
        circleShape.setRadius(circle.radius / ppt);
        circleShape.setPosition(new Vector2(circle.x / ppt, circle.y / ppt));

        //Obtenemos la posicion
        Vector2 posicion = circleShape.getPosition();
        tiledAux.setX(posicion.x);
        tiledAux.setY(posicion.y);
        tiledAux.setHeight(circle.radius * 2f);
        tiledAux.setWidth(circle.radius * 2f);
        tiledAux.setTipoFigura(Constantes.FIGURA_CIRCULO);
        return circleShape;
    }

    private static PolygonShape getPolygon(PolygonMapObject polygonObject,TiledMapObject tiledAux) {
        PolygonShape polygon = new PolygonShape();
        float[] vertices = polygonObject.getPolygon().getTransformedVertices();

        float[] worldVertices = new float[vertices.length];

        for (int i = 0; i < vertices.length; ++i) {
            worldVertices[i] = vertices[i] / ppt;
        }
        tiledAux.setTipoFigura(Constantes.FIGURA_POLIGONO);
        polygon.set(worldVertices);
        return polygon;
    }

    private static ChainShape getPolyline(PolylineMapObject polylineObject,TiledMapObject tiledAux) {
        float[] vertices = polylineObject.getPolyline().getTransformedVertices();
        Vector2[] worldVertices = new Vector2[vertices.length / 2];

        for (int i = 0; i < vertices.length / 2; ++i) {
            worldVertices[i] = new Vector2();
            worldVertices[i].x = vertices[i * 2] / ppt;
            worldVertices[i].y = vertices[i * 2 + 1] / ppt;
        }

        ChainShape chain = new ChainShape();
        chain.createChain(worldVertices);

        tiledAux.setTipoFigura(Constantes.FIGURA_CADENA);

        return chain;
    }
}

I try to create other objects in Box2D instead of using the TiledMap but not collide.

\$\endgroup\$
1
  • \$\begingroup\$ Is very strange. If I put a new Player, the physics work between the two players, but not in the floor. prntscr.com/al9rlc \$\endgroup\$
    – Ildelian
    Mar 28, 2016 at 20:40

2 Answers 2

0
\$\begingroup\$

You are setting your Bodies to be Static, and this indicates that they are 0 mass, and do not move.

Try setting the body type of your character to Dynamic instead.

https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/physics/box2d/BodyDef.BodyType.html

\$\endgroup\$
8
  • \$\begingroup\$ And not is the problem, I have two characters, one Static and one Dinamic. The Dynamic character can collide with the static character, but no with the floor. \$\endgroup\$
    – Ildelian
    Mar 30, 2016 at 9:53
  • \$\begingroup\$ @Ildelian That is strange. Some other things you can try, is making the floor hitbox larger. Sometimes a small hitbox will cause instability with box2d. Another thing, make sure that your floor and your character on not on the same collision layer. \$\endgroup\$
    – jgallant
    Mar 30, 2016 at 10:38
  • \$\begingroup\$ Yes, is very Strange. I have done this tests: \$\endgroup\$
    – Ildelian
    Mar 30, 2016 at 14:15
  • \$\begingroup\$ 1 -> Load all the "RectangleMapObject" from the map and draw all with the same position and size, result: prntscr.com/am0k9d -> All the objects is in the same position and Physics works. \$\endgroup\$
    – Ildelian
    Mar 30, 2016 at 14:15
  • \$\begingroup\$ 2 -> Load all the "RectangleMapObject" from the map and draw all with distinct position (Setting Manually) and same size, result: prntscr.com/am0myc -> All the objects is in different position and Physics works. \$\endgroup\$
    – Ildelian
    Mar 30, 2016 at 14:15
0
\$\begingroup\$

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.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .