LibGDX + TileMap, Problem with collision, tile properties and dimension

I have a problem with my Tiled Maps that i have loaded into my game following this guide; https://github.com/libgdx/libgdx/wiki/Tile-maps. All is fine and dandy, i have created a collisionsystem by following a youtube tutorial, pick the tile cell right, left, above or below you depending on which direction you are going, and then check the properties of that tile, if its blocked its blocked.

This works, but, its all scewed. The collision doesnt happen where it should on the map but at other positions, like if the map would actualy be larger then the rendered representation.
Here is a picture to illustrate; https://www.dropbox.com/s/k4mxqh2j2h92uo1/faultystuff.png

The player there is standing at position 8, 8(position.x /32, and position.y /32), that position in Tiled would show the player further down if i translate the position. But the actual position on the map is rather at 8, 12. The thing is, i can continue to walk up a bit and run into this blocked tile out in the void when the character is about to run into tile 8, 12. I have the same problem at other parts of the map, but it seems that it counts 4 tiles wrong, the center pillar is blocked about 3 tiles to the left as well, and the lower part there continues left and right a bit.

I have tried adding a scale as the wiki page does to the map renderer but that didnt solve anything since it flipped out and made the map ultra small.

I dont know the causes to problems like this. The map rendering is not different from the wiki, the camera is orthographic set to the width and height of the screen and follows the characters with a few problems. The collision is the following from the youtube tutorial;

		float oldX = position.x, oldY = position.y;
		boolean collisionX = false, collisionY = false;
		
		// Move in X.
		position.x = (position.x + velocity.x * Gdx.graphics.getDeltaTime() * SPEED);
		
		
		// Check collision in X.
		if(velocity.x < 0){ // going left
			collisionX = collidesLeft();

			}	else if(velocity.x > 0) {// going right
			collisionX = collidesRight();
			
		}
		// React to x collision
		if(collisionX) {
			position.x = oldX;
			velocity.x = 0;
		}
		// Move in Y.
		position.y = (position.y + velocity.y * Gdx.graphics.getDeltaTime() * SPEED);
		
		// Check collision in Y.
		increment = colLayer.getTileHeight();
		increment = getHeight() < increment ? getHeight() / 2 : increment / 2;

		if(velocity.y < 0) {// going down
			collisionY = collidesBottom();
		
		}	else if(velocity.y > 0) {// going up
			collisionY = collidesTop();

		}

		// React to y collision
		if(collisionY) {
			position.y = oldY;
			velocity.y = 0;
		}
	}
	
	
	private boolean isCellBlocked(float x, float y) {
		Cell cell = colLayer.getCell((int) (x / colLayer.getTileWidth()), (int) (y / colLayer.getTileHeight()));
		return cell != null && cell.getTile() != null && cell.getTile().getProperties().containsKey("blocked");
	}

	public boolean collidesRight() {
		/*for(float step = 0; step <= getHeight(); step += increment)
			if(isCellBlocked(position.x + getWidth(), position.y + step)){
				System.out.println("Right");
				return true;}*/
		
			if(isCellBlocked(position.x + getWidth(), position.y)){
				System.out.println("Right");
				return true;
			}else return false;
	}
/* there are 3 of these omitted due to being the same */

I’ve actually ran into a problem similar to this while using LibGDX and Tiled maps, make sure that where you are rendering the map, you’re not scaling it.

I have found nothing in my code that suggests any kind of scaling. I followed a LibGDX Tiled tutorial and did what he did, so have no idea where the error occurs. I have also checked the LibGDX wiki and found no sollutions there. When i try the scaling wound there all it does is to mess up the map to 1 x 1cm box, so that doesnt work.
Even so, if it would have been scaled, everything would have been scaled, not just one of the layers?

I think its a camera issue.
If you followed DermetFan teachings, im almost sure he went through *fixing" the camera…

Looking at the bitbucket for his project to be sure, i have all camera settings just as him.

We both create a OrthographicCamera, we both instanciate it in the show method and at the same time send it to the maprenderer, we both set the camera position on the player, and we update the camera after that. And if we resize the window we change the viewport.

So there are no differences there.

Well, the collision code is probably right, just show the map rendering / camera setup stuff. The problem is probably hidden there somewhere. I haven’t looked at the bitbucket project you mentioned but here is how it looks in mine (stripped down to a minimum):


// somewhere in the main class
public void create() {
        camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
        camera.setToOrtho(false, VIRTUAL_WIDTH, VIRTUAL_HEIGHT);
}

public void render() {
       mapHandler.draw();
       batch.setProjectionMatrix(camera.combined); // this one is important too, as you want the same projection matrix for your         
       //       sprite batch as for the map
       batch.begin();
       // render other stuff
       batch.end();
}


/// other class
public class MapHandler {
    private TiledMap map;
    private TiledMapRenderer mapRenderer;

    public void draw(SpriteBatch sb) {
        mapRenderer.render();
    }

    public void load(String s) {
        map = new TmxMapLoader().load(s);
        mapRenderer = new OrthogonalTiledMapRenderer(map);
        mapRenderer.setView(game.getCamera());
    }
}


