diff options
author | chai <chaifix@163.com> | 2018-11-18 22:32:55 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2018-11-18 22:32:55 +0800 |
commit | fc7b4579e49aaeecc81919e247e03f68bd5abfd4 (patch) | |
tree | 6547b8c7d3632591358267d06006eddc53216105 /src/libjin/Graphics/particles | |
parent | 3905924fc35f92e5092576c3f6e8fc5db7588cde (diff) |
*粒子系统
Diffstat (limited to 'src/libjin/Graphics/particles')
-rw-r--r-- | src/libjin/Graphics/particles/je_particle.cpp | 56 | ||||
-rw-r--r-- | src/libjin/Graphics/particles/je_particle.h | 124 | ||||
-rw-r--r-- | src/libjin/Graphics/particles/je_particle_emitter.cpp | 81 | ||||
-rw-r--r-- | src/libjin/Graphics/particles/je_particle_emitter.h | 62 | ||||
-rw-r--r-- | src/libjin/Graphics/particles/je_particle_system.cpp | 58 | ||||
-rw-r--r-- | src/libjin/Graphics/particles/je_particle_system.h | 28 |
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. |