Who Wants Some Math?
One of the most simple principles in 2D games is an object that bounces around in a container.
This little set of math knowledge is really important for any game that has some basic physics in it, for example, Pong.
An easy way to reflect a vector about a certain axis is just to negate a component of the vector, for example, x = (-1)x. But what if you had a game like Pong where you could rotate the paddles?
In this case, the math becomes a little harder. In XNA, you have a great mini-physics library available with data types like Vector2 and methods like Reflect that do all the work for you. There are physics engines out there for Silverlight that will do this for you, but it’s helpful to know what you’re doing in the first place. Come with me for a little trig lesson!
Basic Trig & Vectors
Disclaimer: Some of this may not be 100% textbook correct. I minored in math in college and this took a lot of digging!
Vectors. A vector, in two dimensions, has an X component, a Y component, and a magnitude or length. Any vector with a magnitude of 1 is a unit vector. <1, 0> is the X unit vector and <0, 1> is the Y unit vector. Normalizing is the act of creating a unit vector from any other vector.
You can use vectors to represent the general direction or heading of an object. An object that is traveling along the X axis might have a direction vector of <1, 0>.
Vectors have different operations commonly associated with them.
- Addition. Adding two vectors generates a resultant vector. If A = <1,0> and B = <0, 1>, then A + B = <1, 1>.
- Normalization. A normalized vector is any vector with the length 1. To find the normal vector of any given vector, divide both components of the vector by the vector’s length.
- Multiplication. Multiplying a vector by a scalar factor will increase the magnitude of the vector. An easy way to do this is to multiply both components by the scalar factor. If you were to multiply <1, 0> by a factor of 3, you would have <3, 0>.
- Dot product. The dot product of a vector is different than multiplication in that you are multiplying two vectors together. If you had a vector A<1, 2> and a vector B<2, 4>, the dot product A·B would be equal to <Ax*Bx, Ay*By> or <2, 8>.
- Reflection. As mentioned above, if you are reflecting on a surface that can be represented by a unit vector (basically an axis), then you could accomplish reflection just by negating one of the components. But what if you are reflecting off of some weirdly rotated platform, or the vector <2, 3>, or a line at a 45 degree angle?
In either case, you can use the formula below to accomplish reflection:
Let R be the vector result of the reflection
Let N be the normal vector of the vector you are bouncing off of
Let V be the vector that represents the incoming object’s direction
R = 2 * (V · N) – V
So if V is <1, 2> and you are bouncing off the Y axis (the normal unit vector is <0, 1>) then V·N would be <1, 2> · <0, 1> = <0, 2>
Multiplying this by 2 would yield <0, 4>
Subtracting the original vector V would yield <0, 4> – <1, 2> = <-1, 2>
See the difference? Before: <1, 2>. After: <-1, 2>. The X component is negative which means that the object will bounce off of a left, or right, wall.
The nice part is that this formula works if you are bouncing off of some non-planar vector, such as <2, 1>.
Let V be <1, 2> and let our bouncy vector be <2, 1>. The length of <2, 1> can be calculated like the hypotenuse of a triangle: Sqrt(2*2 + 1*1) = Sqrt(4 + 1) = Sqrt(5) = 2.236.
The normal vector N would be <2, 1> / 2.236 = <0.894, 0.447>. If you again take the length of this resulting normal vector, you’d get 0.999 or 1, which means our work is accurate.
The dot product of V and N, V·N yields <0.894, 0.894>
Multiplying this by 2 would yield <1.788, 1.788>
Subtracting the original vector V would yield <.788, -.212> for the reflection vector. See how that works? Well, probably not; those numbers don’t mean anything, so here’s a bad scan of some graph paper.
Notice the original direction vector, V, indicates a heading of up and to the right. Vector B, the one we are bouncing off of, is also up and to the right but at a lesser degree (also note this vector is translated somewhere in space). The box you see is the right angle between V and R, the reflection of V. Notice that this makes perfect sense, because our vector R indicates the direction "to the right and down a little" ( <.788, -.212> ).
Applications in Silverlight
In Silverlight, there are no useful physics / trig / math stuff built in aside from what’s included in the compact framework. I had to roll my own MathHelper class and include it in my project to do a lot of these operations. This is the Math Helper you see being used in the Silverlight applications at the top of the post.
Applications in XNA
XNA is the best! All this stuff is already built in in XNA so you don’t need to mess with the above math at all! Just use Vector2.Reflect, Vector2.Dot, and other lovely methods that are at your disposal. Makes Pong Easier.
This is some of the most basic stuff you need to know to understand what exactly is going on behind all of that bouncing. Hopefully it was moderately easy to understand!