aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/Graphics/particles
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2018-11-18 22:32:55 +0800
committerchai <chaifix@163.com>2018-11-18 22:32:55 +0800
commitfc7b4579e49aaeecc81919e247e03f68bd5abfd4 (patch)
tree6547b8c7d3632591358267d06006eddc53216105 /src/libjin/Graphics/particles
parent3905924fc35f92e5092576c3f6e8fc5db7588cde (diff)
*粒子系统
Diffstat (limited to 'src/libjin/Graphics/particles')
-rw-r--r--src/libjin/Graphics/particles/je_particle.cpp56
-rw-r--r--src/libjin/Graphics/particles/je_particle.h124
-rw-r--r--src/libjin/Graphics/particles/je_particle_emitter.cpp81
-rw-r--r--src/libjin/Graphics/particles/je_particle_emitter.h62
-rw-r--r--src/libjin/Graphics/particles/je_particle_system.cpp58
-rw-r--r--src/libjin/Graphics/particles/je_particle_system.h28
6 files changed, 299 insertions, 110 deletions
diff --git a/src/libjin/Graphics/particles/je_particle.cpp b/src/libjin/Graphics/particles/je_particle.cpp
index 20bbd03..53f4570 100644
--- a/src/libjin/Graphics/particles/je_particle.cpp
+++ b/src/libjin/Graphics/particles/je_particle.cpp
@@ -1,5 +1,9 @@
+#include "../../math/je_math.h"
+
#include "je_particle.h"
+using namespace JinEngine::Math;
+
namespace JinEngine
{
namespace Graphics
@@ -7,20 +11,62 @@ namespace JinEngine
namespace Particles
{
+ Particle::Particle(const Graphic* grc)
+ : graphic(grc)
+ {
+ reset();
+ }
+
void Particle::reset()
{
- lifeTime = 0.0f;
+ transform.set(0, 0, 1, 1, 0, 0, 0);
+ lifeTime = 1.0f;
life = 0.0f;
- position.set(0, 0);
- direction = 0.0f;
speed.set(0, 0);
linearAcceleration.set(0, 0);
radialAcceleration = 0.0f;
- size = 1;
- sizeBegin = 1;
+ angularSpeed = 0;
+ scaleBegin = 1;
+ scaleEnd = 1;
+ color = Color::WHITE;
+ colorStart = Color::WHITE;
+ colorEnd = Color::WHITE;
alive = true;
}
+ void Particle::update(float dt)
+ {
+ float t = life / lifeTime;
+ // Lerp color
+ color.r = lerp<int>(colorStart.r, colorEnd.r, t);
+ color.g = lerp<int>(colorStart.g, colorEnd.g, t);
+ color.b = lerp<int>(colorStart.b, colorEnd.b, t);
+ color.a = lerp<int>(colorStart.a, colorEnd.a, t);
+ // Lerp scale.
+ Vector2<float> scale = transform.getScale();
+ scale.x = lerp<float>(scaleBegin, scaleEnd, t);
+ scale.y = scale.x;
+ transform.setScale(scale.x, scale.y);
+ // Calculate position.
+ speed += linearAcceleration * dt;
+ transform.move(speed * dt);
+ // Calculate rotation.
+ angularSpeed += radialAcceleration * dt;
+ transform.rotate(angularSpeed * dt);
+ // Update life time.
+ life += dt;
+ alive = life < lifeTime;
+ }
+
+ void Particle::render()
+ {
+ Color c = gl.getColor();
+ gl.setColor(color);
+ if (graphic != nullptr)
+ graphic->render(transform);
+ gl.getColor();
+ }
+
}
}
} \ No newline at end of file
diff --git a/src/libjin/Graphics/particles/je_particle.h b/src/libjin/Graphics/particles/je_particle.h
index 2d112d1..70a2653 100644
--- a/src/libjin/Graphics/particles/je_particle.h
+++ b/src/libjin/Graphics/particles/je_particle.h
@@ -1,8 +1,10 @@
#ifndef __JE_PARTICLE_H__
#define __JE_PARTICLE_H__
+#include "../../math/je_transform.h"
#include "../../math/je_vector2.hpp"
#include "../je_color.h"
+#include "../je_graphic.h"
namespace JinEngine
{
@@ -19,56 +21,20 @@ namespace JinEngine
struct LifeTimeDef
{
bool enableRandom = false;
- union
- {
- struct
- {
- float min, max;
- } random;
- float life;
- } life;
- };
-
- ///
- ///
- ///
- struct SpeedOverTimeDef
- {
- bool enable = false;
- bool enableRandom = false;
- union
- {
+ Struct(life,
struct
{
- Math::Vector2<float> startFloor;
- Math::Vector2<float> startCeil;
- Math::Vector2<float> endFloor;
- Math::Vector2<float> endCeil;
+ float floor, ceil;
} random;
- struct
- {
- Math::Vector2<float> start;
- Math::Vector2<float> end;
- } speed;
- } speed;
+ float life = 1.0f;
+ );
};
- struct SizeOverTimeDef
+ struct ScaleOverTimeDef
{
bool enable = false;
- bool enableRandom = false;
- union {
- struct {
- float startFloor = 1;
- float startCeil = 1;
- float endFloor = 1;
- float endCeil = 1;
- } random;
- struct {
- float start = 1;
- float end = 1;
- } size;
- } size;
+ float start = 1;
+ float end = 1;
};
struct ColorOverTimeDef
@@ -85,7 +51,20 @@ namespace JinEngine
struct RadialAccelarationDef
{
- float radialAccelaration;
+ float radialAccelaration = 0.f;
+ };
+
+ struct AngularSpeedDef
+ {
+ bool enableRandom = false;
+ Struct(angularSpeed,
+ struct
+ {
+ float floor = 0;
+ float ceil = 0;
+ } random;
+ float angularSpeed = 0;
+ );
};
///
@@ -101,22 +80,22 @@ namespace JinEngine
LifeTimeDef lifeTimeDef; ///<
linearAccelarationDef linearAccelarationDef; ///<
RadialAccelarationDef radialAccelarationDef; ///<
+ AngularSpeedDef angularSpeedDef; ///<
// Optional definitions.
- SpeedOverTimeDef speedOverTimeDef; ///<
- SizeOverTimeDef sizeOverTimeDef; ///<
+ ScaleOverTimeDef sizeOverTimeDef; ///<
ColorOverTimeDef colorOverTimeDef; ///<
};
///
- /// A single particle contains various properties of particle, such as position, accelaration, color and
- /// other attributes changed over time.
+ /// A single particle contains various properties of particle, such as position, accelaration, color
+ /// and other attributes changed over time.
///
struct Particle
{
///
/// Default constructor.
///
- Particle() {};
+ Particle(const Graphic* graphic);
///
/// Reset to default.
@@ -124,45 +103,54 @@ namespace JinEngine
void reset();
///
+ ///
+ ///
+ void update(float dt);
+
+ ///
+ ///
+ ///
+ void render();
+
+ //////////////////////////////////////////////////////////////////////////////////////////////////
+
+ ///
/// Whole life time.
///
- float lifeTime = 0.0f;
+ float lifeTime = 1.0f;
///
/// Current life time.
///
float life = 0.0f;
+ const Graphic* graphic;
+
///
- /// Current position.
+ /// Color over lifetime.
///
- Math::Vector2<float> position;
+ Color color = Color::WHITE;
+ Color colorStart = Color::WHITE;
+ Color colorEnd = Color::WHITE;
///
- /// Emitte direction.
- ///
- float direction = 0;
+ /// Position scale rotation origin.
+ ///
+ Math::Transform transform;
+ ///
+ /// Speeds.
+ ///
Math::Vector2<float> speed;
Math::Vector2<float> linearAcceleration;
+ float angularSpeed;
float radialAcceleration = 0;
///
/// Size over lifetime.
///
- float size = 1;
- float sizeBegin = 1;
- float sizeEnd = 1;
-
- float rotation = 0;
- float angle = 0;
-
- ///
- /// Color over lifetime.
- ///
- Color color = Color::WHITE;
- Color colorStart = Color::WHITE;
- Color colorEnd = Color::WHITE;
+ float scaleBegin = 1;
+ float scaleEnd = 1;
///
/// Is particle still alive? Alive is equivalent to NOT available in particle pool.
diff --git a/src/libjin/Graphics/particles/je_particle_emitter.cpp b/src/libjin/Graphics/particles/je_particle_emitter.cpp
index edc4bee..d8fb78d 100644
--- a/src/libjin/Graphics/particles/je_particle_emitter.cpp
+++ b/src/libjin/Graphics/particles/je_particle_emitter.cpp
@@ -3,6 +3,7 @@
#include "../../math/je_random.h"
#include "je_particle_emitter.h"
+#include "je_particle_system.h"
using namespace JinEngine::Math;
@@ -13,28 +14,90 @@ namespace JinEngine
namespace Particles
{
+ static const uint8 ACCURACY_4 = 4;
+ static const uint8 ACCURACY_5 = 5;
+ static const uint8 ACCURACY_6 = 6;
+
// Particle emitter
- static RandomGenerator rnd(time(NULL));
+ static RandomGenerator rng(0xEA44944);
ParticleEmitter::ParticleEmitter(ParticleSystem& ps)
- : mParticleSystem(ps)
+ : mPS(ps)
+ , mDef(ps.mDef.emitterDef)
+ , mPDef(ps.mDef.particleDef)
+ , mTime(0)
{
}
void ParticleEmitter::update(float dt)
{
mTime += dt;
- if (mTime < 1)
- return;
-
-
- mTime -= 1;
+ for (;mTime >= mInterval; mTime -= mInterval)
+ {
+ emit();
+ // Random rate.
+ if (mDef.emitRateDef.enableRandom)
+ mInterval = rng.randf(mDef.emitRateDef.rate.random.floor, mDef.emitRateDef.rate.random.ceil, ACCURACY_5);
+ else
+ mInterval = mDef.emitRateDef.rate.rate;
+ }
}
void ParticleEmitter::emit()
{
-
-
+ Particle* p = mPS.claim();
+ if (p == nullptr)
+ return;
+ p->reset();
+ // Init position.
+ if (mDef.positionDef.enableRandom)
+ {
+ float x = rng.randf(mDef.positionDef.position.random.floor.x, mDef.positionDef.position.random.ceil.x, ACCURACY_4);
+ float y = rng.randf(mDef.positionDef.position.random.floor.y, mDef.positionDef.position.random.ceil.y, ACCURACY_4);
+ p->transform.setPosition(x, y);
+ }
+ else
+ {
+ p->transform.setPosition(mDef.positionDef.position.position);
+ }
+ // Init speed.
+ float r = 0;
+ if (mDef.directionDef.enableRandom)
+ r = rng.randf(mDef.directionDef.direction.random.floor, mDef.directionDef.direction.random.ceil, ACCURACY_4);
+ else
+ r = mDef.directionDef.direction.direction;
+ float f = 0;
+ if (mDef.forceDef.enableRandom)
+ f = rng.randf(mDef.forceDef.force.random.floor, mDef.forceDef.force.random.ceil, ACCURACY_4);
+ else
+ f = mDef.forceDef.force.force;
+ p->speed.set(f*cos(r), f*sin(r));
+ // Init life time
+ if (mPDef.lifeTimeDef.enableRandom)
+ p->lifeTime = rng.randf(mPDef.lifeTimeDef.life.random.floor, mPDef.lifeTimeDef.life.random.floor, ACCURACY_4);
+ else
+ p->lifeTime = mPDef.lifeTimeDef.life.life;
+ // Init linear accelaration
+ p->linearAcceleration = mPDef.linearAccelarationDef.linearAccelaration;
+ // Init angular accelaration
+ p->radialAcceleration = mPDef.radialAccelarationDef.radialAccelaration;
+ // Init Angular speed.
+ if (mPDef.angularSpeedDef.enableRandom)
+ p->angularSpeed = rng.randf(mPDef.angularSpeedDef.angularSpeed.random.floor, mPDef.angularSpeedDef.angularSpeed.random.ceil, ACCURACY_4);
+ else
+ p->angularSpeed = mPDef.angularSpeedDef.angularSpeed.angularSpeed;
+ // Scale over time
+ if (mPDef.sizeOverTimeDef.enable)
+ {
+ p->scaleBegin = mPDef.sizeOverTimeDef.start;
+ p->scaleEnd = mPDef.sizeOverTimeDef.end;
+ }
+ // Color over time
+ if (mPDef.colorOverTimeDef.enable)
+ {
+ p->colorStart = mPDef.colorOverTimeDef.colorStart;
+ p->colorEnd = mPDef.colorOverTimeDef.colorEnd;
+ }
}
}
diff --git a/src/libjin/Graphics/particles/je_particle_emitter.h b/src/libjin/Graphics/particles/je_particle_emitter.h
index 9200532..44bd1fb 100644
--- a/src/libjin/Graphics/particles/je_particle_emitter.h
+++ b/src/libjin/Graphics/particles/je_particle_emitter.h
@@ -16,29 +16,27 @@ namespace JinEngine
struct PositionDef
{
bool enableRandom = false;
- union
- {
+ Struct(position,
struct
{
- Math::Vector2<float> min;
- Math::Vector2<float> max;
+ Math::Vector2<float> floor;
+ Math::Vector2<float> ceil;
} random;
Math::Vector2<float> position;
- } position;
+ );
};
struct DirectionDef
{
bool enableRandom = false;
- union
- {
+ Struct(direction,
struct
{
- float min = 0;
- float max = 0;
+ float floor = 0;
+ float ceil = 0;
} random;
float direction = 0;
- } direction;
+ );
};
///
@@ -47,25 +45,42 @@ namespace JinEngine
struct EmitRateDef
{
bool enableRandom = false;
- union
- {
+ Struct(rate,
struct
{
- float min = 1;
- float max = 1;
+ float floor = 1;
+ float ceil = 1;
} random;
float rate = 1;
- } rate;
+ );
+ };
+
+ ///
+ /// Initial speed of particle.
+ ///
+ struct ForceDef
+ {
+ bool enableRandom = false;
+ Struct(force,
+ struct
+ {
+ float floor = 1;
+ float ceil = 1;
+ } random;
+ float force = 1;
+ );
};
///
/// Definition of particle emitter.
///
- struct ParticleEmitterDef : public Temporary
+ struct ParticleEmitterDef
{
+ EmitRateDef emitRateDef; ///< Emit rate.
+
PositionDef positionDef; ///< Emit position(relativily to the particle system center).
DirectionDef directionDef; ///< Emit direction.
- EmitRateDef emitRateDef; ///< Emit rate.
+ ForceDef forceDef; ///< Emit force.
};
class ParticleSystem;
@@ -90,10 +105,14 @@ namespace JinEngine
///
///
///
- ParticleSystem& mParticleSystem;
+ ParticleSystem& mPS;
+
+ const ParticleEmitterDef& mDef;
+
+ const ParticleDef& mPDef;
///
- /// Emit a particle according to emitter definition and particle definition, particle system should
+ /// Emit particle according to emitter definition and particle definition, particle system should
/// assign particle value to the particle in particle pool, but not use this return particle.
///
void emit();
@@ -103,6 +122,11 @@ namespace JinEngine
///
float mTime;
+ ///
+ ///
+ ///
+ float mInterval;
+
};
} // namespace Particles
diff --git a/src/libjin/Graphics/particles/je_particle_system.cpp b/src/libjin/Graphics/particles/je_particle_system.cpp
index 68f8f21..a81a3c9 100644
--- a/src/libjin/Graphics/particles/je_particle_system.cpp
+++ b/src/libjin/Graphics/particles/je_particle_system.cpp
@@ -4,8 +4,64 @@ namespace JinEngine
{
namespace Graphics
{
+ namespace Particles
+ {
+ ParticleSystem::ParticleSystem(const ParticleSystemDef& def)
+ : mDef(def)
+ , mEmitter(*this)
+ , mParticlePool(def.maxParticleCount, sizeof(Particle))
+ {
+ }
+ ParticleSystem::~ParticleSystem()
+ {
+ }
+ void ParticleSystem::update(float dt)
+ {
+ mEmitter.update(dt);
+ for (int i = 0; i < mAliveParticles.size(); ++i)
+ {
+ Particle* p = mAliveParticles[i];
+ if (p->alive == false)
+ {
+ recycle(i, p);
+ --i;
+ }
+ else
+ {
+ p->update(dt);
+ }
+ }
+ }
+
+ void ParticleSystem::render(float x, float y, float sx /* = 1 */, float sy /* = 1 */, float r /* = 0 */, float ax /* = 0 */, float ay /* = 0 */)
+ {
+ for (Particle* p : mAliveParticles)
+ p->render();
+ }
+
+ void ParticleSystem::setGraphic(const Graphic* graphic)
+ {
+ mGraphic = graphic;
+ }
+
+ Particle* ParticleSystem::claim()
+ {
+ Particle* p = new (mParticlePool.GetNextWithoutInitializing()) Particle(mGraphic);
+ mAliveParticles.push_back(p);
+ return p;
+ }
+
+ void ParticleSystem::recycle(int i, Particle* p)
+ {
+ if (i >= mAliveParticles.size())
+ return;
+ mAliveParticles.erase(mAliveParticles.begin() + i);
+ mParticlePool.Delete(p);
+ }
+
+ }
}
-}
+} \ No newline at end of file
diff --git a/src/libjin/Graphics/particles/je_particle_system.h b/src/libjin/Graphics/particles/je_particle_system.h
index afa96b2..8ee79ec 100644
--- a/src/libjin/Graphics/particles/je_particle_system.h
+++ b/src/libjin/Graphics/particles/je_particle_system.h
@@ -22,10 +22,10 @@ namespace JinEngine
///
/// Definition of particle system.
///
- struct ParticleSystemDef : public Temporary
+ struct ParticleSystemDef
{
+ ParticleSystemDef() {}
uint maxParticleCount = 1; ///< Max count of particles in pool. 1 by default.
-
ParticleEmitterDef emitterDef; ///< Particle emitter definition.
ParticleDef particleDef; ///< Particle definition.
};
@@ -33,7 +33,7 @@ namespace JinEngine
///
/// Particle emitter, handle all particles it emitts.
///
- class ParticleSystem : public Game::GameObject
+ class ParticleSystem/* : public Game::GameObject*/
{
public:
///
@@ -51,25 +51,37 @@ namespace JinEngine
///
/// Update particle system and all alive particles.
///
- void update(float sec);
+ void update(float dt);
///
/// Render particle system.
///
- void render(int x, int y, float sx = 1, float sy = 1, float r = 0, float ax = 0, float ay = 0);
+ void render(float x, float y, float sx = 1, float sy = 1, float r = 0, float ax = 0, float ay = 0);
///
/// Set sprite to render.
///
/// @param sprite Sprite to render.
///
- void setSprite(Sprite* sprite);
+ void setGraphic(const Graphic* graphic);
private:
- // Disable default constructor.
+
+ friend class ParticleEmitter;
+
ParticleSystem();
///
+ ///
+ ///
+ Particle* claim();
+
+ ///
+ ///
+ ///
+ void recycle(int i, Particle* p);
+
+ ///
/// Particle system definition.
///
ParticleSystemDef mDef;
@@ -77,7 +89,7 @@ namespace JinEngine
///
/// Sprite to be drawn.
///
- Sprite* mSprite;
+ const Graphic* mGraphic;
///
/// Particle emitter.