`joel_kleier.electric_froth = \`

2014-11-28

Developing hobby games I usually just stick to libraries that already handle things like *physics*. Basically I follow examples, copy/paste code, and plugin numbers. This is good for getting a hobby game *built* but not so good to learn the math and gain an intuition of what’s actually going on, which is what I want to do now.

*Vectors* are the basic building block of 2D game physics. They describe the distance and direction of game objects (from player characters to projectiles, even lighting). As such, I think they may be the *best* place to start this exploration and self-learning exercise.

This article was written as I attempt to learn the subject matter at hand, so there is a strong possibility of incorrect information based on my own ignorance.

Please, if you see an error of any kind, feel free to send me an email!

NOTE:

Check out the source code to this page, I used processing.js to generate all the visual examples, and I tried to pepper the source files with a bunch of comments.

Vectors represent two measurements – a magnitude and a direction. For example, “traveling at 2 kph (kilometers per hour) due east” is a vector! This data is descriptive, but not necessarily useful for computation in that format. To make the data more useful, it is typically encoded into two numerical values, `x`

and `y`

, representing a distance from the origin on the x and y axis.

NOTE: I am assuming the use of a 2-dimensiononal, Cartesian coordinate system, and kind of ignoring 3-dimensional stuff for now

Our “traveling at 2 kph due east” example then turns into something like `[2, 0]`

, which would look something like:

The important thing to remember is in order to think about a (2D) vector in concrete numbers, we can express it as a pair of these x and y values. IE (0, 1), (30.3, 2.2), etc. These 2 numbers represent a *distance* on the x and y axis, and not a point – this is important because it means vectors are encoded as the *legs* of a *right triangle*. Why is this important? I’ve found that it helps me to *visualize* vectors in a 2D space.

In terms of (Nim) code, this could be expressed as a 2 dimensional array, a tuple, or more explicitly, like:

```
type
Vector* = object
x*: float
y*: float
```

I like the more explicit approach in this case because I think it’ll make writing dependent code a little more clear, and I need as much clarity I can get.

The first really useful value to calculate based off of this vector encoding is the *magnitude*. This turns out to be pretty simple. Remember how the this vector encoding is basically showing us the lengths of the legs of a *right triangle*? Taking advantage of that, we can use Pythagoras Theorem, which boils down to this formula: *x ^{2} + y^{2} = h^{2}*.

The *magnitude*, then, is the *h* value, and since the formula is for *h ^{2}*, rearranging it to solve for

I think the results of both formulas will be useful later, so I’m going to make two procedures – one to calculate the magnitude squared (_h^{2}_) and the magnitude itself (just *h*), here’s the code:

```
# magSq == "magnitude squared" == h*h
proc magnitudeSq*(self: Vector): float =
result = self.x * self.x + self.y * self.y
# the actual magnitude value (h)
proc magnitude*(self: Vector): float =
result = sqrt(self.magSq)
```

NOTE: the `sqrt`

comes from the Nim standard library `math`

The definition of a vector is a *magnitude* AND *direction*, so how do we encode the direction in terms of `x`

and `y`

? Simple put, the *sign* of the `x`

and `y`

values indicates their direction. If the `x`

is *positive* then the vector is going an *easterly* direction (if we’re thinking of *direction* in terms of the cardinal directions) and a *positive* `y`

would be a *northernly* direction. A *negative* `x`

value will be in a *westerly* direction, and a *negative* `y`

value would be in a *southernly* direction.

In terms of code, there’s nothing extra needed since `Vector.x`

and `Vector.y`

are signed values.

First, why add and subtract vectors? The best answer is an example: presuming a characters movement is described by velocity (direction and speed, encoded as a vector) and acceleration (change in direction and speed, encoded as a vector), then it is only natural that when it comes time for a character to move within the simulation, their *acceleration* should be added to their *velocity*, and the result should be added to their current position. Being able to add *acceleration* and *velocity* (both vectors) becomes super important here.

Adding and subtracting vectors, conceptually, is like traveling along the the hypotenuse of one triangle, then traveling along the hypotenuse of a second triangle. From where the first vector began to where the second vector ends is the resulting vector. Confusing? Khan Academy has a pretty good video on adding vectors.

Here’s my attempt to visualize it:

The first vector:

The second vector:

Traveling along the first vector, then traveling along the second vector to get a third vector:

The resulting vector:

The math for this is straight forward: add the two `x`

values for the result `x`

value, add the two `y`

values for the result `y`

value. The same formula can be used for subtracting vectors as well, just subract the `x`

and `y`

values instead of adding them.

The resulting code might look like:

```
# just overload the `+` operator
proc `+`*(a, b: Vector): Vector =
result.x = a.x + b.x
result.y = a.y + b.y
# just overload the `-` operator
proc `-`*(a, b: Vector): Vector =
result.x = a.x - b.x
result.y = a.y - b.y
```

A *scalar* is just a single number, and *scaling* a vector by a *scalar* is the act of multiplying the *vector* by the *scalar*. Why is this useful? Let’s say there’s a scenario where a ball rolls along a floor… how fast does it slow down? This could be modeled by using a *scalar* value for friction, and shrinking the *velocity* (a vector) of the ball by that much every tick of the simulation.

The math for scaling a vector is as simple as multiplying the *scalar* by the `x`

and `y`

components of the vector. In terms of code, it might look something like:

```
# just overloaded the `*` operator
proc `*`*(a: Vector, b: float): Vector =
result.x = a.x * b;
result.y = a.y * b;
```

A *unit vector* is a vector who’s length/magnitude is exactly 1. A *normalized vector* is a vector who’s components have been divided by it’s magnitude in order to be in proportion with a unit vector. For example, the vector `[1, 2]`

has a magnitude of about `2.236`

. If this vector is *normalized*, it’s value would become `[1/2.236, 2/2.236]`

.

Why is this useful? The key is that a normalized vector is *proportional* to the original vector. This means the *normalized* vector carries direction with a proportional encoding for magnitude, thus enabling the *normalized* vector to be scaled to any size proportional to the original magnitude.

Again, why is this useful? I think it’s best illustrated with an example! Think of light reflecting off of several objects. Each object has a vector describing an amount of light that get’s reflected, as well as a direction of reflection. The intensity of light can be represented by a single scalar value, turning the problem into one of *scaling* each objects light vector.

If each object’s light vector is *normalized*, then they will have a consistent representation of reflected light based on the same *scale*. If each light vector were *not* *normalized*, then there would be a very inconsistent representation of light, each object behaving like it existed in it’s own little world.

Whew. I hope that helped. Here’s some code to implement normalization:

```
proc normalize*(self: Vector): Vector =
result.x = self.x/self.mag;
result.y = self.y/self.mag;
```

Seriously, Wolfire’s Linear Algebra for Game Developers, Part 2 has a great example of the *dot product* and why it’s useful. Not even going to try to make a better example and explanation, because I doubt I could at this point.

I’ll paraphrase though, the *dot product* is kind of a proportion of how much the vectors are pointing in the same direction. It’s also kind of useful in projection.

Suffice it to say, here’s some code for implementing the dot product:

```
proc dot*(A, B: Vector): float =
return A.x*B.x + A.y*B.y;
```

Notice that this code looks an aweful lot like the *magnitudeSq* method! Intuitively, then, the dot product of vector A against intself would be the *h ^{2}* value when solving for Pythagora’s Theorem… which means our magnitude code could be adjusted to look more like:

```
# just get the square-root of the dot product of the vector against itself
proc magnitude*(self: Vector): float =
result = sqrt(self.dot(self))
```

The act of *projecting* a vector onto another is, essentially, finding the vector between the *points* `a`

and `b`

in the following image:

Intuitively, if the vector being projected onto is a *normalized* vector, then really the problem becomes straight forward! First, find the *magnitude* of the vector resulting from a vector projected onto a *normalized* vector (turns out, this is the *dot product*). Then, scale the *normalized* vector (who’s legs are proportional to each other) by the *magnitude* to get the resulting vector encoded as `x`

and `y`

values.

Why is this useful? This is kinda hard for me to answer in what I feel is total understanding, as I don’t think I’ve actually *used* it enough to really grasp it use. The text book answer might be a few things:

- finding the proportion of how much of one vector lies in another’s direction (useful for determining if AI with a view arc can see a player, for example)
- tying into the first point, finding the angle between two vectors
- finding the local coordinates of a vector on an arbitrary axis other than the
`x`

and`y`

axis

That’s still a pretty meaty explaination. I guess it boils down to being able to see a vector in the context of another, and making assumptions based off the result.

I’m pretty sure that I will be using *projection* pretty heavily once I start getting into implementing the Separating Axis Theorem

Enough talk! Let’s see some code:

```
# this procedure handles a more generalized form of projection (IE when unit
# vectors aren't explicitly used
# A projected onto B
proc project*(A, B: Vector): Vector =
var magSq = B.dot(B);
var dot = A.dot(B) / magSq;
result.x = A.x * dot;
result.y = A.y * dot;
# B is an already normalized vector
# A projected onto B
proc projectN*(A, B: Vector): Vector =
var dot = A.dot(B);
result.x = A.x * dot;
result.y = A.x * dot;
```

I *think* I’ve gone through all of the absolute basics of vectors as they immediately relate to 2D game physics. The next step for me to take will be to (re)learn about linear transformations (for things like vector rotation, reflection, etc). I’m fairly certain there are shortcuts for these things, especially for 2D, but the goal is to develop an intuition about this stuff, so it’s important that I don’t just copy/paste code or take every formula at face value.

Next time will *probably* be a much shorter post, specifically covering my re-learning useful linear transformations for 2D vectors and hopefully dealing with a lot more code!