public class GameScreen implements Screen {

	TheGame game;
 	TiledMap map;
	OrthogonalTiledMapRenderer mapRender;
	OrthographicCamera camera;
	Player player;
	SpriteBatch batch;	
	int height = Gdx.graphics.getHeight(), width = Gdx.graphics.getWidth();
	float scale = 1 / 32f;
	
	public GameScreen (TheGame game) {
		this.game = game;
	}

	public void render(float delta) {
		Gdx.gl.glClearColor(0, 0, 0, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		
		mapRender.setView(camera);
		mapRender.render();
		mapRender.getSpriteBatch().begin();
		mapRender.getSpriteBatch().end();
		batch.begin();
		batch.draw(player.getTexture(), player.position.x, player.position.y);
		batch.end();
		player.update();
		camera.position.set(player.position.x + player.getWidth() / 2, player.position.y + player.getHeight() / 2, 0);
		camera.update();
	}

	public void resize(int width, int height) {
		camera.viewportWidth = width;
		camera.viewportHeight = height;
		camera.update();

	}

	public void show() {
		map = new TmxMapLoader().load("maps/meh.tmx");
		mapRender = new OrthogonalTiledMapRenderer(map);
		camera = new OrthographicCamera(width, height);

		player = new Player(new Vector2(width / 2, height /2), 1, 30, new Texture("img/player2.png"), (TiledMapTileLayer) map.getLayers().get(0));
		Gdx.input.setInputProcessor(player);
		batch = new SpriteBatch();

	}

Thats all my code in the GameScreen. The scale float is a leftover from trying to fix the problem with the wiki article.

did you try the


batch.setProjectionMatrix(camera.combined);

?

I had tried that before to no avail. But it seems to fix part of the problem. The map is no longer scaled, but the collision isnt working correctly. Only seem to work on some of the sides of the blocked tiles, but its different on different combinations of placed tiles. Top side is blocked all the time though. Left only when its a single tile, right only single tiles, but also works when there are tiles to the left of it, but not above or below. And bottom side never blocks. :confused:

Amazing how copy pasting can have such different results.

And you did set your mapRenderer.setView() to camera.combined, too? :smiley:
Sorry, just trying to help but I can’t think of anything else now :slight_smile:

@Override
    public void resize(int width, int height) {
        camera.position.set(player.getX(), player.getY(), 0f);
        camera.viewportWidth = 800;
        camera.viewportHeight = 600;
        stage.setViewport(width, height, true);

       

    }

Try that.

And also, this :
*renderer = mapRender


...
 updateCamera();

//ARE YOU USING THIS : ?
            camera.update(true);

            //Clear Screen
            Gdx.gl.glClearColor(0, 0, 0, 1);
            Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
            //Render
            //Add Camera to renderer
            renderer.setView(camera);
            renderer.render();
....

seismic: The maprenderer does not allow to set views, i have tried that.
Andre: I am not using stages in my game. Should i?

I will contact dermetFan for you , because i really dont see any issue there.

[quote=“Sabomoth,post:12,topic:45152”]
This has nothing to do with your issue. There’s no need for a Stage for what you want to do.

[quote=“seismic,post:10,topic:45152”]
The setView method takes an OrthographicCamera, not a Matrix4. It uses the combined matrix of the given camera already.

Sabomoth: You are using two SpriteBatches (batch and the one in the map renderer). A SpriteBatch is a heavy object, so you should always just have one at a time. Also, it makes it more complicated to keep track of their matrices, like you are experiencing. In the code you posted in reply #6, you used the other SpriteBatch that didn’t have the combined matrix set. That’s why seismic’s suggestion in reply #7 fixed at least part of the problem. I suggest you to get rid of batch and use only the one from the map renderer. It’s projection matrix gets set by the setView(…) method already. Also, update before you render to avoid a lag of one frame.


public void render(float delta) {
      Gdx.gl.glClearColor(0, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      
      player.update();
      camera.position.set(player.position.x + player.getWidth() / 2, player.position.y + player.getHeight() / 2, 0);
      camera.update();

      mapRender.setView(camera);
      mapRender.render();
      mapRender.getSpriteBatch().begin();
      mapRenderer.getSpriteBatch().draw(player.getTexture(), player.position.x, player.position.y);
      mapRender.getSpriteBatch().end();
   }

Maybe your collision isn’t working properly because you don’t set increment before checking for the collision on the X axis:

// Move in X.
      position.x = (position.x + velocity.x * Gdx.graphics.getDeltaTime() * SPEED);
      
      // Check collision in X.
      // ...

It should be more along those lines:


      // Move in X.
      position.x = (position.x + velocity.x * Gdx.graphics.getDeltaTime() * SPEED);
      
      // calculate the increment for step in #collidesLeft() and #collidesRight()
      increment = collisionLayer.getTileWidth();
      increment = getWidth() < increment ? getWidth() / 2 : increment / 2;
      
      // Check collision in X.

Also make sure you use the correct coordinates in the collidesLeft, Right, Top and Bottom methods.