You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
5.6 KiB
218 lines
5.6 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "particle_prototype.h" |
|
#include "particle_util.h" |
|
#include "baseparticleentity.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
// ------------------------------------------------------------------------- // |
|
// Definitions |
|
// ------------------------------------------------------------------------- // |
|
#define NUM_MOVIEEXPLOSION_EMITTERS 50 |
|
#define EXPLOSION_EMITTER_LIFETIME 3 |
|
#define EMITTED_PARTICLE_LIFETIME 1 |
|
|
|
|
|
// ------------------------------------------------------------------------- // |
|
// Classes |
|
// ------------------------------------------------------------------------- // |
|
class MovieExplosionEmitter |
|
{ |
|
public: |
|
Vector m_Pos; |
|
Vector m_Velocity; |
|
float m_Lifetime; |
|
TimedEvent m_ParticleSpawn; |
|
}; |
|
|
|
|
|
class C_MovieExplosion : public C_BaseParticleEntity, public IPrototypeAppEffect |
|
{ |
|
public: |
|
DECLARE_CLASS( C_MovieExplosion, C_BaseParticleEntity ); |
|
DECLARE_CLIENTCLASS(); |
|
|
|
C_MovieExplosion(); |
|
~C_MovieExplosion(); |
|
|
|
// C_BaseEntity. |
|
public: |
|
virtual void OnDataChanged(DataUpdateType_t updateType); |
|
|
|
// IPrototypeAppEffect. |
|
public: |
|
virtual void Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs); |
|
|
|
// IParticleEffect. |
|
public: |
|
virtual void Update(float fTimeDelta); |
|
virtual void RenderParticles( CParticleRenderIterator *pIterator ); |
|
virtual void SimulateParticles( CParticleSimulateIterator *pIterator ); |
|
|
|
|
|
public: |
|
MovieExplosionEmitter m_Emitters[NUM_MOVIEEXPLOSION_EMITTERS]; |
|
float m_EmitterLifetime; |
|
|
|
CParticleMgr *m_pParticleMgr; |
|
PMaterialHandle m_iFireballMaterial; |
|
|
|
// Setup for temporary usage in SimulateAndRender. |
|
float m_EmitterAlpha; |
|
|
|
private: |
|
C_MovieExplosion( const C_MovieExplosion & ); |
|
|
|
}; |
|
|
|
// Expose to the particle app. |
|
EXPOSE_PROTOTYPE_EFFECT(MovieExplosion, C_MovieExplosion); |
|
|
|
IMPLEMENT_CLIENTCLASS_DT(C_MovieExplosion, DT_MovieExplosion, MovieExplosion) |
|
END_RECV_TABLE() |
|
|
|
|
|
|
|
// ------------------------------------------------------------------------- // |
|
// C_MovieExplosion |
|
// ------------------------------------------------------------------------- // |
|
C_MovieExplosion::C_MovieExplosion() |
|
{ |
|
m_pParticleMgr = NULL; |
|
} |
|
|
|
|
|
C_MovieExplosion::~C_MovieExplosion() |
|
{ |
|
if(m_pParticleMgr) |
|
m_pParticleMgr->RemoveEffect( &m_ParticleEffect ); |
|
} |
|
|
|
|
|
void C_MovieExplosion::OnDataChanged(DataUpdateType_t updateType) |
|
{ |
|
C_BaseEntity::OnDataChanged(updateType); |
|
|
|
if(updateType == DATA_UPDATE_CREATED) |
|
{ |
|
Start( ParticleMgr(), NULL ); |
|
} |
|
} |
|
|
|
|
|
void C_MovieExplosion::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs) |
|
{ |
|
if(!pParticleMgr->AddEffect(&m_ParticleEffect, this)) |
|
return; |
|
|
|
// Setup our emitters. |
|
for(int iEmitter=0; iEmitter < NUM_MOVIEEXPLOSION_EMITTERS; iEmitter++) |
|
{ |
|
MovieExplosionEmitter *pEmitter = &m_Emitters[iEmitter]; |
|
pEmitter->m_Velocity = RandomVector(-1, 1) * 200; |
|
|
|
pEmitter->m_Pos = GetAbsOrigin(); |
|
|
|
pEmitter->m_Lifetime = 0; |
|
pEmitter->m_ParticleSpawn.Init(15); |
|
} |
|
m_EmitterLifetime = 0; |
|
|
|
// Get our materials. |
|
m_iFireballMaterial = m_ParticleEffect.FindOrAddMaterial("particle/particle_sphere"); |
|
|
|
m_pParticleMgr = pParticleMgr; |
|
} |
|
|
|
|
|
void C_MovieExplosion::Update(float fTimeDelta) |
|
{ |
|
if(!m_pParticleMgr) |
|
return; |
|
|
|
m_EmitterLifetime += fTimeDelta; |
|
if(m_EmitterLifetime > EXPLOSION_EMITTER_LIFETIME) |
|
return; |
|
|
|
m_EmitterAlpha = (float)sin(m_EmitterLifetime * 3.14159f / EXPLOSION_EMITTER_LIFETIME); |
|
|
|
// Simulate the emitters and have them spit out particles. |
|
for(int iEmitter=0; iEmitter < NUM_MOVIEEXPLOSION_EMITTERS; iEmitter++) |
|
{ |
|
MovieExplosionEmitter *pEmitter = &m_Emitters[iEmitter]; |
|
|
|
pEmitter->m_Pos = pEmitter->m_Pos + pEmitter->m_Velocity * fTimeDelta; |
|
pEmitter->m_Velocity = pEmitter->m_Velocity * 0.9; |
|
|
|
float tempDelta = fTimeDelta; |
|
while(pEmitter->m_ParticleSpawn.NextEvent(tempDelta)) |
|
{ |
|
StandardParticle_t *pParticle = |
|
(StandardParticle_t*)m_ParticleEffect.AddParticle( sizeof(StandardParticle_t), m_iFireballMaterial); |
|
|
|
if(pParticle) |
|
{ |
|
pParticle->m_Pos = pEmitter->m_Pos; |
|
pParticle->m_Velocity = pEmitter->m_Velocity * 0.2f + RandomVector(-20, 20); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
void C_MovieExplosion::RenderParticles( CParticleRenderIterator *pIterator ) |
|
{ |
|
const StandardParticle_t *pParticle = (const StandardParticle_t*)pIterator->GetFirst(); |
|
while ( pParticle ) |
|
{ |
|
// Draw. |
|
Vector tPos; |
|
TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos); |
|
float sortKey = tPos.z; |
|
|
|
float lifetimePercent = pParticle->m_Lifetime / EMITTED_PARTICLE_LIFETIME; |
|
Vector color; |
|
color.x = sin(lifetimePercent * 3.14159); |
|
color.y = color.x * 0.5f; |
|
color.z = 0; |
|
RenderParticle_ColorSize( |
|
pIterator->GetParticleDraw(), |
|
tPos, |
|
color, |
|
m_EmitterAlpha * sin(3.14159 * lifetimePercent), |
|
10); |
|
|
|
pParticle = (const StandardParticle_t*)pIterator->GetNext( sortKey ); |
|
} |
|
} |
|
|
|
void C_MovieExplosion::SimulateParticles( CParticleSimulateIterator *pIterator ) |
|
{ |
|
StandardParticle_t *pParticle = (StandardParticle_t*)pIterator->GetFirst(); |
|
while ( pParticle ) |
|
{ |
|
// Update its lifetime. |
|
pParticle->m_Lifetime += pIterator->GetTimeDelta(); |
|
if(pParticle->m_Lifetime > 1) |
|
{ |
|
pIterator->RemoveParticle( pParticle ); |
|
} |
|
else |
|
{ |
|
// Move it (this comes after rendering to make it clear that moving the particle here won't change |
|
// its rendering for this frame since m_TransformedPos has already been set). |
|
pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * pIterator->GetTimeDelta(); |
|
} |
|
|
|
pParticle = (StandardParticle_t*)pIterator->GetNext(); |
|
} |
|
} |
|
|
|
|