Trivial Physics Simulations ( Silverlight) - Part 2

If you know how vectors work, this isn't going to be interesting. If you've never seen one before, I'll try to keep it simple. Keep in mind that throughout this post I'm talking in 2 dimensions. The same stuff applies for 3D work; you'd just add another variable (the Z component) to the vectors.

A 2D vector stores two numbers which can be used to describe the position of an object (X, Y), or the velocity (X = the speed along the X axis, Y = the speed along the Y axis).

So take for example an object that's traveling at a speed of 10 pixels per second directly northeast:


The red line (marked "v") is the actual velocity (10 pixels per second), while the dotted blue lines indicate the speed along the x-axis (vx) and the y-axis (vy). Essentially, we've "decomposed" the one diagonal line into one horizontal and one vertical. For now, we're going to leave the details at that.

At the very least, here's what a Vector2D needs to know how to do:

  • Store the X/Y components
  • Add two Vectors to each other (eg; add acceleration to velocity)

So here's the code:

    1: public class Vector2D
    2: {
    3:     public double X { get; set; }
    4:     public double Y { get; set; }
    6:     public Vector2D(double x, double y)
    7:     {
    8:         X = x;
    9:         Y = y;
   10:     }
   12:     /// <summary>
   13:     /// Add two vectors and return the resultant vector
   14:     /// </summary>
   15:     public static Vector2D operator +(Vector2D v1, Vector2D v2)
   16:     {
   17:         return new Vector2D(v1.X + v2.X, v1.Y + v2.Y);
   18:     }
   20: }

At this point, we can do stuff like this:

    1: Vector2D acceleration = new Vector2D(0, 10);
    2: Vector2D velocity = new Vector2D(50, -50);
    3: velocity += acceleration;

That's probably sufficient to write the engine, but there are a few other features we'll want which will make the eventual code cleaner. Specifically:

  • Scale the vector by a fixed amount.
  • Generate a vector given an angle and a speed.

Why do we want that second one? Well, let's say you want to write code to generate the vector in the hand-drawn scribble above. What values do you give for vx and vy in order to generate the speed of 10 pixels per second in the northeast direction? You'd actually need to calculate them using some trigonometry, and that's some ugly code to have to read at a high level; so we bury it in the Vector class.

Eventually, we want to be able to do this:

    1: // Init from a speed (10 pixels per second) and an angle (45 degrees)
    2: Vector2D velocity = Vector2D.FromSpeedAndAngle( 10, 45 );

And here are the methods we want to add to the above class:

    1: /// <summary>
    2: /// Scale the vector by the given amount (ie; multiply by a scalar)
    3: /// </summary>
    4: public static Vector2D operator *(Vector2D v1, double scale)
    5: {
    6:     return new Vector2D(v1.X * scale, v1.Y * scale);
    7: }
    9: /// <summary>
   10: /// Convert the given angle (in degrees) to a vector with origin
   11: /// (0,0) and length == speed, breaking down into the X/Y components.
   12: /// </summary>
   13: public static Vector2D FromSpeedAndAngle(double speed, double degrees)
   14: {
   15:     double radians = Vector2D.DegreesToRadians(degrees);
   16:     return new Vector2D(Math.Cos(radians), -Math.Sin(radians)) * speed;
   17: }
   19: protected static double DegreesToRadians(double angle)
   20: {
   21:     return angle * (Math.PI / 180);
   22: }

For now, we're done with the Vector2D class. As I promised, it's quite trivial. We might add a couple of helpers here and there if we need them, but they will be obvious.

The key thing to remember about Vector2D is that it inherently stores both the magnitude and direction of the motion. So not only will it tell us the direction something is going in, but how fast it's doing it. This allows us to use it interchangeably for velocity/acceleration/position, and have everything "Just Work".

Next up: The Particle class.