I personally never calculate an angle like that. I like to work with vectors, it might be slightly less efficient but this way you can do it step by step, it gets more readable and easier to understand.
So what is a vector? A vector is essentially a direction and a magnitude together. Often in games it is used as a position data structure too but essentially a Vector(10,10)
is vector pointing north east with a magnitude of 14.14
= √(10²+10²)
(Pythagoras).
So what can we do with a vector? We can calculate direction, velocities, angles and more in 2D or 3D space. LibGDX does most of the math for you. You just have to know a couple of basic Vector rules to get the result you are after.
So let's first start by rotating your arrow.
//We need the origin of your arrow we will be rotating around and calculate the direction with.
Vector2 arrowOrigin;
//We need to mouse position to rotate the arrow to.
Vector2 mousePosition;
We can create a rotated vector between the points by subtracting the origin from the target.
Vector2 direction = mousePosition.sub(arrowOrigin);
We now have the direction from arrowOrigin to mousePosition. If you want to know the angle of the arrow to point to your mouse all we need to do is:
float angle = direction.angle(); // Angle in degrees from -180 to 180
Now we can use the direction vector to move your arrow towards the mouse. But remember when I said a vector is a magnitude as well? Currently that angled vector stretches has the same length as the distance between the two other vectors we got direction from. So if we add direction
to arrowOrigin
it would be instantly be on top of the mouse pointer. We can deal with this by normalizing the direction and make the total magnitude of it 1
.
direction.nor();
We can still use this vector for our rotation since nothing has changed there. If we a origin of 0, 0
and a target of 10,10
the previous direction vector would have been 10, 10
. what we just did is shrank the length of it to 1 by maintaining it's rotation. If we do this to all our vector movement we have a equal starting magnitude of 1.
Now let's make a velocity vector. At this time I have to warn you about how LibGDX deal with vectors. A vector is passed by reference by default and it's methods will work on the method itself. So if you do velocity = direction.scl(100);
Then not only both velocity and direction have been scaled by 100, velocity is just a reference of direction. If there is something strange going on 99% of the time it's because of this. It gave me headaches when I started out with LibGDX. But luckely, we can just copy the vector.
float arrowSpeed = 10;
Vector2 velocity = direction.cpy(); //created a copy
velocity.scl(arrowSpeed); //scaled vector by the arrow speed
arrowOrigin.add(velocity); //Now move our arrow with the created velocity
I know it's a long wall of text and you didn't ask for it but as you can see. it are really just a couple of lines of very understandable code. Since Vectors in LibGDX make use of chaining methods you can even shorten all this.
// subtract normalize/scale
velocity = mousePosition.sub(arrowOrigin).nor().scl(arrowSpeed);
angle = velocity.angle();
Now if you actually start adding velocity to your arrow it is important to know when to stop. If you are inventive enough you can calculate it yourself with the information I gave you, it's fairly simple. But why bother, LibGDX took care of everything.
//Distance
float distanceToTarget = arrowOrigin.dst(mousePosition);
if (distanceToTarget <= speed)
{
//We have or almost arived on our destination.
//We might want to set out arrow to it's destination
}
I love to work with Vectors this way so whether you use this or not, I hope you learned something from it.
I have created a very basic program for you that does what you want. Get it from github:
https://github.com/madmenyo/FollowMouse
The readme shows how to make it work.