LibGdx sprite rotation vs Box2D physics rotation problem
Tearing my hair out on this one. I am an experienced software developer, but very new to LibGdx and Box2D development.
I am writing a game where the game board is the size of the screen. The game board does not pan - it just fills the screen. For the descriptions below presume that the device is being held vertically, so that vertical is the longest length. Also, for the description below, presume that on a device with a 'normal' aspect ratio, circles will be rendered perfectly circular, but a device that is narrower than expected, the circles will be squashed so that they are taller than wide.
I have a number of circle shapes that are rendered to the screen.
Because different devices will have different width / height aspect ratios, I am happy for the circle shapes to be squashed on a device that is narrower on the horizontal than expected (I am trying to avoid maintaining identical aspect ratios and forcing black borders at the edges of the game board).
My problem is this: when Box2D debug renders the screen, showing the physics objects, the circle shapes maintain their width and height, even when rotated. To describe further, if a sphere is displayed with 0 degree rotation on a narrow device, it takes an oval shape that is taller than it is wide, as would be expected on a narrower than expected device. If you rotate the circle shape by 90 degrees, the Box2d debug renderer shows the rotation (there is a line that sticks out of the centre of the object at an angle that shows the angle of rotation) but the object maintains its taller than wide oval shape. This is correct, as a sphere on a horizontally narrower aspect-ratioed device will always be displayed taller than wide.
When I attempt to overlay a LibGDX sprite on top of the Box2D physics simulation (the sprite, in its unaltered form, is circular, and is then scaled to the devices aspect ratio), with a zero degree angle, it appears nicely mapped to the Box2D representation - taller than it is wide. However, when I rotate the LibGDX sprite by 90 degrees, it appears rotated the way a billboard image would be rotated, so it is now wider than it is tall (imagine drawing a taller-than-wide oval on a piece of paper and turning the piece of paper by 90 degrees).
It appears to me that Box2D applies rotation before it applies the camera scaling - so the circular object is rotated first (maintaining its circular shape under the hood), and then sqaushed to form an ellipse that is taller than wide on the screen. Whereas, the LibGDX engine applies the transforms in reverse. The object is squashed to taller-than-wide, then rotated, so it becomes wider-than-tall on the screen.
I have pasted the relevant code below:
//screen size in box2D metres
private static float screenHeight = 100.0f;
private static float screenWidth = 70.0f;
//set up the camera in the show() method
cam = new OrthographicCamera(screenWidth, screenHeight);
cam.position.set(screenWidth / 2, screenHeight / 2, 0);
//render method
batch.begin();
for (int i = 0; i < ballList.length; i++)
{
ballList[i].render(batch);
}
batch.end();
//ball class render method
public void render(SpriteBatch batch)
{
ballHappyImage.setOrigin(64.0f, 64.0f);
ballHappyImage.setPosition(body.getPosition().x - 64.0f, body.getPosition().y - 64.0f);
float scaleWidth = Gdx.graphics.getWidth() / 1400.0f; //hardcoded to make things fit correctly
float scaleHeight = Gdx.graphics.getHeight() / 2000.0f; //hardcoded to make things fit correctly
ballHappyImage.setRotation(body.getAngle() * MathUtils.radiansToDegrees);
ballHappyImage.setScale(scaleWidth, scaleHeight);
ballHappyImage.draw(batch);
}
The images below show the Box2D debug rendered line drawings overlayed on the libgdx sprites.