## Creating and Destroying Particles
To create individual particles, create a `b2ParticleDef`-struct object. Next,
specify the behavior and properties of the particle. Finally, call the method
to create the particle.
The following example creates an individual particle.
`b2ParticleDef pd;`
`pd.flags = b2_elasticParticle;`
`pd.color.Set(0, 0, 255, 255);`
`pd.position.Set(i, 0);`
`int tempIndex = m_particleSystem->CreateParticle(pd);`
Particle lists are self-compacting. Therefore, the index returned by
CreateParticle is only valid until a lower-indexed particle, or a group
referencing a lower-indexed particle, is deleted.
To destroy an individual particle, invoke the function
`void DestroyParticle(int32 index);`
The following example destroys the particle created above.
`m_particleSystem->DestroyParticle(tempIndex);`
### Particle lifetimes
In addition to manual destruction of particles as described above, particles
can also expire and be destroyed due to age.
The following example tells the system to track particle ages for the purpose
of destroying them.
`m_particleSystem->SetParticleDestructionByAge(true);`
A particle can die one of two "age-related" deaths. First, you can set a
lifetime for a particle--a period of time after which it expires. The following
example does this:
`m_particleSystem->SetParticleLifetime(`
`index, Random() *`
`(k_particleLifetimeMax - k_particleLifetimeMin) +`
`k_particleLifetimeMin);`
where `index` specifies the number of the particle whose lifetime is being
assigned, and the `Random()` function generates a random value for that
lifetime.
You do not need to set a specific lifetime for a particle for it to have an
age-related death. If you set a maximum number of particles that can exist in a
particle system, and you have have told the system to track particle ages, the
system clamps particle count by culling "excess" particles. Particle culling
takes place in age order, with the oldest ones destroyed first.
The following example sets a maximum particle count for a particle system.
`m_particleSystem->SetMaxParticleCount(k_maxParticleCount);`
The Faucet example in the Testbed provides an example of both types of
lifetime-driven particle destruction.
### Stuck Particles
Particles may get stuck and become obstructions that need to be destroyed or
relocated. A particle is identified as possibly stuck if it remains in contact
with two or more surfaces for a user-specified number (threshold) of particle
iterations. Once "candidates" are identified, you can implement your own logic
to decide whether they are actually stuck, and how to deal with them.
The ability to implement your own logic gives you flexibility in deciding
when you want to consider a particle stuck. For instance, a ball may
be traveling down a chute, making contact with walls on multiple sides. This
state satisfies the "possibly stuck" condition described in the previous
paragraph. But you could implement logic judging the ball not stuck as long
as it keeps traveling down the chute.
On the other hand, you could also decide that not only an immobile particle,
but even a mobile one trapped in a certain spatial range, is stuck. The system
relies on you to judge the candidates.
The following example shows one possible implementation for such a case.
// This code example of app logic deciding whether or not to eliminate stuck
// particles shows a user who set up a global array of sensor fixtures
// covering areas they know to be "problematic" for stuck particles in
// their geometry, and then at each step testing any stuck particles against
// those sensors, eliminating any stuck particles that lie inside a known
// problem region.
void DestroyStuckParticlesInSensors(
const b2Fixture * const *sensors, int32 num)
{
const int32 stuck = gParticleSystem->GetStuckCandidateCount();
if (stuck > 0)
{
const int32 *candidates = gParticleSystem->GetStuckCandidates();
const b2Vec2 *positions = gParticleSystem->GetPositionBuffer();
for (int32 i = 0; i < stuck; ++i)
{
const int32 particle = candidates[i];
const b2Vec2 &position = positions[particle];
for (int32 j = 0; j < num; ++j)
{
if(sensors[j]->TestPoint(position))
{
gParticleSystem->DestroyParticle(particle);
}
}
}
}
}
// particles in multiple contacts for 5 or more iterations are
// candidates
gParticleSystem->SetStuckThreshold(5);
// step the world (assuming the timestep, velocity iterations,
// and position iterations have been set globally).
gWorld->Step(gTimeStep, gVelocityIterations, gPositionIterations);
// Perform the above check for stuck particles against sensors
// in this global array.
DestroyStuckParticlesInSensors(gProblemAreaSensors, gNumSensors);