summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-04-07 11:27:29 +0200
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-05-08 14:03:04 +0000
commit928c1584b67cb93a2c1e180a73574a84b4e7af01 (patch)
treef1619940e83fb21871a1fd6993c78a2d092759e0
parent13a0a505bde8868e7ac9d50aa7dfe7d6bbae60c4 (diff)
downloadmana-particle-system.tar.gz
mana-particle-system.tar.bz2
mana-particle-system.tar.xz
mana-particle-system.zip
ParticleEmitter cleanupsparticle-system
* Don't needlessly use explicit heap allocation for ParticleEmitter instances. * Initialize ParticleEmitter members at the definition.
-rw-r--r--src/particle.cpp25
-rw-r--r--src/particle.h15
-rw-r--r--src/particleemitter.cpp59
-rw-r--r--src/particleemitter.h22
-rw-r--r--src/particleemitterprop.h13
5 files changed, 54 insertions, 80 deletions
diff --git a/src/particle.cpp b/src/particle.cpp
index 0cd680e8..977e11de 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -177,7 +177,7 @@ bool Particle::update()
{
for (auto &childEmitter : mChildEmitters)
{
- Particles newParticles = childEmitter->createParticles(mLifetimePast);
+ Particles newParticles = childEmitter.createParticles(mLifetimePast);
for (auto &newParticle : newParticles)
{
newParticle->moveBy(mPos);
@@ -324,34 +324,32 @@ Particle *Particle::addEffect(const std::string &particleEffectFile,
{
if (emitterNode.name() == "emitter")
{
- ParticleEmitter *newEmitter;
- newEmitter = new ParticleEmitter(emitterNode, newParticle, mMap,
- rotation, dyePalettes);
- newParticle->addEmitter(newEmitter);
+ newParticle->addEmitter(ParticleEmitter(emitterNode, newParticle, mMap,
+ rotation, dyePalettes));
}
else if (emitterNode.name() == "deatheffect")
{
std::string deathEffect { emitterNode.textContent() };
- char deathEffectConditions = 0x00;
+ unsigned char deathEffectConditions = 0x00;
if (emitterNode.getBoolProperty("on-floor", true))
{
- deathEffectConditions += Particle::DEAD_FLOOR;
+ deathEffectConditions |= Particle::DEAD_FLOOR;
}
if (emitterNode.getBoolProperty("on-sky", true))
{
- deathEffectConditions += Particle::DEAD_SKY;
+ deathEffectConditions |= Particle::DEAD_SKY;
}
if (emitterNode.getBoolProperty("on-other", false))
{
- deathEffectConditions += Particle::DEAD_OTHER;
+ deathEffectConditions |= Particle::DEAD_OTHER;
}
if (emitterNode.getBoolProperty("on-impact", true))
{
- deathEffectConditions += Particle::DEAD_IMPACT;
+ deathEffectConditions |= Particle::DEAD_IMPACT;
}
if (emitterNode.getBoolProperty("on-timeout", true))
{
- deathEffectConditions += Particle::DEAD_TIMEOUT;
+ deathEffectConditions |= Particle::DEAD_TIMEOUT;
}
newParticle->setDeathEffect(deathEffect, deathEffectConditions);
}
@@ -408,7 +406,7 @@ void Particle::adjustEmitterSize(int w, int h)
return;
for (auto &childEmitter : mChildEmitters)
- childEmitter->adjustSize(w, h);
+ childEmitter.adjustSize(w, h);
}
float Particle::getCurrentAlpha() const
@@ -426,9 +424,6 @@ float Particle::getCurrentAlpha() const
void Particle::clear()
{
- delete_all(mChildEmitters);
- mChildEmitters.clear();
-
delete_all(mChildParticles);
mChildParticles.clear();
}
diff --git a/src/particle.h b/src/particle.h
index 96013b71..aac45e09 100644
--- a/src/particle.h
+++ b/src/particle.h
@@ -23,6 +23,7 @@
#include "actor.h"
#include "guichanfwd.h"
+#include "particleemitter.h"
#include "vector.h"
#include <list>
@@ -33,7 +34,6 @@ class Particle;
class ParticleEmitter;
using Particles = std::list<Particle *>;
-using Emitters = std::list<ParticleEmitter *>;
/**
* A particle spawned by a ParticleEmitter.
@@ -41,7 +41,7 @@ using Emitters = std::list<ParticleEmitter *>;
class Particle : public Actor
{
public:
- enum AliveStatus
+ enum AliveStatus : unsigned char
{
ALIVE = 0,
DEAD_TIMEOUT = 1,
@@ -119,9 +119,12 @@ class Particle : public Actor
/**
* Adds an emitter to the particle.
*/
- void addEmitter(ParticleEmitter *emitter)
+ void addEmitter(const ParticleEmitter &emitter)
{ mChildEmitters.push_back(emitter); }
+ void addEmitter(ParticleEmitter &&emitter)
+ { mChildEmitters.push_back(std::move(emitter)); }
+
/**
* Sets the position in 3 dimensional space in pixels relative to map.
*/
@@ -246,7 +249,7 @@ class Particle : public Actor
void setAlpha(float alpha) override {}
- void setDeathEffect(const std::string &effectFile, char conditions)
+ void setDeathEffect(const std::string &effectFile, unsigned char conditions)
{ mDeathEffect = effectFile; mDeathEffectConditions = conditions; }
protected:
@@ -266,11 +269,11 @@ class Particle : public Actor
AliveStatus mAlive = ALIVE; /**< Is the particle supposed to be drawn and updated?*/
// generic properties
bool mAutoDelete = true; /**< May the particle request its deletion by the parent particle? */
- Emitters mChildEmitters; /**< List of child emitters. */
+ std::list<ParticleEmitter> mChildEmitters; /**< List of child emitters. */
Particles mChildParticles; /**< List of particles controlled by this particle */
bool mAllowSizeAdjust = false; /**< Can the effect size be adjusted by the object props in the map file? */
std::string mDeathEffect; /**< Particle effect file to be spawned when the particle dies */
- char mDeathEffectConditions = 0;/**< Bitfield of death conditions which trigger spawning of the death particle */
+ unsigned char mDeathEffectConditions = 0; /**< Bitfield of death conditions which trigger spawning of the death particle */
// dynamic particle
float mGravity = 0.0f; /**< Downward acceleration in pixels per game-tick. */
diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp
index 525c5a60..e3c052fd 100644
--- a/src/particleemitter.cpp
+++ b/src/particleemitter.cpp
@@ -43,27 +43,6 @@ ParticleEmitter::ParticleEmitter(XML::Node emitterNode, Particle *target,
mMap = map;
mParticleTarget = target;
- // Initializing default values
- mParticlePosX.set(0.0f);
- mParticlePosY.set(0.0f);
- mParticlePosZ.set(0.0f);
- mParticleAngleHorizontal.set(0.0f);
- mParticleAngleVertical.set(0.0f);
- mParticlePower.set(0.0f);
- mParticleGravity.set(0.0f);
- mParticleRandomness.set(0);
- mParticleBounce.set(0.0f);
- mParticleFollow = false;
- mParticleAcceleration.set(0.0f);
- mParticleDieDistance.set(-1.0f);
- mParticleMomentum.set(1.0f);
- mParticleLifetime.set(-1);
- mParticleFadeOut.set(0);
- mParticleFadeIn.set(0);
- mOutput.set(1);
- mOutputPause.set(0);
- mParticleAlpha.set(1.0f);
-
for (auto propertyNode : emitterNode.children())
{
if (propertyNode.name() == "property")
@@ -76,7 +55,6 @@ ParticleEmitter::ParticleEmitter(XML::Node emitterNode, Particle *target,
}
else if (name == "position-y")
{
-
mParticlePosY = readParticleEmitterProp(propertyNode, 0.0f);
mParticlePosY.minVal *= SIN45;
mParticlePosY.maxVal *= SIN45;
@@ -92,7 +70,6 @@ ParticleEmitter::ParticleEmitter(XML::Node emitterNode, Particle *target,
else if (name == "image")
{
std::string image = propertyNode.getProperty("value", "");
- // Don't leak when multiple images are defined
if (!image.empty() && !mParticleImage)
{
if (!dyePalettes.empty())
@@ -188,7 +165,7 @@ ParticleEmitter::ParticleEmitter(XML::Node emitterNode, Particle *target,
{
ParticleEmitter newEmitter(propertyNode, mParticleTarget, map,
rotation, dyePalettes);
- mParticleChildEmitters.push_back(newEmitter);
+ mParticleChildEmitters.push_back(std::move(newEmitter));
}
else if (propertyNode.name() == "rotation")
{
@@ -201,26 +178,26 @@ ParticleEmitter::ParticleEmitter(XML::Node emitterNode, Particle *target,
else if (propertyNode.name() == "deatheffect")
{
mDeathEffect = propertyNode.textContent();
- mDeathEffectConditions = 0x00;
+
if (propertyNode.getBoolProperty("on-floor", true))
{
- mDeathEffectConditions += Particle::DEAD_FLOOR;
+ mDeathEffectConditions |= Particle::DEAD_FLOOR;
}
if (propertyNode.getBoolProperty("on-sky", true))
{
- mDeathEffectConditions += Particle::DEAD_SKY;
+ mDeathEffectConditions |= Particle::DEAD_SKY;
}
if (propertyNode.getBoolProperty("on-other", false))
{
- mDeathEffectConditions += Particle::DEAD_OTHER;
+ mDeathEffectConditions |= Particle::DEAD_OTHER;
}
if (propertyNode.getBoolProperty("on-impact", true))
{
- mDeathEffectConditions += Particle::DEAD_IMPACT;
+ mDeathEffectConditions |= Particle::DEAD_IMPACT;
}
if (propertyNode.getBoolProperty("on-timeout", true))
{
- mDeathEffectConditions += Particle::DEAD_TIMEOUT;
+ mDeathEffectConditions |= Particle::DEAD_TIMEOUT;
}
}
}
@@ -271,11 +248,11 @@ ParticleEmitter::~ParticleEmitter() = default;
template <typename T> ParticleEmitterProp<T>
ParticleEmitter::readParticleEmitterProp(XML::Node propertyNode, T def)
{
- ParticleEmitterProp<T> retval;
+ def = propertyNode.getFloatProperty("value", (double) def);
+ const T min = (T) propertyNode.getFloatProperty("min", (double) def);
+ const T max = (T) propertyNode.getFloatProperty("max", (double) def);
- def = (T) propertyNode.getFloatProperty("value", (double) def);
- retval.set((T) propertyNode.getFloatProperty("min", (double) def),
- (T) propertyNode.getFloatProperty("max", (double) def));
+ ParticleEmitterProp<T> retval(min, max);
std::string change = propertyNode.getProperty("change-func", "none");
T amplitude = (T) propertyNode.getFloatProperty("change-amplitude", 0.0);
@@ -360,14 +337,10 @@ std::list<Particle *> ParticleEmitter::createParticles(int tick)
newParticle->setAlpha(mParticleAlpha.value(tick));
for (auto &particleChildEmitter : mParticleChildEmitters)
- {
- newParticle->addEmitter(new ParticleEmitter(particleChildEmitter));
- }
+ newParticle->addEmitter(particleChildEmitter);
if (!mDeathEffect.empty())
- {
newParticle->setDeathEffect(mDeathEffect, mDeathEffectConditions);
- }
newParticles.push_back(newParticle);
}
@@ -383,19 +356,17 @@ void ParticleEmitter::adjustSize(int w, int h)
int oldWidth = mParticlePosX.maxVal - mParticlePosX.minVal;
int oldHeight = mParticlePosX.maxVal - mParticlePosY.minVal;
int oldArea = oldWidth * oldHeight;
+
+ // when the effect has no dimension it is not designed to be resizeable
if (oldArea == 0)
- {
- //when the effect has no dimension it is
- //not designed to be resizeable
return;
- }
// set the new dimensions
mParticlePosX.set(0, w);
mParticlePosY.set(0, h);
int newArea = w * h;
// adjust the output so that the particle density stays the same
- float outputFactor = (float)newArea / (float)oldArea;
+ float outputFactor = (float) newArea / oldArea;
mOutput.minVal *= outputFactor;
mOutput.maxVal *= outputFactor;
}
diff --git a/src/particleemitter.h b/src/particleemitter.h
index ede5a71d..fdbf2d1a 100644
--- a/src/particleemitter.h
+++ b/src/particleemitter.h
@@ -41,9 +41,11 @@ class Particle;
class ParticleEmitter
{
public:
- ParticleEmitter(XML::Node emitterNode, Particle *target, Map *map,
+ ParticleEmitter(XML::Node emitterNode,
+ Particle *target,
+ Map *map,
int rotation = 0,
- const std::string& dyePalettes = std::string());
+ const std::string &dyePalettes = std::string());
/**
* Copy Constructor (necessary for reference counting of particle images)
@@ -99,27 +101,27 @@ class ParticleEmitter
ParticleEmitterProp<float> mParticleGravity;
ParticleEmitterProp<int> mParticleRandomness;
ParticleEmitterProp<float> mParticleBounce;
- bool mParticleFollow;
+ bool mParticleFollow = false;
/*
* Properties of targeting particles:
*/
Particle *mParticleTarget;
ParticleEmitterProp<float> mParticleAcceleration;
- ParticleEmitterProp<float> mParticleDieDistance;
- ParticleEmitterProp<float> mParticleMomentum;
+ ParticleEmitterProp<float> mParticleDieDistance { -1.0f };
+ ParticleEmitterProp<float> mParticleMomentum { 1.0f };
/*
* Behavior over time of the particles:
*/
- ParticleEmitterProp<int> mParticleLifetime;
+ ParticleEmitterProp<int> mParticleLifetime { -1 };
ParticleEmitterProp<int> mParticleFadeOut;
ParticleEmitterProp<int> mParticleFadeIn;
Map *mMap; /**< Map the particles are spawned on */
- ParticleEmitterProp<int> mOutput; /**< Number of particles spawned per update */
- ParticleEmitterProp<int> mOutputPause; /**< Pause in frames between two spawns */
+ ParticleEmitterProp<int> mOutput { 1 }; /**< Number of particles spawned per update */
+ ParticleEmitterProp<int> mOutputPause; /**< Pause in frames between two spawns */
int mOutputPauseLeft = 0;
/*
@@ -128,13 +130,13 @@ class ParticleEmitter
ResourceRef<Image> mParticleImage; /**< Particle image, if used */
Animation mParticleAnimation; /**< Filename of particle animation file */
Animation mParticleRotation; /**< Filename of particle rotation file */
- ParticleEmitterProp<float> mParticleAlpha; /**< Opacity of the graphical representation of the particles */
+ ParticleEmitterProp<float> mParticleAlpha { 1.0f }; /**< Opacity of the graphical representation of the particles */
/*
* Death effect of the particles
*/
std::string mDeathEffect;
- char mDeathEffectConditions;
+ unsigned char mDeathEffectConditions = 0x00;
/** List of emitters the spawned particles are equipped with */
std::list<ParticleEmitter> mParticleChildEmitters;
diff --git a/src/particleemitterprop.h b/src/particleemitterprop.h
index 78f349b8..6a9d6ecb 100644
--- a/src/particleemitterprop.h
+++ b/src/particleemitterprop.h
@@ -37,17 +37,20 @@ enum ChangeFunc
template <typename T> struct ParticleEmitterProp
{
+ explicit ParticleEmitterProp(T value = T())
+ : ParticleEmitterProp(value, value)
+ {}
+
+ ParticleEmitterProp(T min, T max)
+ : minVal(min), maxVal(max)
+ {}
+
void set(T min, T max)
{
minVal = min;
maxVal = max;
}
- void set(T val)
- {
- set(val, val);
- }
-
void setFunction(ChangeFunc func, T amplitude, int period, int phase)
{
changeFunc = func;