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!
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.
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.
1: using System;
2:
3: namespace MathHelper
4: {
5: public class Vector2
6: {
7: private float _x;
8: private float _y;
9:
10: /// <summary>
11: /// Gets or sets the X component of the vector
12: /// </summary>
13: public float X
14: {
15: get
16: {
17: return _x;
18: }
19: set
20: {
21: _x = value;
22: }
23: }
24:
25: /// <summary>
26: /// Gets or sets the Y component of the vector
27: /// </summary>
28: public float Y
29: {
30: get
31: {
32: return _y;
33: }
34: set
35: {
36: _y = value;
37: }
38: }
39:
40: /// <summary>
41: /// Gets the length of the vector
42: /// </summary>
43: public float Length
44: {
45: get
46: {
47: return (float)Math.Sqrt(_x * _x + _y * _y);
48: }
49: }
50:
51: /// <summary>
52: /// Gets a Vector2 object containing X=1, Y=0
53: /// </summary>
54: public static Vector2 UnitX
55: {
56: get
57: {
58: return new Vector2(1.0f, 0.0f);
59: }
60: }
61:
62: /// <summary>
63: /// Gets a Vector2 object containing X=0, Y=1
64: /// </summary>
65: public static Vector2 UnitY
66: {
67: get
68: {
69: return new Vector2(0.0f, 1.0f);
70: }
71: }
72:
73: public Vector2()
74: {
75: _x = 0;
76: _y = 0;
77: }
78:
79: public Vector2(float x, float y)
80: {
81: _x = x;
82: _y = y;
83: }
84:
85: /// <summary>
86: /// Reflects a vector based on incidence with another vector
87: /// </summary>
88: /// <param name="unitVector">The unit vector to reflect on</param>
89: /// <returns>The new reflected Vector2 object</returns>
90: public Vector2 Reflect(Vector2 unitVector)
91: {
92: float dotProduct = this.Dot(unitVector);
93: Vector2 reflection = unitVector.Multiply(2 * dotProduct).Subtract(this);
94: return reflection;
95: }
96:
97: /// <summary>
98: /// Subtracts one vector from another
99: /// </summary>
100: /// <param name="vector">The vector to subtract from this one</param>
101: /// <returns>The resultant vector</returns>
102: public Vector2 Subtract(Vector2 vector)
103: {
104: Vector2 result = new Vector2();
105: result.X = this.X - vector.X;
106: result.Y = this.Y - vector.Y;
107: return result;
108: }
109:
110: /// <summary>
111: /// Adds one vector to another
112: /// </summary>
113: /// <param name="vector">The vector to add to this one</param>
114: /// <returns>The resultant vector</returns>
115: public Vector2 Add(Vector2 vector)
116: {
117: Vector2 result = new Vector2();
118: result.X = this.X + vector.X;
119: result.Y = this.Y + vector.Y;
120: return result;
121: }
122:
123: /// <summary>
124: /// Multiplies the vector by a scalar value
125: /// </summary>
126: /// <param name="scaleFactor">The magnitude of the new vector</param>
127: /// <returns>The resultant vector</returns>
128: public Vector2 Multiply(float scaleFactor)
129: {
130: Vector2 result = new Vector2();
131: result.X = this.X * scaleFactor;
132: result.Y = this.Y * scaleFactor;
133: return result;
134: }
135:
136: /// <summary>
137: /// Gets the dot product (a scalar value) between this vector and another
138: /// </summary>
139: /// <param name="vector">The vector to dot with this one</param>
140: /// <returns>The scalar dot product</returns>
141: public float Dot(Vector2 vector)
142: {
143: float result = 0.0f;
144: result = this.X * vector.X + this.Y * vector.Y;
145: return result;
146: }
147: }
148: }
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!