Couple questions about camera and movement on 2d tiled game

Hey guys

I’m working on a 2d top-down tiled game. I’m doing it to learn but will probably turn it into a another farming game similar to harvest moon. I’ve got the map loaded and character displayed and all that, but i’m having a little bit of trouble with a couple things.

I’ve got my camera set up and it follows the player around…but i’m having trouble getting it to stop scrolling when the player gets near the end of the map. Below is my code. I’ve only done the x axis and i’ve just been playing with the values.


public void render() {		
		//handleInput();
		
		GL10 gl = Gdx.graphics.getGL10();
		gl.glClearColor(0, 0, 0, 1);
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
		gl.glViewport((int)glViewport.x, (int)glViewport.y, (int)glViewport.width,(int) glViewport.height);
		
		map.renderer.setView(camera);
		map.render();
		
		map.renderer.getSpriteBatch().setProjectionMatrix(camera.combined);
		map.renderer.getSpriteBatch().begin();
		
		
		
		mainPlayer.Draw((SpriteBatch) map.renderer.getSpriteBatch());
		
		map.renderer.getSpriteBatch().end();

//move camera to follow player	
	if (mainPlayer.getPosition().x >= 15 && mainPlayer.getPosition().x <= 30) {
		camera.position.x = mainPlayer.getPosition().x;
		
		}
		System.out.println(camera.position.x);
		camera.position.y = mainPlayer.getPosition().y;
		
		camera.update();
		camera.apply(gl);
		
	}

below is a picture of what i’m talking about. I don’t want the black area to be seen.

http://s21.postimg.org/wt6tgs7bn/cameratest.jpg

I’ve been searching around a bit and I know how i’m going to do my collision detection. I’m going to do it the same way dermetfan does it in his video tutorial. How would be the best way to keep the player on the map? Just do a check to make sure the cell isn’t null? Also, i’m a bit confused as how to warp to the next map when the player hits the edges of the map.

Also, this is more of an opinion from you guys, but what should I do next? I know this is a pretty dumb question, but i’m doing this to learn as well as turning it into a game…I thought about adding particle effects next because they interest me. I still have quite a few things to implement though…time system, gui, tools, and NPC’s which I still have no clue how i’m going to do.

You could check if the camera exceeds the desired bounds at the player’s new position. If it does, set the camera position to the maximum possible without crossing the bounds. If not, just set it to player position. You could pre-calculate the max & min camera positions yourself, based on the map size & camera scale and all that, before the camera & map becomes visible.

Then it’d just be a case of doing this (In pseudo code, and just for x):


if(player.getX() > Camera.MAX_X) {
     camera.x = Camera.MAX_X;
} else if(player.getX() < Camera.MIN_X) {
     camera.x = Camera.MIN_X;
} else {
     camera.x = player.getX();
}

Here is how I implemented it… This also “interpolates” speed to move to player. Basically makes it look like you’re following the player slowly, not instantly.

public class Camera extends Entity {

	private Player player;
	private Level level;

	public Camera(Level level, Player player) {
		this.level = level;
		this.player = player;

		x = (level.width * Level.TILE_SIZE) / 2;
		y = (level.height * Level.TILE_SIZE) / 2;
	}

	public void tick() {
		Shader.NORMAL.getVariableLoc("offset");

		doMove();

		level.offset.x = ((float) this.x - Game.WIDTH / 2);
		level.offset.y = ((float) this.y - Game.HEIGHT / 2);

	}

	private void doMove() {
		float xd = this.x - (player.x + width / 2);
		float yd = this.y - (player.y + height / 2);

		float xspeed = xd / 1;
		float yspeed = yd / 1;

		SnowFlake.cxs = 0;
		SnowFlake.cys=0;
		
		if (ableToMove(xspeed, 0)) {
			x -= xspeed;
			SnowFlake.cxs = xspeed;
		}
		if (ableToMove(0, yspeed)) {
			y -= yspeed;
			SnowFlake.cys = yspeed;
		}
		
	}

	private boolean ableToMove(float xspeed, float yspeed) {
		float xx = x - xspeed;
		float yy = y - yspeed;
		int w = Game.WIDTH / 2;
		int h = Game.HEIGHT / 2;
		
		boolean bool =check(xx + w, yy) && check(xx, yy + h) && check(xx - w, yy) && check(xx, yy - h);
		return true;
	}

	private boolean check(float x, float y) {
//		return (x < 0 || x >= level.width * Level.TILE_SIZE || y < 0 || y >= level.height * Level.TILE_SIZE);
		
		return !level.outOfBounds(Casting.castFloat(x), Casting.castFloat(y)); // same as (int) x, (int) y, almost.
	}


public class Casting {

	public static int castFloat(float f) {
		int ff = (int) f;
		if (f < 0) ff -= 1;
		if (f > 0) f += 1;
		return ff;
	}

}

}

This code basically checks if camera.x + Screen.WIDTH/2 < Level.WIDTH

nerb-

That’s almost exactly what i’m already doing in the code…I’m just having issues determining the max_x and max_y.

trollwarrior-

Thanks. That makes a little more sense. I’m not using my own camera class, just have it thrown in but i’m thinking about changing that just to make it a little easier to work with the camera. I’m not sure I follow your example 100% but it’s definitely a help.