If I did not scale anything at all, this works for me:
sprite.setPosition(body.getPosition().x - sprite.getWidth() / 2, body.getPosition().y - sprite.getHeight() / 2);
About scaling, well this is also new for me. First thing to know about this is Box2D uses meter and its calculation are correct if the body dimensions are between 0.1 meters and 10 meters. So, if you don’t do any scaling, your 20x20 sprite will be 20 meters x 20 meters in Box2D.
Like I said, I am still experiencing about this. But people use some constants for this, which are:
static final float WORLD_TO_BOX = 0.01f;
static final float BOX_TO_WORLD = 100f;
Before I started to think about scaling, I thought these are the standard scaling constants but they are not. I mean, you could set WORLD_TO_BOX to 0.1f or even 2f if that’s the thing that will make your game work.
Here is something I use to experiment. Do not assume these are correct, because I might encounter some problems with the way I do things later;
I have a class which creates bodies. You pass some variables to that class. The method parameters are like this:
boxFactory.charBody(position, halfX, halfY, density, friction, restitution)
position is a Vector2. The rest are float values. My WORLD_TO_BOX and BOX_TO_WORLD values are 0.1f and 10f. So I have a ship, and I have a body for that. This is my body:
shipBody = boxFactory.charBody(new Vector2(40, 30), 3.2f, 3.2f, 0.1f, 1f, 0f);
I probably should have multiplied 32*WORLD_TO_BOX instead of giving 3.2f but like I said, experimenting right now.
I have a 64x64 image as my ship sprite. So I scale it:
sprite.setScale(MyBox.WORLD_TO_BOX);
MyBox is my class which creates bodies and WORLD_TO_BOX is a static constant of that class.
I am not entirely sure about my camera setup, but this is how I did it:
camera = new OrthographicCamera();
camera.setToOrtho(false, Gdx.graphics.getWidth() * MyBox.WORLD_TO_BOX, Gdx.graphics.getHeight() * MyBox.WORLD_TO_BOX);
I think this is not correct, because when I put this into resize() method, things are mixed up.
To sum up, 1 meter = (whatever you want) pixels.
This is the thread I tried to get help: http://www.java-gaming.org/topics/libgdx-box2d-scaling-between-world-and-box/29743/view.html
Philbedy has a different approach to that. You might try that as well.
EDIT: I think scaling is almost mandatory, because a 32x32 sprite will be 32x32 meters and this will mess up box2d simulation. I wasn’t able to find a good guide (well no guide at all) about how scaling should go. And I think the best way to experiment this is to build a working example without scaling, and then trying to implement scaling to it.
BTW, I just set up a InputProcessor and its touchDown method is like this:
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
System.out.println("X:" + screenX + " Y: " + screenY);
System.out.println(world.getEnemyBody().getPosition());
return true;
}
And when I click on the enemy body, the output is like this:
[quote]X:800 Y: 376
[80.0:30.0]
[/quote]
This might help you (and me) understand the scaling thing better.