package it.marteEngine;
import it.marteEngine.entity.Entity;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Vector2f;
/**
*
* for now let's just assume that the camera covers the whole screen, starting
* at 0,0 so no clipping area necessary
*
*/
public class Camera {
private World myWorld;
/** coordinates of the top left corner of the camera area in the world */
public float cameraX;
public float cameraY;
/** width and height of the render area for this camera */
private float renderWidth;
private float renderHeight;
private Vector2f maxSpeed = null;
private int horBorderPixel = 0;
private int vertBorderPixel = 0;
private Rectangle visibleRect = null;
private Rectangle moveRect = null;
private Entity follow;
public Camera(World world, Entity toFollow, int width, int height) {
this(world, toFollow, width, height, -1, -1, null);
}
public Camera(World world, Entity toFollow, int width, int height,
int horBorderPixel, int vertBorderPixel, Vector2f maxSpeed) {
this.cameraX = 0;
this.cameraY = 0;
this.renderWidth = width;
this.renderHeight = height;
this.follow = toFollow;
this.horBorderPixel = horBorderPixel;
this.vertBorderPixel = vertBorderPixel;
this.maxSpeed = maxSpeed;
if (toFollow != null) {
// on startup position camera that toFollow is in the center of the
// screen
this.cameraX = follow.x - (this.renderWidth / 2);
this.cameraY = follow.y - (this.renderHeight / 2);
}
this.myWorld = world;
this.visibleRect = new Rectangle(cameraX - horBorderPixel, cameraY
- vertBorderPixel, renderWidth + horBorderPixel, renderHeight
+ vertBorderPixel);
this.moveRect = new Rectangle(cameraX - horBorderPixel, cameraY
- vertBorderPixel, renderWidth + horBorderPixel, renderHeight
+ vertBorderPixel);
setCamera();
}
public void update(GameContainer container, int delta)
throws SlickException {
setCamera();
}
private void setCamera() {
// position camera so that follow is on the center of the screen
if (follow != null
&& !moveRect.contains(follow.x + follow.width / 2, follow.y
+ follow.height / 2)) {
float targetCX = follow.x - (this.renderWidth / 2);
float targetCY = follow.y - (this.renderHeight / 2);
// now smoothly move camera on position cameraX, cameraY to position
// targetCX, targetCY, using
// maxSpeed
if (maxSpeed != null) {
if (Math.abs(targetCX - cameraX) > maxSpeed.x) {
if (targetCX > cameraX)
cameraX += maxSpeed.x * 2;
else
cameraX -= maxSpeed.x * 2;
} else
cameraX = targetCX;
if (Math.abs(targetCY - cameraY) > maxSpeed.y) {
if (targetCY > cameraY)
cameraY += maxSpeed.y * 2;
else
cameraY -= maxSpeed.y * 2;
} else
cameraY = targetCY;
} else {
// move camera directly to new position
cameraX = targetCX;
cameraY = targetCY;
}
// recalculate worldX and worldY based on translateX and translateY
}
// Log.debug("setCamera(): cameraX = " + cameraX + ", cameraY = " +
// cameraY + ", follow.x = " + follow.x + ", follow.y = " + follow.y);
// do some border checking. we want to stay inside the world with our
// container
if (cameraX < 0)
cameraX = 0;
if (cameraX + renderWidth > myWorld.width)
cameraX = myWorld.width - renderWidth + 1;
if (cameraY < 0)
cameraY = 0;
if (cameraY + renderHeight > myWorld.height)
cameraY = myWorld.height - renderHeight + 1;
// Log.debug("setCamera2(): cameraX = " + cameraX + ", cameraY = " +
// cameraY + ", follow.x = " + follow.x + ", follow.y = " + follow.y);
// also calculate rendering rect to improve speed in contains() method
// later on for rendering
visibleRect.setBounds(cameraX - horBorderPixel, cameraY
- vertBorderPixel, renderWidth + horBorderPixel, renderHeight
+ vertBorderPixel);
moveRect.setBounds(cameraX + horBorderPixel / 2 - follow.speed.x,
cameraY + vertBorderPixel / 2, renderWidth - horBorderPixel
+ follow.speed.x, renderHeight - vertBorderPixel);
}
public boolean contains(Entity e) {
Rectangle entity = new Rectangle(e.x, e.y, e.width, e.height);
return visibleRect.intersects(entity);
}
public World getMyWorld() {
return myWorld;
}
public void setMyWorld(World myWorld) {
this.myWorld = myWorld;
}
public Entity getFollow() {
return follow;
}
public void setFollow(Entity follow) {
this.follow = follow;
}
public Rectangle getVisibleRect() {
return visibleRect;
}
public Rectangle getMoveRect() {
return moveRect;
}
}