gsparticleemitter.cpp
来自「网络泡泡被.net管理」· C++ 代码 · 共 763 行 · 第 1/2 页
CPP
763 行
// GsParticleEmitter.cpp: implementation of the CGsParticleEmitter class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "..\INCLUDE\GsParticleSystem.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGsParticleEmitter::CGsParticleEmitter(CGsEngine* pEngine)
{
m_pEngine = pEngine;
// m_splash_vector = GVECTOR(0,0,0);
// m_splash_angle = 0.0F;
// m_life = 1.0F;
//
// m_emit_freq = 0.01F;
//
// m_alpha_born;
// m_alpha_born_odds;
// m_scale_born;
// m_scale_born_odds;
// m_life_born;
// m_life_born_odds;
//
// m_alpha_inc;
// m_scale_inc;
// m_life_inc;
//should have used the new C++ initialization methods for members (which are faster), but I wanted to keep
// the code readable to those new to C++
m_fAge = 0.0f;
m_fTimeLastUpdate = 0.0f;
m_fEmissionResidue = 0.0f;
m_d3dvDirection = D3DVECTOR(0,1,0);
// since we have a previous location , we have to set that to the current location, otherwise
// our first update could have erroneous data in the PrevLocation field
m_d3dvLocation = m_d3dvPrevLocation = D3DVECTOR( 0.0f, 0.0f, 0.0f);
//---- Particle System Settings ----
m_d3dcColorStart.r = 1.0f;
m_d3dcColorStart.g = 0.8f;
m_d3dcColorStart.b = 0.5f;
m_d3dcColorVar.r = 0.0f;
m_d3dcColorVar.g = 0.0f;
m_d3dcColorVar.b = 0.0f;
m_d3dcColorEnd.r = 0.0f;
m_d3dcColorEnd.g = 0.0f;
m_d3dcColorEnd.b = 1.0f;
m_fAlphaStart = 0.5f;
m_fAlphaVar = 0.0f;
m_fAlphaEnd = 0.0f;
m_fSizeStart = 1.0f;
m_fSizeVar = 0.0f;
m_fSizeEnd = 1.0f;
m_fSpeed = 265.0f;
m_fSpeedVar = 0.0f;
m_fTheta = 360.0f;
m_fLife = 1.0f;
m_fLifeVar = 0.1f;
m_fGravityStart = 0.0f;
m_fGravityVar = 0.0f;
m_fGravityEnd = 0.0f;
m_uParticlesPerSec = 68;
m_bIsMoving = FALSE;
m_bIsAttractive = FALSE;
m_bIsColliding = FALSE;
m_isGathering = FALSE;
m_bIsSuppressed = FALSE;
m_uTextureID = 0;
m_key = "";
m_uParticlesAlive = 0;
}
CGsParticleEmitter::~CGsParticleEmitter()
{
for(int i=0; i<m_ani_buf.size(); i++)
{
SAFE_DELETE(m_ani_buf[i].ptr_ani);
}
m_ani_buf.clear();
m_uParticlesAlive = 0;
}
BOOL CGsParticleEmitter::Create(LPCSTR strConfig)
{
CConfig cfg;
if(FALSE==m_pEngine->LoadConfig(cfg, strConfig))
return FALSE;
if(FALSE==Load(cfg))
return FALSE;
m_key = strConfig;
m_uParticlesAlive = 0;
return TRUE;
}
BOOL CGsParticleEmitter::Load(CConfig &config)
{
if(config.GetString("GLOBALS", "config")!=KEY("particles"))
return FALSE;
for(int i=0; i<m_ani_buf.size(); i++)
{
SAFE_DELETE(m_ani_buf[i].ptr_ani);
}
m_ani_buf.clear();
i=0;
// GSANI* pAni;
char str[100];
while(TRUE)
{
PARTICLE_ANI ani;
sprintf(str, "TEXTURE%d", i+1);
KEY key = config.GetString(str, "texture");
ani.ptr_ani = new GSANI(m_pEngine);
if(key.empty() || !ani.ptr_ani->Create(key.c_str()))
{
SAFE_DELETE(ani.ptr_ani);
break;
}
ani.has_alpha = config.GetBOOL(str, "has_alpha");
m_ani_buf.push_back(ani);
ani.ptr_ani->GetTextureGroup()->SetCacheSize(0);
ani.ptr_ani->Play();
i++;
}
if(i<1)
return FALSE;
//---- Particle System Settings ----
m_d3dcColorStart.r = config.GetFloat("data", "color_start_r");
m_d3dcColorStart.g = config.GetFloat("data", "color_start_g");
m_d3dcColorStart.b = config.GetFloat("data", "color_start_b");
m_d3dcColorVar.r = config.GetFloat("data", "color_var_r");
m_d3dcColorVar.g = config.GetFloat("data", "color_var_g");
m_d3dcColorVar.b = config.GetFloat("data", "color_var_b");
m_d3dcColorEnd.r = config.GetFloat("data", "color_end_r");
m_d3dcColorEnd.g = config.GetFloat("data", "color_end_g");
m_d3dcColorEnd.b = config.GetFloat("data", "color_end_b");
m_fAlphaStart = config.GetFloat("data", "alpha_start");
m_fAlphaVar = config.GetFloat("data", "alpha_var");
m_fAlphaEnd = config.GetFloat("data", "alpha_end");
m_fSizeStart = config.GetFloat("data", "size_start");
m_fSizeVar = config.GetFloat("data", "size_var");
m_fSizeEnd = config.GetFloat("data", "size_end");
m_fSpeed = config.GetFloat("data", "speed");
m_fSpeedVar = config.GetFloat("data", "speed_var");
m_fTheta = config.GetFloat("data", "theta");
m_fLife = config.GetFloat("data", "life");
m_fLifeVar = config.GetFloat("data", "life_var");
m_fGravityStart = config.GetFloat("data", "gravity_start");
m_fGravityVar = config.GetFloat("data", "gravity_var");
m_fGravityEnd = config.GetFloat("data", "gravity_end");
m_uParticlesPerSec = config.GetLong("data", "particles_per_sec");
m_bIsMoving = FALSE;//config.GetBOOL("data", "is_moving");
m_bIsAttractive = config.GetBOOL("data", "is_attractive");
m_bIsColliding = config.GetBOOL("data", "is_colliding");
m_isGathering = config.GetBOOL("data", "is_gathering");
m_uTextureID = 0;
return TRUE;
}
BOOL CGsParticleEmitter::Save(CConfig &config)
{
config.WriteString("particles", "GLOBALS", "config");
config.WriteFloat(m_d3dcColorStart.r, "data", "color_start_r");
config.WriteFloat(m_d3dcColorStart.g, "data", "color_start_g");
config.WriteFloat(m_d3dcColorStart.b, "data", "color_start_b");
config.WriteFloat(m_d3dcColorVar.r, "data", "color_var_r");
config.WriteFloat(m_d3dcColorVar.g, "data", "color_var_g");
config.WriteFloat(m_d3dcColorVar.b, "data", "color_var_b");
config.WriteFloat(m_d3dcColorEnd.r, "data", "color_end_r");
config.WriteFloat(m_d3dcColorEnd.g, "data", "color_end_g");
config.WriteFloat(m_d3dcColorEnd.b, "data", "color_end_b");
config.WriteFloat(m_fAlphaStart, "data", "alpha_start");
config.WriteFloat(m_fAlphaVar, "data", "alpha_var");
config.WriteFloat(m_fAlphaEnd, "data", "alpha_end");
config.WriteFloat(m_fSizeStart, "data", "size_start");
config.WriteFloat(m_fSizeVar, "data", "size_var");
config.WriteFloat(m_fSizeEnd, "data", "size_end");
config.WriteFloat(m_fSpeed, "data", "speed");
config.WriteFloat(m_fSpeedVar, "data", "speed_var");
config.WriteFloat(m_fTheta, "data", "theta");
config.WriteFloat(m_fLife, "data", "life");
config.WriteFloat(m_fLifeVar, "data", "life_var");
config.WriteFloat(m_fGravityStart, "data", "gravity_start");
config.WriteFloat(m_fGravityVar, "data", "gravity_var");
config.WriteFloat(m_fGravityEnd, "data", "gravity_end");
config.WriteLong(m_uParticlesPerSec, "data", "particles_per_sec");
config.WriteBOOL(m_bIsAttractive, "data", "is_attractive");
config.WriteBOOL(m_bIsColliding, "data", "is_colliding");
config.WriteBOOL(m_isGathering, "data", "is_gathering");
char str[100];
for(int i=0; i<m_ani_buf.size(); i++)
{
sprintf(str, "TEXTURE%d", i+1);
config.WriteString(m_ani_buf[i].ptr_ani->GetKey(), str, "texture");
config.WriteBOOL(m_ani_buf[i].has_alpha, str, "has_alpha");
}
return TRUE;
}
FLAG CGsParticleEmitter::Update()
{
if(m_pEngine)
return Update(m_pEngine->m_dwPassTime/1000.0f);
else
return -1;
}
FLAG CGsParticleEmitter::Update(float fSec, BOOL bEmit)
{
if(m_pEngine==NULL || m_key.empty())
return -1;
// m_d3dvLocation.x = m_pEngine->ValueCycle(0.0f, 500.0f, 0, 2000, 1);
// m_d3dvLocation.x = 300.0f;
// m_d3dvLocation.y = 100.0f;
// m_d3dvLocation.z = 300.0f;
// fTime is absolute time. So we need to calculate the relative time displacement or fTimeDelta that has elapesed
float fTimeDelta = fSec /*- m_fTimeLastUpdate*/;
// m_fTimeLastUpdate = fSec;
// sort of a hack (or nice screen saver effect) to test out a moving particle system
/*
if (1)//m_bIsMoving)
{
static float fThetaHoriz = 0.0f;
static float fThetaVert = 180.0f;
fThetaHoriz += 50.0f * fTimeDelta;
fThetaVert += 30.0f * fTimeDelta;
if ( fThetaHoriz > 359.0f )
fThetaHoriz = 0.0f;
if ( fThetaVert > 359.0f )
fThetaVert = 0.0f;
m_d3dvLocation.x = 30.0f * (float)cos( fThetaHoriz * 0.01745f );
m_d3dvLocation.y = 50.0f + 30.0f * (float)sin( fThetaVert * 0.01745f );
m_d3dvLocation.z = 30.0f * (float)sin( fThetaHoriz * 0.01745f );
}
else
{
// this will reset it every frame, but most importantly it will reset it to the origin if it isn't Moving
m_d3dvLocation.x = 0.0f;
m_d3dvLocation.y = 10.0f;
m_d3dvLocation.z = 0.0f;
}
*/
// clear our counter variable before counting how many particles are alive
m_uParticlesAlive = 0;
// update all particles that we own
for ( int i=0; i<MAX_PARTICLES; i++ )
{
if (m_rParticles[i].m_fAge >= 0.0f )
// if ( m_rParticles[i].Update( fTimeDelta )) // Note that the update function returns FALSE if the particle died
{
// Some systems may have particles with no Lifetime
// i.e. they could have to collide with terrain
// or they could just always be alive if the system
// had a fixed # of particles alive
if ( m_rParticles[i].m_fAge + fTimeDelta >= m_rParticles[i].m_fLifetime )
{
m_rParticles[i].m_fAge = -1.0f;
// return FALSE;
}
else
{
// everything ages so add the time elapsed
m_rParticles[i].m_fAge += fTimeDelta;
// Our current location will be our previous location next frame
m_rParticles[i].m_d3dvPrevLocation = m_rParticles[i].m_d3dvLocation;
// this moves the particle using the last known velocity and the time that has passed
m_rParticles[i].m_d3dvLocation += m_rParticles[i].m_d3dvVelocity * fTimeDelta;
// whether or not our parent system allows ground plane collision.
// this really should be a per particle setting, not an attribute of the parent system
// This isn't how you would normally do collision. This snaps any particle below the
// ground plane up to ground level. Ground collision is just to show what a fountain
// or other effects might look like
if ( m_bIsColliding )
{
if ( m_rParticles[i].m_d3dvLocation.y < -25.0f )
{
// if they are moving at a decent rate vertically reflect them
if ( m_rParticles[i].m_d3dvVelocity.y > -5.0f ) // -5.0f <= velocity.y <= 0.0f
{
m_rParticles[i].m_d3dvLocation.y = -25.0f;
m_rParticles[i].m_d3dvVelocity.y = 0.0f;
}
// otherwise, let them rest on the ground plance
else
{
m_rParticles[i].m_d3dvLocation.y = m_rParticles[i].m_d3dvPrevLocation.y;
m_rParticles[i].m_d3dvVelocity.y = -m_rParticles[i].m_d3dvVelocity.y*0.5f;
}
}
}
// note that GRAVITY is hardcoded up above. Gravity could be a vector per particle system
// to simulate a crosswind that blew the particles sideways as well.
m_rParticles[i].m_d3dvVelocity += ( GRAVITY * m_rParticles[i].m_fGravity * fTimeDelta );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?