4
\$\begingroup\$

After reading This SO post on Vectors, I'm still pretty confused on how to use vectors to move my entities at any angle. The SO post assumes only 90 degree angles:

if up pressed:
    direction = direction + Vector(0, -1)
if down pressed:
    direction = direction + Vector(0, 1)
if left pressed:
    direction = direction + Vector(-1, 0)
if right pressed:
    direction = direction + Vector(1, 0)

Once I have the vector length (are "length", "speed" and "magnitude" all the same thing?), and vector direction (angle), how do I actually move the entity towards the player target at the specified angle and speed?

So, for example:

Point a (Player x, y): is at (2, 3) 
Point b (Target x, y): is at (6, 8) 

Vector between a and b is:

x2 - x1 =  6-2 = 4 
y2 - y1 =  8-3 = 5 

Vector x,y = (4, 5)

Vector length = sqrt (x^2 + y^2) = 6.4 "units"

Vector direction = atan(5/4) = 51 degrees down and to the left

enter image description here

So I know the speed/length/magnitude is 6.4 "units", and the angle is 51 degrees, but now how do I apply this data to make point B actually move towards point A at that angle and correct speed?

\$\endgroup\$
  • \$\begingroup\$ There are different vectors for different things and I think your question would be clearer if you separated them out. You have calculated (4,5), that's the vector from the player to the enemy. Other vectors are the vector you want the enemy to move along, and the velocity vector you might choose for the enemy that closes the distance, and the player's estimated movement as a vector. You might want the enemy to have a limited velocity vector derived from max_speed * -norm(V) \$\endgroup\$ – cardiff space man Nov 23 '15 at 3:38
  • \$\begingroup\$ Q: (are "length", "speed" and "magnitude" all the same thing?) A: They are if the vector is a velocity vector. If the vector is just the difference of two locations then it is not a velocity vector and the magnitude is not the speed, it's the distance. If you think of the length abstractly it could be equated to the speed. \$\endgroup\$ – cardiff space man Nov 23 '15 at 3:41
  • \$\begingroup\$ Instead of atan(y/x) I always suggest atan2(y, x) because the algorithm of atan2 can cope with the situation of x much smaller than y, while the same situation would force atan to cope with a very large y/x result. \$\endgroup\$ – cardiff space man Nov 23 '15 at 3:43
  • \$\begingroup\$ To confuse you more, technically the (only) correct name for vector length/magnitude in this case is euclidean norm. The length and magnitude is interchangeable in this context if you always understand it as euclidean norm. \$\endgroup\$ – wondra Nov 23 '15 at 8:10
3
\$\begingroup\$

1) First of all, let me roughly clarify a few concepts. You said:

Once I have the vector length (are "length", "speed" and "magnitude" all the same thing?), and vector direction (angle), how do I actually move the entity towards the player target at the specified angle and speed?

Yes, length and magnitude of a vector can be both terms used with the same meaning. However, technically, a vector is not an angle: it forms angles in relation to something else. In your example image, the line segment going from point B to point A forms an angle of around 51 degrees in relation to the X axis.

A vector is given by a point in space (in your case, 2D space). When we think of or use a vector as a direction, it means that it represents the direction going from the origin (0,0) to that given point in space. Not a specific angle. So, in your example, the vector (4,5) that you calculated is the direction from point B to point A. And actually, as you will se, that is all we need.

In what regards speed, that's a totally different thing. By you mixing that together with length and magnitude, it is apparent that you are confounding speed and velocity, which are two different concepts. Speed is just a scalar number that represents the amount of distance walked in a given time, i.e. length divided by elapsed time. Velocity is a vector given by the direction of the movement divided by elapsed time. Hence, the current speed of a movement is the length of the velocity of that movement. For more details, see: http://www.physicsclassroom.com/class/1DKin/Lesson-1/Speed-and-Velocity.

2) That said, the way I find to be the simplest to move an object using vector math is the following. You need 4 pieces: direction, length, speed and frame delta.Time.

In detail: you have to calculate the vector direction (not the angle) and normalize it, have to use the scalar speed that you desire, and have to apply a frame-to-frame delta time for consistency across different computers. You put all that in a loop that loops while the distance between moving char and destination point (in your case, point A) is lower than the total distance between points A and B. And voilá!

