summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/being.cpp9
-rw-r--r--src/imageparticle.cpp2
-rw-r--r--src/particle.cpp74
-rw-r--r--src/particle.h30
-rw-r--r--src/particleemitter.cpp29
-rw-r--r--src/particleemitter.h8
-rw-r--r--src/textparticle.cpp2
7 files changed, 124 insertions, 30 deletions
diff --git a/src/being.cpp b/src/being.cpp
index 138e5c5a..20225f47 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -530,19 +530,20 @@ void Being::fireMissile(Being *victim, const std::string &particle)
if (!victim || particle.empty())
return;
- Particle *target = particleEngine->createChild();
- Particle *missile = target->addEffect(particle, getPixelX(), getPixelY());
+ Particle *missile = particleEngine->addEffect(particle, getPixelX(), getPixelY());
if (missile)
{
- target->setLifetime(2000);
+ Particle *target = particleEngine->createChild();
target->moveBy(Vector(0.0f, 0.0f, 32.0f));
+ target->setLifetime(1000);
victim->controlParticle(target);
missile->setDestination(target, 7, 0);
missile->setDieDistance(8);
missile->setLifetime(900);
}
+
}
void Being::setAction(Action action, int attackType)
@@ -582,7 +583,7 @@ void Being::setAction(Action action, int attackType)
{
switch (mSpriteDirection)
{
- case DIRECTION_DOWN: rotation = 0; break;
+ case DIRECTION_DOWN: rotation = 0; break;
case DIRECTION_LEFT: rotation = 90; break;
case DIRECTION_UP: rotation = 180; break;
case DIRECTION_RIGHT: rotation = 270; break;
diff --git a/src/imageparticle.cpp b/src/imageparticle.cpp
index 76c05d64..2900239f 100644
--- a/src/imageparticle.cpp
+++ b/src/imageparticle.cpp
@@ -41,7 +41,7 @@ ImageParticle::~ImageParticle()
bool ImageParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
{
- if (!mAlive || !mImage)
+ if (!isAlive() || !mImage)
return false;
int screenX = (int) mPos.x + offsetX - mImage->getWidth() / 2;
diff --git a/src/particle.cpp b/src/particle.cpp
index e3c45a9f..cb2faa77 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -56,14 +56,15 @@ bool Particle::enabled = true;
const float Particle::PARTICLE_SKY = 800.0f;
Particle::Particle(Map *map):
- mAlive(true),
+ mAlpha(1.0f),
mLifetimeLeft(-1),
mLifetimePast(0),
mFadeOut(0),
mFadeIn(0),
- mAlpha(1.0f),
+ mAlive(ALIVE),
mAutoDelete(true),
mAllowSizeAdjust(false),
+ mDeathEffectConditions(0x00),
mGravity(0.0f),
mRandomness(0),
mBounce(0.0f),
@@ -81,6 +82,7 @@ Particle::~Particle()
{
// Delete child emitters and child particles
clear();
+ //update particle count
Particle::particleCount--;
}
@@ -104,12 +106,12 @@ bool Particle::update()
if (!mMap)
return false;
- if (mLifetimeLeft == 0)
- mAlive = false;
+ if (mLifetimeLeft == 0 && mAlive == ALIVE)
+ mAlive = DEAD_TIMEOUT;
Vector oldPos = mPos;
- if (mAlive)
+ if (mAlive == ALIVE)
{
//calculate particle movement
if (mMomentum != 1.0f)
@@ -143,7 +145,7 @@ bool Particle::update()
{
if (mInvDieDistance > 0.0f && invHypotenuse > mInvDieDistance)
{
- mAlive = false;
+ mAlive = DEAD_IMPACT;
}
float accFactor = invHypotenuse * mAcceleration;
mVelocity -= dist * accFactor;
@@ -171,7 +173,7 @@ bool Particle::update()
}
mLifetimePast++;
- if (mPos.z > PARTICLE_SKY || mPos.z < 0.0f)
+ if (mPos.z < 0.0f)
{
if (mBounce > 0.0f)
{
@@ -181,8 +183,11 @@ bool Particle::update()
}
else
{
- mAlive = false;
+ mAlive = DEAD_FLOOR;
}
+ } else if (mPos.z > PARTICLE_SKY)
+ {
+ mAlive = DEAD_SKY;
}
// Update child emitters
@@ -202,6 +207,17 @@ bool Particle::update()
}
}
+ // create death effect when the particle died
+ if (mAlive != ALIVE && mAlive != DEAD_LONG_AGO)
+ {
+ if ((mAlive & mDeathEffectConditions) > 0x00 && !mDeathEffect.empty())
+ {
+ Particle* deathEffect = particleEngine->addEffect(mDeathEffect, 0, 0);
+ deathEffect->moveBy(mPos);
+ }
+ mAlive = DEAD_LONG_AGO;
+ }
+
Vector change = mPos - oldPos;
// Update child particles
@@ -225,7 +241,7 @@ bool Particle::update()
p = mChildParticles.erase(p);
}
}
- if (!mAlive && mChildParticles.empty() && mAutoDelete)
+ if (mAlive != ALIVE && mChildParticles.empty() && mAutoDelete)
{
return false;
}
@@ -325,13 +341,39 @@ Particle *Particle::addEffect(const std::string &particleEffectFile,
// Look for additional emitters for this particle
for_each_xml_child_node(emitterNode, effectChildNode)
{
- if (!xmlStrEqual(emitterNode->name, BAD_CAST "emitter"))
- continue;
-
- ParticleEmitter *newEmitter;
- newEmitter = new ParticleEmitter(emitterNode, newParticle, mMap,
- rotation);
- newParticle->addEmitter(newEmitter);
+ if (xmlStrEqual(emitterNode->name, BAD_CAST "emitter"))
+ {
+ ParticleEmitter *newEmitter;
+ newEmitter = new ParticleEmitter(emitterNode, newParticle, mMap,
+ rotation);
+ newParticle->addEmitter(newEmitter);
+ }
+ else if (xmlStrEqual(emitterNode->name, BAD_CAST "deatheffect"))
+ {
+ std::string deathEffect = (const char*)emitterNode->xmlChildrenNode->content;
+ char deathEffectConditions = 0x00;
+ if (XML::getBoolProperty(emitterNode, "on-floor", true))
+ {
+ deathEffectConditions += Particle::DEAD_FLOOR;
+ }
+ if (XML::getBoolProperty(emitterNode, "on-sky", true))
+ {
+ deathEffectConditions += Particle::DEAD_SKY;
+ }
+ if (XML::getBoolProperty(emitterNode, "on-other", false))
+ {
+ deathEffectConditions += Particle::DEAD_OTHER;
+ }
+ if (XML::getBoolProperty(emitterNode, "on-impact", true))
+ {
+ deathEffectConditions += Particle::DEAD_IMPACT;
+ }
+ if (XML::getBoolProperty(emitterNode, "on-timeout", true))
+ {
+ deathEffectConditions += Particle::DEAD_TIMEOUT;
+ }
+ newParticle->setDeathEffect(deathEffect, deathEffectConditions);
+ }
}
mChildParticles.push_back(newParticle);
diff --git a/src/particle.h b/src/particle.h
index 2be169c1..8aa9e5f2 100644
--- a/src/particle.h
+++ b/src/particle.h
@@ -44,6 +44,16 @@ typedef Emitters::iterator EmitterIterator;
class Particle : public Actor
{
public:
+ enum AliveStatus
+ {
+ ALIVE = 0,
+ DEAD_TIMEOUT = 1,
+ DEAD_FLOOR = 2,
+ DEAD_SKY = 4,
+ DEAD_IMPACT = 8,
+ DEAD_OTHER = 16,
+ DEAD_LONG_AGO = 128
+ };
static const float PARTICLE_SKY; /**< Maximum Z position of particles */
static int fastPhysics; /**< Mode of squareroot calculation */
static int particleCount; /**< Current number of particles */
@@ -221,20 +231,20 @@ class Particle : public Actor
void setAllowSizeAdjust(bool adjust)
{ mAllowSizeAdjust = adjust; }
- bool isAlive()
- { return mAlive; }
+ bool isAlive() const
+ { return mAlive == ALIVE; }
/**
* Determines whether the particle and its children are all dead
*/
- bool isExtinct()
+ bool isExtinct() const
{ return !isAlive() && mChildParticles.empty(); }
/**
* Manually marks the particle for deletion.
*/
void kill()
- { mAlive = false; mAutoDelete = true; }
+ { mAlive = DEAD_OTHER; mAutoDelete = true; }
/**
* After calling this function the particle will only request
@@ -252,22 +262,28 @@ class Particle : public Actor
virtual void setAlpha(float alpha) {}
+ virtual void setDeathEffect(const std::string &effectFile, char conditions)
+ { mDeathEffect = effectFile; mDeathEffectConditions = conditions; }
+
protected:
- bool mAlive; /**< Is the particle supposed to be drawn and updated?*/
+ float mAlpha; /**< Opacity of the graphical representation of the particle */
int mLifetimeLeft; /**< Lifetime left in game ticks*/
int mLifetimePast; /**< Age of the particle in game ticks*/
int mFadeOut; /**< Lifetime in game ticks left where fading out begins*/
int mFadeIn; /**< Age in game ticks where fading in is finished*/
- float mAlpha; /**< Opacity of the graphical representation of the particle */
+ Vector mVelocity; /**< Speed in pixels per game-tick. */
+ private:
+ AliveStatus mAlive; /**< Is the particle supposed to be drawn and updated?*/
// generic properties
bool mAutoDelete; /**< May the particle request its deletion by the parent particle? */
Emitters mChildEmitters; /**< List of child emitters. */
Particles mChildParticles; /**< List of particles controlled by this particle */
bool mAllowSizeAdjust; /**< 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;/**< Bitfield of death conditions which trigger spawning of the death particle */
// dynamic particle
- Vector mVelocity; /**< Speed in pixels per game-tick. */
float mGravity; /**< Downward acceleration in pixels per game-tick. */
int mRandomness; /**< Ammount of random vector change */
float mBounce; /**< How much the particle bounces off when hitting the ground */
diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp
index dc9931a5..b9855c10 100644
--- a/src/particleemitter.cpp
+++ b/src/particleemitter.cpp
@@ -320,6 +320,30 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *
mParticleAnimation.addTerminator();
}
} // for frameNode
+ } else if (xmlStrEqual(propertyNode->name, BAD_CAST "deatheffect"))
+ {
+ mDeathEffect = (const char*)propertyNode->xmlChildrenNode->content;
+ mDeathEffectConditions = 0x00;
+ if (XML::getBoolProperty(propertyNode, "on-floor", true))
+ {
+ mDeathEffectConditions += Particle::DEAD_FLOOR;
+ }
+ if (XML::getBoolProperty(propertyNode, "on-sky", true))
+ {
+ mDeathEffectConditions += Particle::DEAD_SKY;
+ }
+ if (XML::getBoolProperty(propertyNode, "on-other", false))
+ {
+ mDeathEffectConditions += Particle::DEAD_OTHER;
+ }
+ if (XML::getBoolProperty(propertyNode, "on-impact", true))
+ {
+ mDeathEffectConditions += Particle::DEAD_IMPACT;
+ }
+ if (XML::getBoolProperty(propertyNode, "on-timeout", true))
+ {
+ mDeathEffectConditions += Particle::DEAD_TIMEOUT;
+ }
}
}
}
@@ -469,6 +493,11 @@ std::list<Particle *> ParticleEmitter::createParticles(int tick)
newParticle->addEmitter(new ParticleEmitter(*i));
}
+ if (!mDeathEffect.empty())
+ {
+ newParticle->setDeathEffect(mDeathEffect, mDeathEffectConditions);
+ }
+
newParticles.push_back(newParticle);
}
diff --git a/src/particleemitter.h b/src/particleemitter.h
index cc073c1c..9baaa73c 100644
--- a/src/particleemitter.h
+++ b/src/particleemitter.h
@@ -127,13 +127,19 @@ class ParticleEmitter
int mOutputPauseLeft;
/*
- * Graphical representation of the particle
+ * Graphical representation of the particles
*/
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 */
+ /*
+ * Death effect of the particles
+ */
+ std::string mDeathEffect;
+ char mDeathEffectConditions;
+
/** List of emitters the spawned particles are equipped with */
std::list<ParticleEmitter> mParticleChildEmitters;
};
diff --git a/src/textparticle.cpp b/src/textparticle.cpp
index 827343fa..e8d99dca 100644
--- a/src/textparticle.cpp
+++ b/src/textparticle.cpp
@@ -38,7 +38,7 @@ TextParticle::TextParticle(Map *map, const std::string &text,
bool TextParticle::draw(Graphics *graphics, int offsetX, int offsetY) const
{
- if (!mAlive)
+ if (!isAlive())
return false;
int screenX = (int) mPos.x + offsetX;