Search code examples
javalibgdxbox2d

How to get b2box body and a sprite to rotate at same speed?


I am trying to make 2D game and I am stuck in making a body of box2D and a textureRegion to rotate at the same speed. My tetxureRegion rotates at a faster speed than the body of box2D. I think the problem might come from the "b2body.setAngularVelocity(-1)"and "rotate(-1)". Someone help me please....thanks

public class VanishableBLock extends Sprite {

private World world;
private GameScreen screen;
public Body b2body;
public Vector2 velocity;
private float stateTime;
private TextureRegion picture;
private Rectangle rectangle;

public VanishableBLock(GameScreen screen, Rectangle rectangle) {
    this.rectangle = rectangle;
    this.world = screen.getWorld();
    this.screen = screen;
    setPosition((rectangle.getX()+rectangle.getWidth()/2) / MavisAdventure.PPM, (rectangle.getY() +rectangle.getHeight()/2)/ MavisAdventure.PPM);
    setOrigin(rectangle.getWidth()/2/ MavisAdventure.PPM,rectangle.getHeight()/2/ MavisAdventure.PPM);
    this.rectangle.height = rectangle.getHeight();
    this.rectangle.width = rectangle.getWidth();
    createVanishableBLock();
    velocity = new Vector2(0, 0.08f);
    picture = new TextureRegion(screen.getAtlas().findRegion("big_mario"), 80, 0, 16, 32);
    stateTime = 0;
    setRegion(picture);
    setBounds(getX(), getY(), rectangle.getWidth() / MavisAdventure.PPM, rectangle.getHeight() / MavisAdventure.PPM);
}
public void createVanishableBLock()
{
    BodyDef bdef = new BodyDef();
    bdef.position.set(getX(),getY());
    bdef.type = BodyDef.BodyType.DynamicBody;
    b2body = world.createBody(bdef);
    FixtureDef fdef = new FixtureDef();
    PolygonShape shape = new PolygonShape();
    shape.setAsBox(rectangle.getWidth()/2/MavisAdventure.PPM, rectangle.getHeight()/2/MavisAdventure.PPM);
    fdef.shape = shape;
    fdef.density = 1000;
    b2body.createFixture(fdef).setUserData(this);
}

public void update(float dt)
{
    stateTime +=dt;

    b2body.setAngularVelocity(-1);
    rotate(-1);             //these 2 cannot rotate at same speed

    b2body.setLinearVelocity(velocity );
    setPosition(b2body.getPosition().x - getWidth()/2, b2body.getPosition().y - getHeight()/2);
    setRegion(picture);
}
public void draw(Batch batch)
{
        super.draw(batch);
}

} enter image description here


Solution

  • From the docs for Sprite:

    rotate(float degrees)
    Sets the sprite's rotation in degrees relative to the current rotation.

    and from the docs for b2Body:

    void b2Body::SetAngularVelocity(float32 omega)
    Set the angular velocity.
    Parameters
    omega the new angular velocity in radians/second.

    So one method expects radians and one method expects degrees. You have to convert your value.

    Either radians to degree: b2body.setAngularVelocity(-1 * 180.f / PI);

    Or degree to radians: rotate(-1 * PI / 180.f);

    where PI is a final static value holding the value of π.

    Apart from that these methods also do different things: One sets a velocity, one sets a relative rotation angle. Even after fixing the parameters, it's only luck if you get the same result, which can only happen if you call these every frame and the frame duration matches exactly the box2d angular velocity (meaning that it rotates by exactly omega every frame).

    I would recommend copying the actual angle of your b2Body object into the sprite, instead of having both the physics engine and the rendering engine calculate rotations. The physics engine should have authority over object position and rotation, while the renderer should just render. Like so:

    setRotation(b2body.getAngle() * 180.f / PI);