Welp. Turns out it wasn’t as hard as I thought. I found a simple Camera class for use with TileMaps, and modified it to work with a background image instead. Here it is for anyone that wants to use it:
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Image;
public class Camera
{
// Image to draw
protected Image bg;
// Position of the camera
protected float camX, camY;
// Width and height of image
protected float bgWidth, bgHeight;
// Game container to get screen width/height
protected GameContainer gc;
/**
* Create new Camera
*
* @param gc the game container
* @param bg the background image
*/
public Camera(GameContainer gc, Image bg)
{
this.bg = bg;
bgWidth = bg.getWidth();
bgHeight = bg.getHeight();
camX = camY = 0;
this.gc = gc;
}
/**
* Centers on the x, y coordinate given. If the camera comes to
* an edge of the image, the camera stops
*
* @param x x position to center on
* @param y y position to center on
*/
public void centerOn(float x, float y)
{
camX = x - gc.getWidth() / 2;
camY = y - gc.getHeight() / 2;
if(camX < 0)
camX = 0;
if(camX + gc.getWidth() > bgWidth)
camX = bgWidth - gc.getWidth();
if(camY < 0)
camY = 0;
if(camY + gc.getHeight() > bgHeight)
camY = bgHeight - gc.getHeight();
}
/**
* Centers on the x coordinate given. Use so the camera
* only accounts for horizontal movement
*
* @param x x position to center on
*/
public void centerOnX(float x)
{
camX = x - gc.getWidth() / 2;
if(camX < 0)
camX = 0;
if(camX + gc.getWidth() > bgWidth)
camX = bgWidth - gc.getWidth();
}
/**
* Centers on the y coordinate given. Use so the camera
* only accounts for vertical movement
*
* @param y y position to center on
*/
public void centerOnY(float y)
{
camY = y - gc.getHeight() / 2;
if(camY < 0)
camY = 0;
if(camY + gc.getHeight() > bgHeight)
camY = bgHeight - gc.getHeight();
}
/**
* Draw the background
*/
public void draw()
{
this.draw(camX, camY);
}
/**
* Draw the background using an offset separate of the camera
*
* @param offsetX x offset to use
* @param offsetY y offset to use
*/
public void draw(float offsetX, float offsetY)
{
gc.getGraphics().drawImage(bg, 0, 0, offsetX, offsetY,
offsetX + gc.getWidth(), offsetY + gc.getHeight());
}
/**
* Translates all graphics relative to the camera
*/
public void translateGraphics()
{
gc.getGraphics().translate(-camX, -camY);
}
/**
* Undoes translateGraphics(). Use before drawing anything
* that is independent of camera position, like HUD's.
*/
public void untranslateGraphics()
{
gc.getGraphics().translate(camX, camY);
}
}
An example of using it in the render() method:
Camera cam;
Image bg;
Image player;
float px, py; // Player coordinates
public void init(GameContainer gc)
{
bg = new Image("Image path");
player = new Image("Image path");
cam = new Camera(gc, bg);
px = py = 0;
}
public void render(GameContainer gc, Graphics g)
{
cam.centerOn(x, py);
cam.draw();
cam.translateGraphics();
g.drawImage(player, x, y);
}
public void update(GameContainer gc, int delta)
{
// Move player and stuff
}