# How do I limit the rotation speed of a mouse-following object?

I am trying to make a 2D top-down game where player controls a spaceship. The spaceship (a rocket) is just a sprite following the mouse cursor with a fixed speed and is always pointing toward the cursor location. I calculate rotation using atan2(yDistance, xDistance). I've already implemented movement to cursor and rotation toward cursor;

float XDistance = Xplayer - Gdx.input.getX();
float YDistance = Yplayer - (Gdx.graphics.getHeight() - Gdx.input.getY());

rotation = (float) Math.atan2(YDistance, XDistance);

if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)) {
if (XDistance >= playerSpeed | YDistance >= playerSpeed | XDistance <= -playerSpeed | YDistance <= -playerSpeed) {
Xplayer -= (float) (playerSpeed * Math.cos(rotation) * deltaTime);
Yplayer -= (float) (playerSpeed * Math.sin(rotation) * deltaTime);
}
MathUtils.clamp(Xplayer, 0, Gdx.graphics.getWidth());
MathUtils.clamp(Yplayer, 0, Gdx.graphics.getHeight());
sprite.setPosition(Xplayer - sprite.getOriginX(), Yplayer - sprite.getOriginY());
sprite.setRotation((float) Math.toDegrees(rotation));


This algorithm makes U-turn (and every rotation in general) instant. I want to achieve a smoother rotation. Instead of instant rotation, I'd like to implement either a curve or simply a bit slower, non instant rotation (while still moving towards cursor current location).

Also, instead of fixed velocity, I am trying to implement acceleration and deceleration, but to no success (for now).

I've already googled lots of various algorithms, but never found the right one.

Update:

public class PlayerEntity {

private float movementSpeedMax;
private float rotationSpeedMax;
private float decay;
private float destinationX;
private float destinationY;

// player
private float playerX;
private float playerY;
private float rotation;

// global
private float _dx;
private float _dy;

private float _vx;
private float _vy;

private float actualRotation = 0;

public PlayerEntity(){
movementSpeedMax = 1000;
rotationSpeedMax = 15;
decay = .95f;
destinationY = 500;
destinationX = 500;
playerX = 0;
playerY = 0;
rotation = 0;
_dx = 0;
_dy = 0;
_vx = 0;
_vy = 0;
actualRotation = 0;
}

public int getX() {
return (int) playerX;
}

public int getY() {
return (int) playerY;
}

public float getAngle() {
return  rotation;
}

public void updateRotation() {
// calculate rotation
_dx = playerX - destinationX;
_dy = playerY - destinationY;

// which way to rotate

// keep rotation positive, between 0 and 360 degrees
if (rotateTo > rotation + 180) {
rotateTo -= 360;
}
if (rotateTo < rotation - 180) {
rotateTo += 360;
}

// ease rotation
actualRotation = (rotateTo - rotation)/ rotationSpeedMax;

// update rotation

if (actualRotation < 180);
rotation += actualRotation;

}

/**
* Calculate Position
*/
public void updatePosition() {
// check if mouse is down
if (Gdx.input.isButtonPressed(Input.Keys.LEFT)) {
// update destination
destinationX = Gdx.input.getX();
destinationY = Gdx.graphics.getHeight() - Gdx.input.getY();

// update velocity
_vx += (destinationX - playerX) / movementSpeedMax;
_vy += (destinationY - playerY) / movementSpeedMax;
}

// apply decay (drag)

_vx *= decay;
_vy *= decay;

// if close to target, slow down turn speed
if (getLength(_dx, _dy) < 50) {
actualRotation *= .25f;
}

if (getDistanceCorrect(destinationX, playerX, destinationY, playerY) < 5) {
_vx = 0;
_vy = 0;
}

// update position
playerX += _vx;
playerY += _vy;
}

private float getLength(float delta_x, float delta_y) {
return (float) Math.sqrt((delta_x * delta_x) + (delta_y * delta_y));
}

private float getDistanceCorrect(float x1, float y1, float x2, float y2) {
return (float) Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
}

private float getRadians(float delta_x, float delta_y) {
float r = (float) Math.atan2(delta_y, delta_x);
if (delta_y < 0) {
r += (2 * Math.PI);
}
return r;

}

return (float) Math.floor(radians / (Math.PI / 180));
}


}

I've created this class (based on someone's solution on actionscript). However, this implementation has very annoying bug. If the character rotates clockwise, he will instantly rotate counter-clockwise by ~360. I need help in solving this problem.

This instant rotation happens after one full rotation (rotation direction doesn't matter).

I suggest moving the target slowly rather than the angle. Try this:

Vector2 Target;

// Interp is a value between 0 and 1. When 0, the target never moves.
// When 1, the target moves instantaneously. Intermediate values cause the target
// to move at different rates.
void UpdateTarget(float interp)
{
Target = interp * Mouse.Position + (1 - interp) * Target;
}


The ship can then still turn instantaneously toward the target, but the target will smoothly change with respect to the mouse.

I think any linear function would be fine for this. You can keep two variables one for your spaceship's current angle spaceshipAngle = Math.PI*k, and one for the current angle that the user inputs with his cursor cursorAngle = Math.PI*p. And what you do is

if (Math.Abs(Math.PI*k, Math.PI*p) < Math.PI)
{
if (Math.PI*k < Math.PI*p)
k += 0.05f;
else
k -= 0.05f;
}
else
{
if (Math.PI*k < Math.PI*p)
{
spaceshipAngle += 2*Math.PI;
k -= 0.05f;
}
else
{
cursorAngle += 2*Math.PI;
k+= 0.05f;
}
}


here the "function" is k = k + 0.05 / k = k - 0.05

Note: If your spaceship looks to the top, it has Math.PI/2 angle, if it looks to the bottom it has Math.PI*3/2 angle, this is how you need to calculate angles for this code to work properly. I have not tested this out so you might see some interesting bugs (for example i don't think this will ever stabilize to an angle even if you don't move your cursor, so you need to fix that), but i think this is mathematically correct.