The three constructors are easy to understand. The GenerateParticle() function will be used when a new particle is created, whether it's a completely new particle, or when a particle dies and we wish to replace it with a new one. TheUpdate() will be used to update the particles in the system. Update() will need to decide if and when to create new particles. And last, Draw() will be used to display the particle system on a given Graphics object.

 

 

///<SUMMARY>

/// Generate a single particle in the system. 

/// This function is used when particles

/// are first created, and when they are regenerated

///</SUMMARY>

///<RETURNS>New particle</RETURNS>

protectedoverride Particle GenerateParticle()

{

// Generate random direction & speed for new particle

// In a fountain, particles move almost straight up

float rndX = 0.5f * ((float)m_rand.NextDouble() - 0.4f);

float rndY = -1 - 1 * (float)m_rand.NextDouble();

float rndZ = 2 * ((float)m_rand.NextDouble() - 0.4f);

 

// Create new particle at system's starting position

Particle part = new Particle(m_Position,

// With generated direction and speed

new Vector(rndX, rndY, rndZ),

// And a random starting life

m_rand.Next(50));

 

// Return newly created particle

return part;

}

 

///<SUMMARY>

/// Update all the particles in the system

///</SUMMARY>

///<RETURNS>False - if there are no more particles in system

/// True - otherwise</RETURNS>

publicoverridebool Update()

{

Particle part; 

// Get number of particles in the system

int count = m_Particles.Count;

 

// For each particle

for (int i=0; i < count; i++)

{

// Get particle from list

part = (Particle)m_Particles[i];

// Update particle and check age

if ((!part.Update()) || (part.Life > 150))

{

// Remove old particles

m_Particles.RemoveAt(i);

// Update counter and index

i--;

count = m_Particles.Count;

}

}

// If there aren't enough particles

if(m_Particles.Count < DEFAULT_NUM_PARTICLES)

// Add another particles

m_Particles.Add(GenerateParticle());

 

// Always return true, since system is regenerating

returntrue;

}

}

}

2 basic particle systems

Now that we've seen the basic interface that we need to implement, we need to start implementing particle systems. Two of the more basic systems are an explosion and a fountain. I'll demonstrate them here.

Explosion

In an explosion, particles just fly everywhere. This is quite easy to implement - we just set all the particles to start at the center of the system, and move to a random direction, with a random speed. Gravity will take care of everything else.

spacer.gif Collapse | Copy Code

using System;

 

namespace Particles

{

///<SUMMARY>

/// Summary description for Explosion.

///</SUMMARY>

publicclass PSExplosion : ParticlesSystem

{

 

privatestaticreadonlyint DEFAULT_NUM_PARTICLES = 150;

 

// Random numbers generator

private Random m_rand = new Random();

 

///<SUMMARY>

/// Default constructor

///</SUMMARY>

public PSExplosion() : this(Vector.Zero, Color.Black)

{ }

 

///<SUMMARY>

/// Constructor

///</SUMMARY>

///<PARAMname="pos">Starting position of system</PARAM>

public PSExplosion(Vector pos) : this(pos, Color.Black)

{ }

 

///<SUMMARY>

/// Constructor

///</SUMMARY>

///<PARAMname="pos">Starting position of system</PARAM>

///<PARAMname="col">Color of the particles in the system</PARAM>

public PSExplosion(Vector pos, Color col)

{

// Set system's position at given position

m_Position = pos;

// Set system color to given color

m_Color = col;

// Create all the particles in the system

for (int i = 0; i < DEFAULT_NUM_PARTICLES; i++)

{

// Create particle, and add it to the list of particles

m_Particles.Add(GenerateParticle());

}

}

 

 

///<SUMMARY>

/// Update all the particles in the system

///</SUMMARY>

///<RETURNS>False - if there are no more particles in system

/// True - otherwise</RETURNS>

publicoverridebool Update()

{

Particle part;

// Get number of particles in the system

int count = m_Particles.Count;

 

// For each particle

for (int i=0; i < count; i++)

{

// Get particle from list

part = (Particle)m_Particles[i];

// Update particle and check age

if ((!part.Update()) || (part.Life > 150))

{

// Remove old particles

m_Particles.RemoveAt(i);

// Update counter and index

i--;

count = m_Particles.Count;

}

}

// If there are no more particles in the system

if (m_Particles.Count <= 0)

returnfalse;

returntrue;

}

 

///<SUMMARY>

/// Generate a single particle in the system.

/// This function is used when particles

/// are first created, and when they are regenerated

///</SUMMARY>

///<RETURNS>New particle</RETURNS>

protectedoverride Particle GenerateParticle()

{

// Generate random direction & speed for new particle

float rndX = 2 * ((float)m_rand.NextDouble() - 0.5f);

float rndY = 2 * ((float)m_rand.NextDouble() - 0.5f);

float rndZ = 2 * ((float)m_rand.NextDouble() - 0.5f);

 

// Create new particle at system's starting position

Particle part = new Particle(m_Position,

// With generated direction and speed

new Vector(rndX, rndY, rndZ),

// And a random starting life

m_rand.Next(50));

 

// Return newly created particle

return part;

}

}

}

In this example, we've created all the particles when the system was created. We've placed them all at exactly the starting point of the system, although for a more realistic look, we might have added a little bit of randomness there too. Each new particle is given a random age - this way the particles don’t die all at the same time. We've also decided to kill particles that are older than 150. We could have chosen another criteria, such as to kill particles only when they leave the display view, or they bumped into something.

Fountain

The fountain example is given here due to two reasons. First, the fountain regenerates particles that die, in order to continue "fountaining" or whatever else fountains do. Secondly, not all the particles are created at once - we first create a few particles, and as time goes on, we add more and more particles to the system.

spacer.gif Collapse | Copy Code

using System;

 

namespace Particles

{

///<SUMMARY>

/// Summary description for Firework.

///</SUMMARY>

publicclass PSFountain : ParticlesSystem

{

privatestaticreadonlyint DEFAULT_NUM_PARTICLES = 250;

 

// Random numbers generator

private Random m_rand = new Random();

 

///<SUMMARY>

/// Default constructor

///</SUMMARY>

public PSFountain() : this(Vector.Zero, Color.Black)

{ }

 

///<SUMMARY>

/// Constructor

///</SUMMARY>

///<PARAMname="pos">Starting position of system</PARAM>

public PSFountain(Vector pos) : this(pos, Color.Black)

{ }

 

///<SUMMARY>

/// Constructor

///</SUMMARY>

///<PARAMname="pos">Starting position of system</PARAM>

///<PARAMname="col">Color of the particles in the system</PARAM>

public PSFountain(Vector pos, Color col)

{

// Mark that this system regenerates particles

m_Regenerate = true;

// Set system's position at given position

m_Position = pos;

// Set system color to given color

m_Color = col;

// Create ONLY 5 particles

for (int i = 0; i < 5; i++)

{

// Create particle, and add it to the list of particles

m_Particles.Add(GenerateParticle());

}

}