The problem has to do with Image's center of rotation not being scaled with the draw() method. Here's a test that demonstrates the issue and a couple of workarounds.
Use the arrow keys to move the camera, W/S to zoom the camera, and 1, 2 and 3 to change the way the sprite is drawn.
Code:
import org.newdawn.slick.Image;
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.BasicGame;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
/**
*
* @author davedes
*/
public class SlickTest extends BasicGame {
public SlickTest() {
super("");
}
public static void main(String[] args) throws SlickException {
new AppGameContainer(new SlickTest(), 800, 600, false).start();
}
private float locx, locy, camx, camy;
private float camzoom = 1f;
private Image sprite;
private int mode = 1;
private float rot = 0;
@Override
public void init(GameContainer gc) throws SlickException {
sprite = new Image("res/pic.jpg");
}
@Override
public void update(GameContainer gc, int delta) throws SlickException {
if (gc.getInput().isKeyDown(Input.KEY_LEFT)) {
camx -= 5;
}
else if (gc.getInput().isKeyDown(Input.KEY_RIGHT)) {
camx += 5;
}
else if (gc.getInput().isKeyDown(Input.KEY_UP)) {
camy -= 5;
}
else if (gc.getInput().isKeyDown(Input.KEY_DOWN)) {
camy += 5;
}
if (gc.getInput().isKeyDown(Input.KEY_W)) {
camzoom += 0.005f;
}
else if (gc.getInput().isKeyDown(Input.KEY_S)) {
camzoom -= 0.005f;
}
if (gc.getInput().isKeyPressed(Input.KEY_1)) {
mode = 1;
//reset to the default...
sprite.setCenterOfRotation(sprite.getWidth()/2f, sprite.getHeight()/2f);
} else if (gc.getInput().isKeyPressed(Input.KEY_2)) {
mode = 2;
} else if (gc.getInput().isKeyPressed(Input.KEY_3)) {
mode = 3;
//reset to the default...
sprite.setCenterOfRotation(sprite.getWidth()/2f, sprite.getHeight()/2f);
}
rot += delta * 0.03f;
}
@Override
public void render(GameContainer gc, Graphics g) throws SlickException {
int x = (int) (locx - camx - sprite.getWidth() / 2f);
int y = (int) (locy - camy - sprite.getHeight() / 2f);
float xpos = x/camzoom + (gc.getWidth()/2f);
float ypos = y/camzoom + (gc.getHeight()/2f);
if (mode==1) {
//what you are doing now...
sprite.setRotation(rot);
sprite.draw(xpos, ypos, 1 / camzoom);
} else if (mode==2) {
//until the bug is fixed you can resolve the issue like so:
float cx = sprite.getWidth() / camzoom / 2f;
float cy = sprite.getHeight() / camzoom / 2f;
sprite.setCenterOfRotation(cx, cy);
sprite.setRotation(rot);
sprite.draw(xpos, ypos, 1 / camzoom);
} else if (mode==3) {
//another way to do it would be to separate camera
//scaling/position and sprite scaling/position
g.translate(gc.getWidth()/2f - camx/camzoom, gc.getHeight()/2f - camy/camzoom);
g.scale(1/camzoom, 1/camzoom);
sprite.setRotation(rot);
sprite.draw(locx-sprite.getWidth()/2f, locy-sprite.getHeight()/2f);
g.resetTransform();
}
g.drawString("Cam zoom: "+camzoom, 10, 25);
g.drawString("Cam loc: "+camx+", "+camy, 10, 40);
g.drawString("Mode: "+mode, 10, 60);
}
}