A two semester long class project on a team. Here I have examples of spawning thousands of particles with memory efficient techniques implementing multiple patterns that are editable with JSON parameters and LUA code and are placed with a third party level editor LDTK
By reusing allocated particle objects, we can quickly spawn hundreds at a time without effecting performance or frame rate
//Brief: Gets an unused particle from the pool, if not, makes more
//Author: Li
//Returns: Reference to the free particle
Particle& ParticleSystem::GetFreeParticle()
{
unsigned size = _particles.size();
if (size > 0 && _activeParticles < size)
{
//assign a deactivated particle
for (unsigned i = 0; i < size; ++i)
{
if (!_particles[i].IsActive())
{
return _particles[i];
}
}
}
//create and add a new one
Particle newParticle = Particle();
_particles.push_back(newParticle);
return _particles.back();
}
By reading in serialized parameters from JSON, particle patterns can be edited on the fly without rebuilding. These patterns are loaded into emitter components that respond to triggers from LUA behaviour read in from Behaviour components allowing for the same build level customization from designers
void ParticleEmitter::Read(jsonObj data)
{
name = GetParent()->GetName() + GetParent()->GetID();
_numParticles = data.getInt("NumberOfParticles");
_maxEmitSpeed = data.getFloat("Speed");
_maxScale = data.getFloat("Scale") * 32.0f;
_loopDelay = data.getFloat("Delay");
_depth = data.getInt("Depth");
if (_loopDelay > 0)
{
_looping = true;
}
if (_playOnAwake)
{
_wait = true;
}
//Read what kind of particle it's emmiting with a string member from deserializer
if (data.getString("Type") == "Burst")
{
int partNum = 0;
if (data.hasObject("MaxParticle") && data.hasObject("MinParticle"))
{
Random r = Random(data.getInt("MinParticle"), data.getInt("MaxParticle"));
partNum = r.getRandomInt();
}
else
{
partNum = _numParticles;
}
BurstPattern* BurstP = new BurstPattern(partNum);
if (data.hasObject("MaxSpeed") && data.hasObject("MinSpeed"))
{
BurstP->SetSpeeds(data.getFloat("MinSpeed"), data.getFloat("MaxSpeed"));
}
if (data.hasObject("MinLifeSpan") && data.hasObject("MaxLifeSpan"))
{
BurstP->SetLifeSpan(data.getFloat("MinLifeSpan"), data.getFloat("MaxLifeSpan"));
}
if (data.hasObject("MaxScale") && data.hasObject("MinScale"))
{
BurstP->SetScale(data.getFloat("MinScale"), data.getFloat("MaxScale"));
}
if (data.hasObject("MaxRot") && data.hasObject("MinRot"))
{
BurstP->SetRot(data.getFloat("MinRot"), data.getFloat("MaxRot"));
}
if (data.hasObject("MaxRotSpeed") && data.hasObject("MinRotSpeed"))
{
BurstP->SetRotSpeed(data.getFloat("MinRotSpeed"), data.getFloat("MaxRotSpeed"));
}
_pattern = dynamic_cast(IParticlePattern*)(BurstP);
}
if (data.getString("Type") == "Trail")
{
_pattern = dynamic_cast(IParticlePattern*)(new TrailPattern());
_active = true;
}
_texture = ParticleSystem::instance()->AddTexture(name,data.getString("texturePath"));
}