Vectors are a mathematical construct to represent direction and length (magnitude is the actual term). They are absolutely important for doing any kind of mathematical movement, so don’t be surprised to find them in every aspect of physics. I’ve read many articles about vectors which largely did more to confuse me with esoteric language and convoluted examples than teach me about this very simple and incredibly powerful mathematical tool. So this is my motivation for writing this article. If I’m successful, by the time you finish reading this, you too will find this topic simple. I’ll also be dropping little bits of other topics along the way to show where you can go from here. I always hated vacuum learning. If you find this distracting, skip any paragraph starting with “Side note:”.
So a vector is represented by 2 numbers (x,y) in 2D space and 3 (x,y,z) in 3D space. We’re just going to deal with 2D for now. It’s magnitude is the distance from (0,0) to the vector’s values. It’s pretty sneaky getting the all-important length (magnitude) in there implicitly. So if your vector is (1,1), your magnitude is 1.4142135623730951 If you want to verify this either use Pythagorean’s Theorem:
A2 + B2 = C2
12 + 12 = 22 = √2 = 1.4142135623730951
in code:
var point:Point = new Point(1, 1); var length:Number = Math.sqrt(Math.pow(point.x, 2) + Math.pow(point.y, 2));
or create a Point and look at its length property.
Side note: The number 1.4142135623730951 (often rounded to 1.4) is a pretty important number for any grid based movement. Since it is about 40% longer to move diagonally than horizontally or vertically. I could also go off on a tangent about the square root of 2, but I’ll just let you Google that one.
So this is all very exciting and all, but what do we do with vectors. One very easy way to think about vectors in the context of animation is “the amount to move an object each frame”. An example, if I wanted to move a Sprite (let’s just call it _ball) from left to right across the screen at a rate of 5 pixels per frame, my vector would look like this:
var point:Point = new Point(5, 0);
If I wanted to move _ball from right to left, my vector would look like this:
var point:Point = new Point(-5, 0);
Within my code called each frame, applying the vector to our _ball would look a lot like this:
_ball.x += point.x; _ball.y += point.y;
Now that’s a pretty simple concept. You may just think “oh, I’m just storing my movement increments in a point instead of separate variables or hard coding them in”. And my answer would be “kinda”. For the next 30 seconds, sure, but be prepared to replace that understanding with a more complete one here very shortly.
What we’ve been talking about would be called Velocity in physics terms. So from now on let’s just call the movement vector we use to increment our _ball’s position, our velocity vector.
So now let’s talk about vector addition. Vector addition really is as simple as point1.x + point2.x and point1.y + point2.y. The classic visual example of vector addition is placing the vectors nose to tail. Drawing a new vector from the tail of your first vector to the nose of your last vector is your resulting vector from the addition. Since I tend to think more in application of math than in the theory, this explanation for me wasn’t enough to really communicate how it works. So I’m showing you both, starting with application.
So if you have a vector to apply to _ball’s velocity, let’s just say it’s gravity, it would look a lot like this:
var _gravity:Point = new Point(0, 5); //increment the velocity vector by the gravity vector _velocity.x += _gravity.x; _velocity.y += _gravity.y; //apply new velocity vector to our _ball's position to move it _ball.x += _velocity.x; _ball.y += _velocity.y;
We want to change the _velocity vector each frame, instead of just adding both together and incrementing _ball’s position. The reason for this is we want the movement of _ball to be based on the change from the last frame. This will give us an arching path.
Should we do something like this:
_ball.x = _velocity.x + _gravity.x; _ball.y = _velocity.y + _gravity.y;
We’d end up in a constant diagonal line with no change in speed or direction, which is called a constant velocity. So we might as well do this:
var _velocity:Point = new Point(5,5); _ball.x = _velocity.x; _ball.y = _velocity.y;
The y value of 5 in the gravity vector is arbitrary. The gravitational constant on Earth’s surface is 9.8 meters per second squared (9.8 m/s2) and by convention negative y is down (in Flash coordinate system positive y is down) so the velocity vector for gravity is -9.8 m/s. Since when animating we deal with pixels, not meters, the actual gravitational constant is, somewhat, useless to us, so we pick a value that gives us the visual result we’re looking for. Hence an arbitrary value for y.
Side note: The difference between 2 values is often called delta and represented by the Greek letter Δ or lower case d. d is used when the difference is very very small, Δ when the difference is larger. In physics “difference” is referred to as “change” since we are dealing with what is happening to an object’s properties in relation to time. So the distance an object moved between 1 second and 2 seconds would be the Δ of its movement. The movement Δ between any 2 points in time is also the definition of velocity, but we are starting to get into calculus and differential equations. I’ll save that for another time.
This is the classic explanation of vector addition. If we add the blue vector (3,3) to the red vector (2,0) we end up with the green vector of (5,3).
Since subtraction is the same as adding by a negative number, vector subtraction pretty much works the same way. In your code, if you want to do subtraction, it is FAR easier to just use a negative value in your vector and then add it than to write some convoluted case code to figure out which one you need to do. Also, those of us used to working with vectors know exactly what (0, -5) means.
So here’s 2 new terms, Normal and Normalize. Contrary to logic, they have nothing to do with each other.
Let’s start with Normalize since it’s the easier concept. If you normalize a vector, you change its x and y so the resulting magnitude is 1. The direction of the vector doesn’t change, but it’s magnitude has. Flash’s Point class has a built in method for normalizing a vector. It also goes a step further to allow you to specify a length, so you’re not confined to a vector length of 1. It looks something like this:
var point:Point = new Point(5, 5); point.normalize(1); trace(point.x, point.y); //0.7071067811865475 0.7071067811865475
A vector with a length of 1 is also called a “unit vector” and is a very important thing.
So let’s look at an example where we’d use a normalized vector. Say we have a dot that really wants to move towards another dot. _dot1, our moving dot, can only move 3 pixels per frame. So how do we know how what to set _dot1’s velocity vector to? It’s not (3, 3) since that has a magnitude of 4.242640687119285. So let’s make a vector that will move _dot1 to _dot2 in one frame. This is very easily done by this very exciting math:
(_dot2.x – _dot1.x, _dot2.y – dot1.y)
Code:
var velocity:Point = new Point(_dot2.x – dot1.x, _dot2.y – dot1.y);
As I said, very exciting. Again, this is just the difference between these 2 points. If we added this vector to _dot1’s position, it would be at _dot2. So to change this vector to our ideal vector with a length of 3, the code would look a lot like this.
velocity.normalize(3);
Now we can just add our velocity to _dot1’s position every frame and it’ll move at its max speed until it gets to, and passes _dot2. If you want _dot1 to stop at _dot2 you’ll need a tiny bit more code just to check, but I’ll trust you can do that.
A more mathematically accurate and diverse way to do what we just did would be to normalize our velocity to a unit vector and multiply it by our max speed when we apply the vector to our object. It would look something like this in code.
var velocity:Point = new Point(_dot2.x – dot1.x, _dot2.y – dot1.y); velocity.normalize(1); _dot1.x += velocity.x * 3; _dot1.y += velocity.y * 3;
This would allow us to do something like have _dot1 slow down as it walked through some mud on his way to _dot2 simply by reducing the amount we multiply our velocity by while _dot1 is in the mud. I’m not going to get deep in this as it’s starting to enter game design. Now on to something else.
The Normal of a vector is another concept that I had a hard time finding an easy explanation for, again due to esoteric language and convoluted examples. In a nut shell it is a vector that is perfectly perpendicular to your original vector. So each vector has 2 possible normals. If you take the angle of your original vector and rotate it +/- 90 degrees (+/- Pi/2) you’ll have a normal.
Side note: Vectors aren’t the only thing that has normals. 3D planes have normals as well that become amazingly useful.
So what can we do with the normal of a vector? Lots of things, but the one I’m going to use as an example will allow us to do something fun that I’ve seen a lot of people ask in forums. “How do I get something to bounce off a wall?” This is actually a LOT easier than you might think. The new velocity for an object bouncing off a perfectly horizontal or vertical wall is exactly the normal of its current velocity. Now that is really really convenient. So to find a vector’s normal, we could use Trig and end up with math like this: (let’s go back to _ball)
var currentAngle:Number = Math.atan2(_velocity.y , _velocity.x); //yes Y comes first var rotatedAngle:Number = currentAngle + Math.PI / 2; //or currentAngle – Math.PI / 2 _velocity.x = _velocity.length * Math.cos(rotatedAngle); _velocity.y = _velocity.length * Math.sin(rotatedAngle);
OR!!! As it turns out, flipping the sign on either x or y will give us the same answer.
_velocity.x *= -1;
Or
_velocity.y *= -1;
So much easier that memorizing Trig equations. Deciding which normal of your velocity vector, assuming we’re bouncing around inside a box, is pretty easy as well. If we are moving up and we want to start moving down after our bounce, we flip our Y. Same if we’re moving down and want to move up, just flip our Y. If we’re moving left and want to bounce to the right, we flip our X. Same with right to left. So say we have a box at (0, 0) that is 300 x 300, our code would look like this.
_ball.x += _velocity.x;
_ball.y += _velocity.y;
If (_ball.x < 0 || _ball.x > 300)
{
_velocity.x *= -1;
}
If (_ball.y < 0 || _ball.y > 300)
{
_velocity.y *= -1;
}
There are a couple bugs in here if you use this as is in a real application, so this is only an example. The bugs are, you should do your collision detection before applying your velocity to your position and I’m not taking the radius of the ball into account, so visually the ball could pass through your wall. This is a vector article after all, not game development.
For now, that is it. I hope this has helped.
~Chris
More Reading:
http://en.wikipedia.org/wiki/Euclidean_vector
http://en.wikipedia.org/wiki/Unit_vector
Video:
http://www.khanacademy.org/video/unit-vectors-and-engineering-notation?playlist=Physics
