/////////////////////////////////////////////////////////////////////// // CEmitter.cpp // Author: Christian Benavides // Description: Class in charge of managing the initialization and // update of the particles. //////////////////////////////////////////////////////////////////////// #include "CParticle.h" #include "CEmitter.h" #include "..\CPlane.h" #include "..\Random.h" #include "..\CConsole.h" #define MIN_VELOCITY_RANGE {-10.0f,-10.0f,-10.0f} #define MAX_VELOCITY_RANGE { 10.0f,10.0f,10.0f} #define MAX_PRINT_NUM 3 CEmitter::CEmitter() { } CEmitter::CEmitter(Vector _ptPosition , const int& _nNumParticles=MAX_NUM_PARTICLES,const float& _fLifeTime=1.0f, const float& _fSpawnRate=0.0f) { m_ptPosition = _ptPosition; m_nNumParticles = _nNumParticles; m_fSpawnRatePerSec = _fSpawnRate; m_fSpawnTimer = 0.0f; m_fMaxLifeTime = _fLifeTime; /// Initialize dead particles (pool of particles) for (int iter = 0; iter < m_nNumParticles; iter++) { CParticle* pParticle = new CParticle(); m_vDeadParticles.push_back(pParticle); } } CEmitter::~CEmitter() { for (unsigned int iter = 0; iter < m_vAliveParticles.size(); iter++) delete m_vAliveParticles[iter]; m_vAliveParticles.clear(); for (unsigned int iter = 0; iter < m_vDeadParticles.size(); iter++) delete m_vDeadParticles[iter]; m_vDeadParticles.clear(); } /*METHODS*/ void CEmitter::Update(float _dt) { /// Increase the timer to calculate wether or not add a new particle m_fSpawnTimer += _dt; if (m_fSpawnTimer >= m_fSpawnRatePerSec && (int)m_vAliveParticles.size() < m_nNumParticles) { /// Add a new particle to the alive vector InitializeParticle(); m_fSpawnTimer = 0.0f; } /// Update the alive particles if (!m_vAliveParticles.empty()) { /// Iterate through the vector and update the particles for (m_itAliveIterator = m_vAliveParticles.begin(); m_itAliveIterator != m_vAliveParticles.end();) { CParticle* pCurrentParticle = *m_itAliveIterator; TestAgainstPlane(&pCurrentParticle); pCurrentParticle->Update(_dt); /// Check if it is still alive if (pCurrentParticle->GetElapsedLifeTime() >= m_fMaxLifeTime) { RemoveParticle(m_itAliveIterator); } else ++m_itAliveIterator; } } } CParticle* CEmitter::InitializeParticle() { CParticle* pNewParticle; /// Grab from the dead list if (!m_vDeadParticles.empty()) { pNewParticle = m_vDeadParticles.back(); m_vDeadParticles.pop_back(); pNewParticle->SetAlive(true); pNewParticle->SetElapsedLifeTime(GetRandomLifeTime()); pNewParticle->SetVelocity(GetRandomVelocity()); pNewParticle->SetPosition(m_ptPosition); //pNewParticle->SetSpeed(DEFAULT_SPEED); m_vAliveParticles.push_back(pNewParticle); } else pNewParticle = nullptr; return pNewParticle; } void CEmitter::RemoveParticle(std::vector::iterator& _pIter) { CParticle* pCurrentParticle = *_pIter; pCurrentParticle->SetAlive(false); m_vDeadParticles.push_back(pCurrentParticle); /// Remove the particle m_itAliveIterator=m_vAliveParticles.erase(_pIter); } float CEmitter::GetRandomLifeTime() const { //return RandomGetFloat(0.0f, m_fMaxLifeTime); return 0.0f; } Vector CEmitter::GetRandomVelocity() const { return RandomGetVector(MIN_VELOCITY_RANGE, MAX_VELOCITY_RANGE); //return{ 0.0f, -1.0f, 0.0f }; } void CEmitter::PrintParticleStatus(CConsole* _hConsole) { /// Print Alive vector status (Velocity,Position,life time) _hConsole->ClearScreen(); _hConsole->SetCursorPosition(0, 0); std::cout << "Plane: Offset: " << m_myGroundPlane->GetOffset(); std::cout << " Normal: " << m_myGroundPlane->GetNormal()<GetVelocity() << std::endl; std::cout << " Pos:" << pCurrParticle->GetPosition() << std::endl; std::cout << " Life:" << pCurrParticle->GetElapsedLifeTime() << std::endl; } } void CEmitter::TestAgainstPlane(CParticle** _particle) { int nResult= m_myGroundPlane->PointToPlane((*_particle)->GetPosition()); switch (nResult) { case 0 : case -1: { if ((*_particle)->GetBounce()) { /// Bounce off of the plane Vector vtNewVelocity = (*_particle)->GetVelocity(); vtNewVelocity = vtNewVelocity.Reflect(m_myGroundPlane->GetNormal()); (*_particle)->SetVelocity(vtNewVelocity); (*_particle)->SetBounce(false); } }break; default: (*_particle)->SetBounce(true); break; } }