You could just choose real world proportions for calculations (human ~ 1.8m, speed in m/s etc) and use the viewport class to transform this into screen coordinates.
You calculate the sprites world size by multiplying the size in pixels by some factor.
Lets say you want 32 pixel per meter along the x axis with a 45 degrees camera angle.
public static final float ymodp = (float)Math.sqrt(0.5d); //multiply this with y to project
public static final float ymodu = 1f/ymodp; //multiply this with y to unproject
public static final float ppm = 32; //pixels per meter
public static final float mpp = 1f/ppm; // meters per pixel
public static int wv = Gdx.graphics.getWidth(); //Sceen width in pixels
public static int hv = Gdx.graphics.getHeight(); //Sceen height in pixels
public static float ww = wv * mpp; //Viewport width in meters
public static float hw = hv * mpp; //Viewport height in meters
Before using your Sprite call this once to set it’s size to be in meters:
sprite.setSize(sprite.getWidth() * mpp, sprite.getHeight() * mpp);
and for the batch:
spriteBatch.setProjectionMatrix(camera.combined);
And when rendering (sprite.getWidth() is in meters now):
sprite.setPosition(-sprite.getWidth() / 2f + position.x, -sprite.getHeight() / 2f + (position.y + position.z) * ymodp);
sprite.draw(spriteBatch);
This draws the sprite centered. (y+z)*projectionCoefficient is only possible because the camera is tilted 45 degrees which means that y and z have equal influence on the perceived y-position of the sprite on screen!
You can now do all other calculations in the normal world coordinate system where 1 unit is 1 meter in all directions.
To move the camera keep in mind that the y axis is not flat anymore, you need to use your projection constant:
public void setPosition(float x, float y, float z) {
camPos.set(x, y, z); //keep the camera position in world coordinates for later use
Math2D.project(camPosProjected.set(camPos)); //transform
camera.position.set(camPosProjected); //set position
camera.update();
}
public static Vector3 project(Vector3 v){
v.y = Metrics.ymodp * (v.y + v.z);
v.z = 0f;
return v;
}
Here’s the whole magic:
GameScreen
SpriteRenderSystem
CameraController2D
Math2D
Metrics