Created
July 19, 2021 19:40
-
-
Save DarkRoku12/8da49e446e2b4206126c95a87da9d38e to your computer and use it in GitHub Desktop.
Base particle system for 2D game engine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include "ps_system.hpp" | |
#include "ps_particle.hpp" | |
#include "ps_emitters.hpp" | |
// Effects - Multi-thread: | |
void ParticleSystem::applyEffectsMultiThread( int id , updater_data ud ) | |
{ | |
std::vector< Particle > *particles = ud.particles; | |
sf::VertexArray *vertices = ud.vertices; | |
float deltaTime = ud.DT; | |
auto effects = ud.effects; | |
vertices->clear(); | |
auto deadCount = particles->begin(); | |
for(auto p = particles->begin(); p != particles->end(); ++p) // p = particle. | |
{ | |
p->lifeSpan += deltaTime; | |
if(p->lifeSpan < p->lifeSpanMax) | |
{ | |
p->position += deltaTime * p->velocity; | |
p->rotation += deltaTime * p->rotationSpeed; | |
p->scale += deltaTime * p->grow; | |
for(auto &e : *effects) | |
{ | |
e->modifier( *p , deltaTime ); | |
} | |
sf::Transform transform; | |
transform.translate( p->position ); | |
transform.rotate( p->rotation ); | |
transform.scale( p->scale ); | |
std::array< sf::Vertex , 4 > verts; | |
for(int i = 0; i < 4; ++i) | |
{ | |
sf::Vertex *v = &verts[i]; | |
v->position = transform.transformPoint( p->mask.position[i] ); | |
v->texCoords = p->mask.texCoords[i]; | |
v->color = p->color; | |
} | |
vertices->append( verts[0] ); vertices->append( verts[1] ); vertices->append( verts[2] ); // ABC triangle. | |
vertices->append( verts[0] ); vertices->append( verts[3] ); vertices->append( verts[2] ); // ADC triangle. | |
*deadCount++ = *p; | |
} | |
} | |
particles->erase( deadCount , particles->end() ); | |
} | |
// System: | |
void ParticleSystem::System::update( float DT ) | |
{ | |
this->deltaTime = DT; | |
for(auto &emitter : emitters) | |
{ | |
emitter->emit( *this , DT ); | |
} | |
if(this->MT_IS_ENABLED) | |
{ | |
udA.DT = DT; udB.DT = DT; | |
auto A = pool.push( applyEffectsMultiThread , udA ); auto B = pool.push( applyEffectsMultiThread , udB ); | |
A.wait(); B.wait(); | |
} | |
else | |
{ | |
applyEffects( &particlesA , &verticesA ); | |
} | |
} | |
bool ParticleSystem::System::switchMultiThread() | |
{ | |
MT_IS_ENABLED = !MT_IS_ENABLED; | |
clear(); | |
if(MT_IS_ENABLED){ pool.resize( std::max( 1u , std::thread::hardware_concurrency() ) ); } | |
else { pool.resize( 0 ); } | |
return MT_IS_ENABLED; | |
} | |
void ParticleSystem::System::draw( sf::RenderTarget &target , sf::RenderStates states ) const | |
{ | |
states.texture = texture; | |
target.draw( verticesA , states ); | |
target.draw( verticesB , states ); | |
} | |
void ParticleSystem::System::applyEffects( std::vector< Particle > *particles , sf::VertexArray *vertices ) | |
{ | |
vertices->clear(); | |
auto deadCount = particles->begin(); | |
for(auto p = particles->begin(); p != particles->end(); ++p) // p = particle. | |
{ | |
p->lifeSpan += deltaTime; | |
if(p->lifeSpan < p->lifeSpanMax) | |
{ | |
p->position += deltaTime * p->velocity; | |
p->rotation += deltaTime * p->rotationSpeed; | |
p->scale += deltaTime * p->grow; | |
for(auto &e : effects) | |
{ | |
e->modifier( *p , deltaTime ); | |
} | |
sf::Transform transform; | |
transform.translate( p->position ); | |
transform.rotate( p->rotation ); | |
transform.scale( p->scale ); | |
std::array< sf::Vertex , 4 > verts; | |
for(int i = 0; i < 4; ++i) | |
{ | |
sf::Vertex *v = &verts[i]; | |
v->position = transform.transformPoint( p->mask.position[i] ); | |
v->texCoords = p->mask.texCoords[i]; | |
v->color = p->color; | |
} | |
vertices->append( verts[0] ); vertices->append( verts[1] ); vertices->append( verts[2] ); // ABC triangle. | |
vertices->append( verts[0] ); vertices->append( verts[3] ); vertices->append( verts[2] ); // ADC triangle. | |
*deadCount++ = *p; | |
} | |
} | |
particles->erase( deadCount , particles->end() ); | |
} | |
void ParticleSystem::System::removeEmitter( Emitter *e ) | |
{ | |
emitters.erase( std::remove( emitters.begin() , emitters.end() , e ) , emitters.end() ); | |
} | |
void ParticleSystem::System::addEmitter( Emitter *e ) | |
{ | |
emitters.push_back( e ); | |
} | |
void ParticleSystem::System::removeEffect( Effects::Effects *e ) | |
{ | |
effects.erase( std::remove( effects.begin() , effects.end() , e ) , effects.end() ); | |
} | |
void ParticleSystem::System::addEffect( Effects::Effects *e ) | |
{ | |
effects.push_back( e ); | |
} | |
int ParticleSystem::System::getParticleCount() const | |
{ | |
return particlesA.size() + particlesB.size(); | |
} | |
void ParticleSystem::System::clear() | |
{ | |
particlesA.clear(); particlesB.clear(); verticesA.clear(); verticesB.clear(); | |
} | |
void ParticleSystem::System::newParticleB( const Particle &p ) | |
{ | |
particlesB.push_back( p ); | |
} | |
void ParticleSystem::System::newParticleA( const Particle &p ) | |
{ | |
particlesA.push_back( p ); | |
} | |
void ParticleSystem::System::newParticle( const Particle &p , int amount ) | |
{ | |
if(particlesA.size() > amount) | |
{ | |
return ; | |
} | |
particlesA.push_back( p ); | |
} | |
void ParticleSystem::System::newParticle( const Particle &p ) | |
{ | |
if(MT_IS_ENABLED && particlesB.size() < particlesA.size()) | |
{ | |
particlesB.push_back( p ); | |
} | |
else | |
{ | |
particlesA.push_back( p ); | |
} | |
} | |
ParticleSystem::System::System( sf::Texture &t , Mask _mask ) : deltaTime( 0 ) | |
{ | |
MT_IS_ENABLED = false ; // Multi-threading, disable by default. | |
texture = &t ; | |
masks.push_back( _mask ); | |
verticesA.setPrimitiveType( sf::Triangles ); verticesB.setPrimitiveType( sf::Triangles ); | |
verticesA.resize( 5000 ); verticesB.resize( 5000 ); | |
verticesA.clear(); verticesB.clear(); | |
particlesA.reserve( 1100 ); particlesB.reserve( 1100 ); | |
udA.effects = &effects; udB.effects = &effects; | |
udA.particles = &particlesA; udA.vertices = &verticesA; | |
udB.particles = &particlesB; udB.vertices = &verticesB; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment