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 + -
显示快捷键?