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:
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.