Let's do it. If the movement goes from point B to point A, then the vector direction of the movement is equal the location (position) of point A in the space minus the location (position) of the point B in space. I will use C# for the following examples, but you will get the idea:

Vector2 movement_direction = A.transform.position - B.transform.position;

Then, we normalize that vector. What does normalize mean? It only means that we take the vector "movement_direction" and force its length/magnitude to become equal 1. That's pretty simple to achieve: you just divide the vector by its length. See more here: http://www.fundza.com/vectors/normalize/. For that, we will need to get the direction lenght, just as you did:

float direction_length = Math.sqrt (Math.Pow(movement_direction.x,2) + Math.Pow(movement_direction.y,2) );

Then, let's normalize the direction of the movement:

Vector2 movement_direction_normalized = movement_direction  / direction_length;

Now, you just choose the speed you want for your movement and you retrieve from your game engine the so called frame delta.Time, which is the time elapsed between the last frame and the current frame of the main game loop.

The final formula for the movement becomes, at each frame of the main loop while the movement is still going on:

movingchar.transform.position = movingchar.transform.position + (movement_direction_normalized * speed * Time.deltaTime;

It means that, at each iteration of the loop while movement is in place, you take the current location of the moving char and sum to it the result of the multiplication between the normalized direction of the movement, the speed of the movement and the frame delta.Time.

Note that you should execute the formula (i.e. update the movement) in a loop that keeps working until the updated distance between the moving character is smaller than the initial distance, i.e. smaller than the distance between points B and A.

Also note that including delta.Time is crucial, because that is the way you guarantee that you movement will have the same speed no matter how fast is the computer running the game. Otherwise, the speed would vary because of the difference in how fast computers calculate each frame of your game.

\$\endgroup\$
  • \$\begingroup\$ Not sure if you know JavaScript, but here is my CodePen: codepen.io/dtturcotte/pen/jboQxa?editors=001. The code is initialized from init() on the bottom. The ball (red) is not moving towards the target (blue) \$\endgroup\$ – Growler Nov 26 '15 at 4:25
  • \$\begingroup\$ @Growler JavaScript is very similar to C#, so that's fine. Which part went wrong when you tried with the stuff I said above? You should narrow me down to the part of the code that does not work. Besides, every time I reload the page, the red ball moves towards the blue, just very very fast, until it reaches blue. \$\endgroup\$ – MAnd Nov 26 '15 at 8:02
1
\$\begingroup\$

Once you have the vector (V in your diagram), you can simply normalize it (that is, make its length 1.0), then multiply it by the speed you want and add it to point B.

To normalize the vector divide the components by the length. In this case, that would mean the normal vector is (4/6.4, 5/6.4) = (0.625, 0.78125).

It's not clear to me what you're trying to accomplish, so I don't know how best to tell you to calculate the speed. If you set it to 6.4, then the target will be in the player's position on the next frame. (But the player may have moved by then.)

Once you know the speed you want, you can move B by doing the following:

b.x += speed * v.x;
b.y += speed * v.y;

That assumes you put the normalized vector into v.

\$\endgroup\$
  • \$\begingroup\$ I have a pen here: codepen.io/dtturcotte/pen/jboQxa?editors=001. I'm trying to figure out how to do this in the context of DOM objects and pixels. The ball (red) is not moving towards the target though... And you can see in there I've commented out this.addVector in Point class because it doesn't make sense to me to add the vector and return it as a new vector... rather just update the Point's x,y directly... But I was told I should never manipulate the Point's location. \$\endgroup\$ – Growler Nov 25 '15 at 4:56
  • \$\begingroup\$ Unfortunately, I don't know a lot about DOM or Javascript. What you've written seems reasonable to me, and looks correct to me. I'm not sure why you're told not to update variables in a function in Javascript. I don't think it's a functional language where functions have to be pure, or anything like that. It's also not clear to me how animation happens in Javascript. Do you have a draw loop that gets called repeatedly? I see that init() gets called, but how is updated after that? \$\endgroup\$ – user1118321 Nov 25 '15 at 19:10
  • \$\begingroup\$ function tick() calls window.requestAnimationFrame(tick); which is the loop. tick() calls updatePosition(ball, normalized_vector); which is ball.addVector(normalized_vector.scaleUp(2));. How do I make the player stop moving once the vector distance has been reached? \$\endgroup\$ – Growler Nov 26 '15 at 4:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.