Search code examples
javalibgdx

Moving an object based on its rotation


I have this ship sprite (prototype for now) and I've been trying to move it along its rotation but it is not working so well.
<-- Vid -->
https://i.sstatic.net/W64bS.jpg
<-- Example Image of what I think should happen --> enter image description here When researching, I saw that sometimes the cosine is for the x position and the sign is for the y position, this makes me a little confused about what to do. But sometimes I saw otherwise which makes me wonder since I thought the x should be using sine and y should be cosine.

Code:

package com.lance.seajam;

import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.Gdx;
import java.lang.Math;

public class Player {
    private final float rotSpeed;
    private final float movementSpeed;

    private final Texture texture;
    private final int textureWidth;
    private final int textureHeight;
    private final SpriteBatch batch;
    private Vector2 position;
    private int rotation;
    private float originX;
    private float originY;
    private int realRot;

    private double DEG2RAD = 180 / Math.PI;

    public Player(Texture texture, SpriteBatch batch) {
        this.texture = texture;
        this.batch = batch;
        this.rotation = 0;
        this.textureWidth = texture.getWidth();
        this.textureHeight = texture.getHeight();
        this.position = new Vector2(300, 300);

        this.originX = textureWidth/2;
        this.originY = textureHeight/2;
        this.rotSpeed = 3f;
        this.movementSpeed = 3f;
    }

    public void Movement() {
        if (Gdx.input.isKeyPressed(Keys.A)) rotation += rotSpeed;
        if (Gdx.input.isKeyPressed(Keys.D)) rotation -= rotSpeed;

        realRot = rotation;

        if (rotation >= 360) realRot = 360;
        if (rotation <= 0) realRot = 0;

        double xVel = 0;
        double yVel = 0;

        xVel += Math.cos(realRot) * movementSpeed;
        yVel += Math.sin(realRot) * movementSpeed;

        if (Gdx.input.isKeyPressed(Keys.W)) {
            position.x += xVel;
            position.y += yVel;
        }

        System.out.println(xVel);
    }

    public void DrawSprite() {
        batch.draw (
            texture, position.x, position.y,
            originX, originY, textureWidth,
            textureHeight, 1, 1,
            rotation, 1, 1, textureWidth,
            textureHeight, false, false
        );
    }
}

Solution

  • If you create an extra Vector2 member, direction in your Player class you can get libGDX to calculate the x and y delta by using the rotateDeg method on Vector2:

    direction.set(Vector2.X).rotateDeg(realRot);
    

    This will set direction to (1, 0) and then rotate it by your rotation amount. Then you can just add direction.x and direction.y to your position.

    position.x += direction.x;
    position.y += direction.y;
    

    or even shorter:

    position.add(direction);
    

    enter image description here

    Full source for Player for the above animation is:

    public class Player {
        private final float rotSpeed;
        private final float movementSpeed;
    
        private final Texture texture;
        private final int textureWidth;
        private final int textureHeight;
        private final SpriteBatch batch;
        private Vector2 position;
        private Vector2 direction = new Vector2(Vector2.X); // Add this
        private int rotation;
        private float originX;
        private float originY;
        private int realRot;
    
        private double DEG2RAD = 180 / Math.PI;
    
        public Player(Texture texture, SpriteBatch batch) {
            this.texture = texture;
            this.batch = batch;
            this.rotation = 0;
            this.textureWidth = texture.getWidth();
            this.textureHeight = texture.getHeight();
            this.position = new Vector2(0, 0);
    
            this.originX = textureWidth/2;
            this.originY = textureHeight/2;
            this.rotSpeed = 3f;
            this.movementSpeed = 3f;
        }
    
        public void Movement() {
            if (Gdx.input.isKeyPressed(Input.Keys.A)) rotation += rotSpeed;
            if (Gdx.input.isKeyPressed(Input.Keys.D)) rotation -= rotSpeed;
    
            realRot = rotation;
    
            // You don't really need this
            //if (rotation >= 360) realRot = 360;
            //if (rotation <= 0) realRot = 0;
    
            // At each update, set the direction vector to point to the right, and then rotate
            // it using your readRot variable.
            direction.set(Vector2.X).rotateDeg(realRot);
    
            direction.scl(movementSpeed); // Scale the direction by you speed
    
            if (Gdx.input.isKeyPressed(Input.Keys.W)) {
                position.x += direction.x;
                position.y += direction.y;
            }
        }
    
        public void DrawSprite() {
            batch.draw (
                    texture, position.x, position.y,
                    originX, originY, textureWidth,
                    textureHeight, 1, 1,
                    rotation, 1, 1, textureWidth,
                    textureHeight, false, false
            );
        }
    }