Trivial Physics Simulations (...in Silverlight) - Part 3

So now that we have vectors, we need to do something with them. We're going to use the concept of a Particle. This is supposed to represent a tiny object in our world that is affected by physics. For this reason, it has a position, velocity, acceleration, etc.

For starters, let's define the basic particle:

    1: public abstract class Particle
    2: {
    3:     protected TimeSpan _Age;  // How old is the particle right now?
    4:  
    5:     public Vector2D Position { get; set; }
    6:     public Vector2D Velocity { get; set; }
    7:     public Vector2D Acceleration { get; set; }
    8:     public TimeSpan MaxAge { get; set; }
    9:     public bool Alive { get { return (_Age < MaxAge); } }
   10:     public double Radius { get; set; }
   11:  
   12:     public Particle(Vector2D pos, Vector2D vel, Vector2D acc, TimeSpan maxage, double radius)
   13:     {
   14:         Position = pos;
   15:         Velocity = vel;
   16:         Acceleration = acc;
   17:         MaxAge = maxage;
   18:         Radius = radius;
   19:         _Age = TimeSpan.FromMilliseconds(0);
   20:     }
   21:  
   22:     /// <summary>
   23:     /// Iterate one frame of animation for this particle.
   24:     /// </summary>
   25:     /// <param name="timeSinceLastFrame">How much time has passed since the last frame?</param>
   26:     public void RunFrame( TimeSpan timeSinceLastFrame )
   27:     {
   28:         double secondsPassed = (timeSinceLastFrame.TotalMilliseconds / 1000.0);
   29:         Velocity += Acceleration * secondsPassed;
   30:         Position += Velocity * secondsPassed;
   31:         _Age += timeSinceLastFrame;
   32:     }
   33: }

A few things to note:

  • It's an abstract class. Depending on your use of it, it doesn't have to be. This is actually a ready-to-go particle; it just doesn't have anything in terms of visuals attached to it.
  • Note the concept of "Age" in there (lines 3, 8 and 9). A particle lives for a while, then dies. It doesn't have to - but for most particle based simulations, you do want that.
  • The "Radius" property is supposed to indicate the size of the particle. It could be argued that this belongs in a subclass.

The only real point of interest is the RunFrame method on line 26. This is the key to the whole physics simulation. Remember I said that it's down to two lines of code? Those are 29 & 30 - the rest is fluff. We call this method every frame, telling it how long since the last call, and it will move the given particle in the right direction by the right amount.

So now that we have this abstract particle, let's use it to make something a little more specific to our fireworks demo:

    1: public class FireworksParticle : Particle
    2: {
    3:     public object Custom { get; set; }
    4:     public Color GlowColor { get; set; }
    5:  
    6:     public FireworksParticle(Vector2D pos, Vector2D vel, Vector2D acc, TimeSpan maxage, double radius, Color color)
    7:         : base(pos, vel, acc, maxage, radius)
    8:     {
    9:         GlowColor = color;
   10:     }
   11:  
   12:     /// <summary>
   13:     /// Fade the opacity of a particle as it gets older
   14:     /// </summary>
   15:     public double Opacity
   16:     {
   17:         get
   18:         {
   19:             double pctOfLifetime = ((double)_Age.TotalMilliseconds) / ((double)MaxAge.TotalMilliseconds);
   20:             
   21:             if (pctOfLifetime > 1)  pctOfLifetime = 1;
   22:             if (pctOfLifetime < 0)  pctOfLifetime = 0;
   23:  
   24:             return pctOfLifetime;
   25:         }
   26:     }
   27: }

You'll see we're only adding two things, both tangential to the core of this topic, but we need a little bling: The particle's color and opacity - the latter being a function of its age; it dims as it grows older.

Oh, and the Custom property. I'll get to that later; it's totally an implementation detail and not necessarily a pretty one.

So, what are we missing at this point?

  1. We need a page to put all this on, with some UI controls for playing with variables.
  2. We need some way of rendering the particles to the page (there's no drawing code above - I prefer not to put it in these classes).
  3. We need to actually create particles with positions and velocities that will suggest some kind of fireworks.
  4. We need code to tie it all together; the rendering, the UI, the particle generation.

Here's a screenshot of what the end result will look like:

Capture 

(Yeah, no beauty contest winner - but it's effective :))

 

Next up: Putting it all together.

 

Avi