summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIra Rice <irarice@gmail.com>2008-10-26 02:32:25 +0000
committerIra Rice <irarice@gmail.com>2008-10-26 02:32:25 +0000
commitfe76762f26180fdbbbac6e16bfa02c8bde3be78b (patch)
tree78867b5e4af1eee3feb7f4c4b3387a7037f18227
parentd9c8c729a1dc2f18c1a367eddfd2eb94b79ec190 (diff)
downloadmana-fe76762f26180fdbbbac6e16bfa02c8bde3be78b.tar.gz
mana-fe76762f26180fdbbbac6e16bfa02c8bde3be78b.tar.bz2
mana-fe76762f26180fdbbbac6e16bfa02c8bde3be78b.tar.xz
mana-fe76762f26180fdbbbac6e16bfa02c8bde3be78b.zip
Added Crush's recent Particle engine modifications from TMW.
-rw-r--r--AethyraLin2WinXcompile.cbp1
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/particle.cpp2
-rw-r--r--src/particleemitter.cpp100
-rw-r--r--src/particleemitter.h37
-rw-r--r--src/particleemitterprop.h112
-rw-r--r--src/utils/minmax.h50
8 files changed, 194 insertions, 112 deletions
diff --git a/AethyraLin2WinXcompile.cbp b/AethyraLin2WinXcompile.cbp
index f2711040..2abfefb8 100644
--- a/AethyraLin2WinXcompile.cbp
+++ b/AethyraLin2WinXcompile.cbp
@@ -318,6 +318,7 @@
<Unit filename="src\particle.h" />
<Unit filename="src\particleemitter.cpp" />
<Unit filename="src\particleemitter.h" />
+ <Unit filename="src\particleemitterprop.h" />
<Unit filename="src\party.cpp" />
<Unit filename="src\party.h" />
<Unit filename="src\player.cpp" />
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index d7ff67a8..d5021823 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -265,7 +265,6 @@ SET(SRCS
utils/base64.h
utils/dtor.h
utils/fastsqrt.h
- utils/minmax.h
utils/strprintf.cpp
utils/strprintf.h
utils/tostring.h
@@ -328,6 +327,7 @@ SET(SRCS
particle.h
particleemitter.cpp
particleemitter.h
+ particleemitterprop.h
player.cpp
player.h
properties.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 0f12579f..17445ddf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -227,7 +227,6 @@ aethyra_SOURCES = gui/widgets/dropdown.cpp \
utils/base64.h \
utils/dtor.h \
utils/fastsqrt.h \
- utils/minmax.h \
utils/strprintf.cpp \
utils/strprintf.h \
utils/tostring.h \
@@ -290,6 +289,7 @@ aethyra_SOURCES = gui/widgets/dropdown.cpp \
particle.h \
particleemitter.cpp \
particleemitter.h \
+ particleemitterprop.h \
party.cpp \
party.h \
player.cpp \
diff --git a/src/particle.cpp b/src/particle.cpp
index 703b34c3..b7071674 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -181,7 +181,7 @@ Particle::update()
e++
)
{
- Particles newParticles = (*e)->createParticles();
+ Particles newParticles = (*e)->createParticles(mLifetimePast);
for ( ParticleIterator p = newParticles.begin();
p != newParticles.end();
p++
diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp
index 08944cdd..edd7bf4f 100644
--- a/src/particleemitter.cpp
+++ b/src/particleemitter.cpp
@@ -74,20 +74,22 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *
if (name == "position-x")
{
- mParticlePosX = readMinMax(propertyNode, 0.0f);
+ mParticlePosX = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "position-y")
{
- mParticlePosY = readMinMax(propertyNode, 0.0f);
+ mParticlePosY = readParticleEmitterProp(propertyNode, 0.0f);
mParticlePosY.minVal *= SIN45;
mParticlePosY.maxVal *= SIN45;
+ mParticlePosY.changeAmplitude *= SIN45;
}
else if (name == "position-z")
{
- mParticlePosZ = readMinMax(propertyNode, 0.0f);
+ mParticlePosZ = readParticleEmitterProp(propertyNode, 0.0f);
mParticlePosZ.minVal *= SIN45;
mParticlePosZ.maxVal *= SIN45;
+ mParticlePosZ.changeAmplitude *= SIN45;
}
else if (name == "image")
{
@@ -101,72 +103,74 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map *
}
else if (name == "horizontal-angle")
{
- mParticleAngleHorizontal = readMinMax(propertyNode, 0.0f);
+ mParticleAngleHorizontal = readParticleEmitterProp(propertyNode, 0.0f);
mParticleAngleHorizontal.minVal += rotation;
mParticleAngleHorizontal.minVal *= DEG_RAD_FACTOR;
mParticleAngleHorizontal.maxVal += rotation;
mParticleAngleHorizontal.maxVal *= DEG_RAD_FACTOR;
+ mParticleAngleHorizontal.changeAmplitude *= DEG_RAD_FACTOR;
}
else if (name == "vertical-angle")
{
- mParticleAngleVertical = readMinMax(propertyNode, 0.0f);
+ mParticleAngleVertical = readParticleEmitterProp(propertyNode, 0.0f);
mParticleAngleVertical.minVal *= DEG_RAD_FACTOR;
mParticleAngleVertical.maxVal *= DEG_RAD_FACTOR;
+ mParticleAngleVertical.changeAmplitude *= DEG_RAD_FACTOR;
}
else if (name == "power")
{
- mParticlePower = readMinMax(propertyNode, 0.0f);
+ mParticlePower = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "gravity")
{
- mParticleGravity = readMinMax(propertyNode, 0.0f);
+ mParticleGravity = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "randomnes" || name == "randomness") // legacy bug
{
- mParticleRandomness = readMinMax(propertyNode, 0);
+ mParticleRandomness = readParticleEmitterProp(propertyNode, 0);
}
else if (name == "bounce")
{
- mParticleBounce = readMinMax(propertyNode, 0.0f);
+ mParticleBounce = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "lifetime")
{
- mParticleLifetime = readMinMax(propertyNode, 0);
+ mParticleLifetime = readParticleEmitterProp(propertyNode, 0);
mParticleLifetime.minVal += 1;
}
else if (name == "output")
{
- mOutput = readMinMax(propertyNode, 0);
+ mOutput = readParticleEmitterProp(propertyNode, 0);
mOutput.maxVal +=1;
}
else if (name == "output-pause")
{
- mOutputPause = readMinMax(propertyNode, 0);
- mOutputPauseLeft = mOutputPause.value();
+ mOutputPause = readParticleEmitterProp(propertyNode, 0);
+ mOutputPauseLeft = mOutputPause.value(0);
}
else if (name == "acceleration")
{
- mParticleAcceleration = readMinMax(propertyNode, 0.0f);
+ mParticleAcceleration = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "die-distance")
{
- mParticleDieDistance = readMinMax(propertyNode, 0.0f);
+ mParticleDieDistance = readParticleEmitterProp(propertyNode, 0.0f);
}
else if (name == "momentum")
{
- mParticleMomentum = readMinMax(propertyNode, 1.0f);
+ mParticleMomentum = readParticleEmitterProp(propertyNode, 1.0f);
}
else if (name == "fade-out")
{
- mParticleFadeOut = readMinMax(propertyNode, 0);
+ mParticleFadeOut = readParticleEmitterProp(propertyNode, 0);
}
else if (name == "fade-in")
{
- mParticleFadeIn = readMinMax(propertyNode, 0);
+ mParticleFadeIn = readParticleEmitterProp(propertyNode, 0);
}
else if (name == "alpha")
{
- mParticleAlpha = readMinMax(propertyNode, 1.0f);
+ mParticleAlpha = readParticleEmitterProp(propertyNode, 1.0f);
}
else if (name == "follow-parent")
{
@@ -301,21 +305,35 @@ ParticleEmitter::~ParticleEmitter()
}
-template <typename T> MinMax<T>
-ParticleEmitter::readMinMax(xmlNodePtr propertyNode, T def)
+template <typename T> ParticleEmitterProp<T>
+ParticleEmitter::readParticleEmitterProp(xmlNodePtr propertyNode, T def)
{
- MinMax<T> retval;
+ ParticleEmitterProp<T> retval;
def = (T) XML::getFloatProperty(propertyNode, "value", (double) def);
retval.set((T) XML::getFloatProperty(propertyNode, "min", (double) def),
(T) XML::getFloatProperty(propertyNode, "max", (double) def));
+ std::string change = XML::getProperty(propertyNode, "change-func", "none");
+ T amplitude = (T) XML::getFloatProperty(propertyNode, "change-amplitude", 0.0);
+ int period = XML::getProperty(propertyNode, "change-period", 0);
+ int phase = XML::getProperty(propertyNode, "change-phase", 0);
+ if (change == "saw" || change == "sawtooth") {
+ retval.setFunction(FUNC_SAW, amplitude, period, phase);
+ } else if (change == "sine" || change == "sinewave") {
+ retval.setFunction(FUNC_SINE, amplitude, period, phase);
+ } else if (change == "triangle") {
+ retval.setFunction(FUNC_TRIANGLE, amplitude, period, phase);
+ } else if (change == "square"){
+ retval.setFunction(FUNC_SQUARE, amplitude, period, phase);
+ }
+
return retval;
}
std::list<Particle *>
-ParticleEmitter::createParticles()
+ParticleEmitter::createParticles(int tick)
{
std::list<Particle *> newParticles;
@@ -324,9 +342,9 @@ ParticleEmitter::createParticles()
mOutputPauseLeft--;
return newParticles;
}
- mOutputPauseLeft = mOutputPause.value();
+ mOutputPauseLeft = mOutputPause.value(tick);
- for (int i = mOutput.value(); i > 0; i--)
+ for (int i = mOutput.value(tick); i > 0; i--)
{
// Limit maximum particles
if (Particle::particleCount > Particle::maxCount) break;
@@ -348,33 +366,33 @@ ParticleEmitter::createParticles()
newParticle->setPosition(
- mParticlePosX.value(),
- mParticlePosY.value(),
- mParticlePosZ.value());
+ mParticlePosX.value(tick),
+ mParticlePosY.value(tick),
+ mParticlePosZ.value(tick));
- float angleH = mParticleAngleHorizontal.value();
- float angleV = mParticleAngleVertical.value();
- float power = mParticlePower.value();
+ float angleH = mParticleAngleHorizontal.value(tick);
+ float angleV = mParticleAngleVertical.value(tick);
+ float power = mParticlePower.value(tick);
newParticle->setVelocity(
cos(angleH) * cos(angleV) * power,
sin(angleH) * cos(angleV) * power,
sin(angleV) * power);
- newParticle->setRandomness(mParticleRandomness.value());
- newParticle->setGravity(mParticleGravity.value());
- newParticle->setBounce(mParticleBounce.value());
+ newParticle->setRandomness(mParticleRandomness.value(tick));
+ newParticle->setGravity(mParticleGravity.value(tick));
+ newParticle->setBounce(mParticleBounce.value(tick));
newParticle->setFollow(mParticleFollow);
newParticle->setDestination(mParticleTarget,
- mParticleAcceleration.value(),
- mParticleMomentum.value()
+ mParticleAcceleration.value(tick),
+ mParticleMomentum.value(tick)
);
- newParticle->setDieDistance(mParticleDieDistance.value());
+ newParticle->setDieDistance(mParticleDieDistance.value(tick));
- newParticle->setLifetime(mParticleLifetime.value());
- newParticle->setFadeOut(mParticleFadeOut.value());
- newParticle->setFadeIn(mParticleFadeIn.value());
- newParticle->setAlpha(mParticleAlpha.value());
+ newParticle->setLifetime(mParticleLifetime.value(tick));
+ newParticle->setFadeOut(mParticleFadeOut.value(tick));
+ newParticle->setFadeIn(mParticleFadeIn.value(tick));
+ newParticle->setAlpha(mParticleAlpha.value(tick));
for (std::list<ParticleEmitter>::iterator i = mParticleChildEmitters.begin();
i != mParticleChildEmitters.end();
diff --git a/src/particleemitter.h b/src/particleemitter.h
index c237c1ba..31346401 100644
--- a/src/particleemitter.h
+++ b/src/particleemitter.h
@@ -27,10 +27,11 @@
#include <list>
#include "utils/xml.h"
-#include "utils/minmax.h"
#include "resources/animation.h"
+#include "particleemitterprop.h"
+
class Image;
class Map;
class Particle;
@@ -66,7 +67,7 @@ class ParticleEmitter
* Spawns new particles
* @return: a list of created particles
*/
- std::list<Particle *> createParticles();
+ std::list<Particle *> createParticles(int tick);
/**
* Sets the target of the particles that are created
@@ -76,50 +77,50 @@ class ParticleEmitter
{ mParticleTarget = target; };
private:
- template <typename T> MinMax<T> readMinMax(xmlNodePtr propertyNode, T def);
+ template <typename T> ParticleEmitterProp<T> readParticleEmitterProp(xmlNodePtr propertyNode, T def);
/**
* initial position of particles:
*/
- MinMax<float> mParticlePosX, mParticlePosY, mParticlePosZ;
+ ParticleEmitterProp<float> mParticlePosX, mParticlePosY, mParticlePosZ;
/**
* initial vector of particles:
*/
- MinMax<float> mParticleAngleHorizontal, mParticleAngleVertical;
+ ParticleEmitterProp<float> mParticleAngleHorizontal, mParticleAngleVertical;
/**
* Initial velocity of particles
*/
- MinMax<float> mParticlePower;
+ ParticleEmitterProp<float> mParticlePower;
/*
* Vector changing of particles:
*/
- MinMax<float> mParticleGravity;
- MinMax<int> mParticleRandomness;
- MinMax<float> mParticleBounce;
+ ParticleEmitterProp<float> mParticleGravity;
+ ParticleEmitterProp<int> mParticleRandomness;
+ ParticleEmitterProp<float> mParticleBounce;
bool mParticleFollow;
/*
* Properties of targeting particles:
*/
Particle *mParticleTarget;
- MinMax<float> mParticleAcceleration;
- MinMax<float> mParticleDieDistance;
- MinMax<float> mParticleMomentum;
+ ParticleEmitterProp<float> mParticleAcceleration;
+ ParticleEmitterProp<float> mParticleDieDistance;
+ ParticleEmitterProp<float> mParticleMomentum;
/*
* Behavior over time of the particles:
*/
- MinMax<int> mParticleLifetime;
- MinMax<int> mParticleFadeOut;
- MinMax<int> mParticleFadeIn;
+ ParticleEmitterProp<int> mParticleLifetime;
+ ParticleEmitterProp<int> mParticleFadeOut;
+ ParticleEmitterProp<int> mParticleFadeIn;
Map *mMap; /**< Map the particles are spawned on */
- MinMax<int> mOutput; /**< Number of particles spawned per update */
- MinMax<int> mOutputPause; /**< Pause in frames between two spawns */
+ ParticleEmitterProp<int> mOutput; /**< Number of particles spawned per update */
+ ParticleEmitterProp<int> mOutputPause; /**< Pause in frames between two spawns */
int mOutputPauseLeft;
/*
@@ -127,7 +128,7 @@ class ParticleEmitter
*/
Image *mParticleImage; /**< Particle image, if used */
Animation mParticleAnimation; /**< Filename of particle animation file */
- MinMax<float> mParticleAlpha; /**< Opacity of the graphical representation of the particles */
+ ParticleEmitterProp<float> mParticleAlpha; /**< Opacity of the graphical representation of the particles */
/** List of emitters the spawned particles are equipped with */
std::list<ParticleEmitter> mParticleChildEmitters;
diff --git a/src/particleemitterprop.h b/src/particleemitterprop.h
new file mode 100644
index 00000000..e645c169
--- /dev/null
+++ b/src/particleemitterprop.h
@@ -0,0 +1,112 @@
+/*
+ * The Mana World
+ * Copyright 2006 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include <cstdlib>
+#include <cmath>
+
+/**
+ * Returns a random numeric value that is larger than or equal min and smaller
+ * than max
+ */
+
+enum ChangeFunc
+{
+ FUNC_NONE,
+ FUNC_SINE,
+ FUNC_SAW,
+ FUNC_TRIANGLE,
+ FUNC_SQUARE
+};
+
+template <typename T> struct ParticleEmitterProp
+{
+ ParticleEmitterProp():
+ changeFunc(FUNC_NONE)
+ {
+ }
+
+ 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;
+ changeAmplitude = amplitude;
+ changePeriod = period;
+ changePhase = phase;
+ }
+
+ T value(int tick)
+ {
+ tick += changePhase;
+ T val = (T) (minVal + (maxVal - minVal) * (rand() / ((double) RAND_MAX + 1)));
+
+ switch (changeFunc)
+ {
+ case FUNC_SINE:
+ val += (T) std::sin(M_PI * 2 * ((double)(tick%changePeriod) / (double)changePeriod)) * changeAmplitude;
+ break;
+ case FUNC_SAW:
+ val += (T) (changeAmplitude * ((double)(tick%changePeriod) / (double)changePeriod)) * 2 - changeAmplitude;
+ break;
+ case FUNC_TRIANGLE:
+ if ((tick%changePeriod) * 2 < changePeriod)
+ {
+ val += changeAmplitude - (T)((tick%changePeriod) / (double)changePeriod) * changeAmplitude * 4;
+ } else {
+ val += changeAmplitude * -3 + (T)((tick%changePeriod) / (double)changePeriod) * changeAmplitude * 4;
+ // I have no idea why this works but it does
+ }
+ break;
+ case FUNC_SQUARE:
+ if ((tick%changePeriod) * 2 < changePeriod)
+ {
+ val += changeAmplitude;
+ } else {
+ val -= changeAmplitude;
+ }
+ break;
+ case FUNC_NONE:
+ default:
+ //nothing
+ break;
+ }
+
+ return val;
+ }
+
+ T minVal;
+ T maxVal;
+
+ ChangeFunc changeFunc;
+ T changeAmplitude;
+ int changePeriod;
+ int changePhase;
+};
diff --git a/src/utils/minmax.h b/src/utils/minmax.h
deleted file mode 100644
index daf18c68..00000000
--- a/src/utils/minmax.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * The Mana World
- * Copyright 2006 The Mana World Development Team
- *
- * This file is part of The Mana World.
- *
- * The Mana World is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * The Mana World is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with The Mana World; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: minmax.h 3628 2007-10-18 18:39:48Z b_lindeijer $
- */
-
-#include <cstdlib>
-
-/**
- * Returns a random numeric value that is larger than or equal min and smaller
- * than max
- */
-
-template <typename T> struct MinMax
-{
- void set(T min, T max)
- {
- minVal=min; maxVal=max;
- }
-
- void set(T val)
- {
- set(val, val);
- }
-
- T value()
- {
- return (T)(minVal + (maxVal - minVal) * (rand() / ((double) RAND_MAX + 1)));
- }
-
- T minVal;
- T maxVal;
-};