# How to make sprite move in any direction?

I have an arrow sprite that rotates based on where my cursor is pointed, I can only make it move up,down,left and right.How about in a diagonal way?

//this is the rotation
nt x=Gdx.input.getX();
int y=Gdx.graphics.getHeight()-Gdx.input.getY();

double radians= Math.atan2(y - arrowSpr.getY(), x - arrowSpr.getX());
arrowSpr.setRotation(angle);

//then the movement
arrowSpr.translateX(speed.x);
arrowSpr.translateY(speed.y);

• Use vector to increase vertical and horizontal side together to get diagonal movement Jul 30 '15 at 8:26

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:

The readme shows how to make it work.

• So where is exactly the code that implements the movement of the arrow sprite?Can you give me an example please,I'm new to everything on this. Jul 30 '15 at 6:10
• @StormAsdg I show you exactly how you can use vectors to rotate and move stuff. If you have the origin of the arrow and the mouse position it are exactly 2 lines of code to find the angle and create the velocity vector to add to your arrow. Besides that if you do not supply me with all details I cannot possibly give you ready to use code. Jul 30 '15 at 6:22
• I have the angle,the problem is how I'm gonna make it move toward that angle. Jul 30 '15 at 6:31
• I'm telling you to do it my way, It makes your life easier if you understand angles. If you do not want to do that then rotate the origin Vector of your arrow by your angle and you have your un-normalized direction. Normalize that and scale it by X speed to create a velocity vector. Add this velocity to your sprite. I will create a very basic example a bit later if I have some time to spare. Jul 30 '15 at 6:45
• I do hope you learn something from my code example and not just use it to get to your goal. Basic vector math is really not that hard and you are going to use it very often in game programming. I updated my answer. Jul 30 '15 at 8:16

I can't help you exactly with code because I'm not sure where all your variables are coming from. If you provide some context to this code, I can help more specifically.

In the meantime, take a look at this picture:

If you know how far you want the sprite to travel, and you know the angle. You can calculate the x and y distances using the formulas from the picture.

Hope this helps!