Jump to content
  • Advertisement
stitchs_login

2D Camera Jitters

This topic is 436 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey,

I'm running through some game tutorials and have just implemented my camera. It scrolls, following the player sprite, and culls tiles from the map outside of bounds.

One thing I'm noticing is some minor artifact tearing between some of the tiles that make up the on-screen map. Originally, I assumed it was because I coded my camera X and Y as Integers, and my player coordinates as floats, so there was some classic data loss from downcasting float -> int. I modified that, and removed integer casts that related to passing player coordinates to the camera. This has reduced the tearing, but everything still jitters a small amount.

The player only moves at a speed of 1.0f. If I run it at 3.0f, it is more noticable. Where could I be going wrong?

Thanks,

Stitchs (code below).

package dev.mygame.display;

public class Camera
{
	private float x;
	private float y;
	private int w;
	private int h;
	private int focusX;
	private int focusY;
	
	public Camera(float x, float y, int w, int h)
	{
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
	}
	
	public float getX()
	{
		return x;
	}
	
	public void setX(float x)
	{
		this.x = x;
	}
	
	public float getY()
	{
		return y;
	}
	
	public void setY(float y)
	{
		this.y = y;
	}
	
	public int getFocusX()
	{
		return focusX;
	}
	
	public void setFocus(float focusX, float focusY)
	{
		float lerp = 1.0f;
		x += lerp * (focusX - w/2 - x);
		y += lerp * (focusY - h/2 - y);
	}
	
	public int getFocusY()
	{
		return focusY;
	}
	
	public int getWidth()
	{
		return w;
	}
	
	public int getHeight()
	{
		return h;
	}
	
	public void tick()
	{
		// centre the camera on the focus point
		//focusX -= w/2;
		//focusY -= h/2;
		// set the origin so we can offset everything else
		x = focusX;
		y = focusY;
	}
}
package dev.mygame.entities.creatures;

import java.awt.Graphics;

import dev.mygame.gfx.Assets;
import dev.mygame.Game;

public class Player extends Creature
{
	private Game game;
	
	public Player(Game game, float x, float y)
	{
		super(game, x, y, Creature.DEFAULT_WIDTH, Creature.DEFAULT_HEIGHT);
		this.game = game;
	}
	
	@Override
	public void tick()
	{
		getInput();
		move();
	}
	
	private void getInput()
	{
		xMove = 0;
		yMove = 0;
		
		if(game.getKeyManager().up)
		{
			yMove = -speed;
		}
		if(game.getKeyManager().down)
		{
			yMove = +speed;
		}
		if(game.getKeyManager().left)
		{
			xMove = -speed;
		}
		if(game.getKeyManager().right)
		{
			xMove = +speed;
		}
	}
	
	@Override
	public void render(Graphics g)
	{
		g.drawImage(Assets.playerOne, (int)(x - game.getCamera().getX()), (int)(y - game.getCamera().getY()), width, height, null);
	}
}
package dev.mygame.states;

import java.awt.Graphics;

import dev.mygame.entities.creatures.Player;
import dev.mygame.gfx.Assets;
import dev.mygame.Game;
import dev.mygame.worlds.World;
import dev.mygame.display.Camera;

public class GameState extends State
{
	private Player player;
	private World world;
	
	public GameState(Game game)
	{
		super(game);
		world = new World(game, "/maps/World1.json");
		player = new Player(game, world.getSpawnX(), world.getSpawnY());
	}
	
	@Override
	public void tick()
	{
		player.tick();
		game.getCamera().setFocus(player.getX() + player.getWidth()/2, player.getY() + player.getHeight()/2);
	}
	
	@Override
	public void render(Graphics g)
	{
		world.render(g);
		player.render(g);
	}
}

 

Edited by stitchs_login

Share this post


Link to post
Share on other sites
Advertisement

I would focus on your camera::setFocus function.

The (focusX - w/2) bit gives the offset by itself but (focusX - w/2 - x) seems like it throws it an additional unnecessary amount. I don't see you call camera::tick which is good because then we'd probably be talking half screen jitter. The other mess would be your variable naming between function arguments and the class members. Refactor some naming to make sure you are setting what you think you're setting and double check your camera position logic for one or two render frames by walking the logic by hand.

It's difficult because I don't see your base Creature::move is doing with your user input.

Share this post


Link to post
Share on other sites

Hi @GoliathForge,

The tick() method in Camera is a hangover that I'm removing in this phase. When you say that I should refactor some naming, do you mean that having the parameter names the same as the instance-level members could be confusing? Or am I missing some consistency in the naming pattern?

As for Creature::move()

package dev.mygame.entities.creatures;

import dev.mygame.entities.Entity;
import dev.mygame.Handler;

public abstract class Creature extends Entity
{
	public static final int DEFAULT_HEALTH = 10;
	public static final float DEFAULT_SPEED = 1.0f;
	public static final int DEFAULT_WIDTH = 64;
	public static final int DEFAULT_HEIGHT = 64;
	
	protected int health;
	protected float speed;
	protected float xMove;
	protected float yMove;
	
	public Creature(Handler handler, float x, float y, int width, int height)
	{
		super(handler, x, y, width, height);
		health = DEFAULT_HEALTH;
		speed = DEFAULT_SPEED;
		xMove = 0f;
		yMove = 0f;
	}
	
	public void move()
	{
		x += xMove;
		y += yMove;
	}
	....
}

I admit, I haven't yet printed the values to the setFocus method, so I will do that in my next round of implementation. Thinking about my original wording, if anything, it's not camera jitter I'm experiencing. It's more akin to a tear in some graphic rendering between tiles when I move my player vertically.

@the incredible smoker

On 10/6/2017 at 4:34 PM, the incredible smoker said:

Floats are not accurate.

Could you elaborate in relation to the screen-tearing that I'm experiencing? Right now, I don't *need* the precision provided by doubles. It would be something I'd consider in the future when I begin to implement physics calculations that may require it. Currently, I'm following a tutorial series that doesn't suggest using them. If this is a possible solution to my issues, I would love to hear some more context to your answer.

Thanks,

Stitchs.

Share this post


Link to post
Share on other sites
3 hours ago, stitchs_login said:

When you say that I should refactor some naming, do you mean that having the parameter names the same as the instance-level members could be confusing?

right...it's just a little thing, but every bit helps.

3 hours ago, stitchs_login said:

Thinking about my original wording, if anything, it's not camera jitter I'm experiencing. It's more akin to a tear in some graphic rendering between tiles when I move my player vertically.

Ah, very good. I'm not a java user but it's my understanding that you can't enable vsync programmatically and has to be done with the graphics card's settings interface. Try that. 

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!