⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 particle.cpp

📁 一个自己写的游戏引擎,用DirectX 写成
💻 CPP
字号:
//--------------------------------------------------
//  Desc: Timer
//  Author: 
//--------------------------------------------------
#include "../stdafx.h"
#include "Particle.h"
#include "IniFile.h"
#include "Interface.h"
#include "Color.h"

ParticleSystem::ParticleSystem()
{
	vecLocation.x = vecPrevLocation.x = 0.0f;
	vecLocation.y = vecPrevLocation.y = 0.0f;
	fTx = fTy = 0.0f;

	nParticlesAlive = 0;
	fAge = -2.0f;
	fUpdSpeed = 1.0f/50;
//	fUpdSpeed = 0.0f;
	fResidue = 0.0f;
	dwUpdatetm = 0;
	fEmissionResidue = 0.0f;
}

ParticleSystem::ParticleSystem(ParticleSystemInfo *pPsi, DWORD htex)
{
	info = *pPsi;
	hHandle = htex;

	vecLocation.x = vecPrevLocation.x = 0.0f;
	vecLocation.y = vecPrevLocation.y = 0.0f;
	fTx = fTy = 0.0f;

	nParticlesAlive = 0;
	fAge = -2.0f;
	fUpdSpeed = 1.0f/50;
	fResidue = 0.0f;
	dwUpdatetm = 0;  
	fEmissionResidue = 0.0f;
}

ParticleSystem::~ParticleSystem()
{
	// TODO: Release The Texture here
}

void ParticleSystem::SetSystem(ParticleSystemInfo *pPsi, DWORD htex)
{
	info = *pPsi;
	hHandle = htex;
}

void ParticleSystem::LoadIniFile(const char *Inifile)
{
	char textureFile[256];
	CIniFile ini(Inifile);
	ini.ReadString("FX", "TextureFile", textureFile);
	hHandle = LoadTexture(textureFile);
	vecLocation.x = vecPrevLocation.x = ini.ReadFloat("FX", "fPositionX");
	vecLocation.y = vecPrevLocation.y = ini.ReadFloat("FX", "fPositionY");
	info.fXPosMin = ini.ReadFloat("FX", "fXPosMin");
	info.fXPosMax = ini.ReadFloat("FX", "fXPosMax");
	info.fYPosMin = ini.ReadFloat("FX", "fYPosMin");
	info.fYPosMax = ini.ReadFloat("FX", "fYPosMax");
	info.fEmission = ini.ReadFloat("FX", "fEmission");
	info.EmissionNum = ini.ReadInt("FX", "EmissionNum");
	info.fLifetime = ini.ReadFloat("FX", "fLifetime");
	info.fParticleLifeMin = ini.ReadFloat("FX", "fParticleLifeMin");
	info.fParticleLifeMax = ini.ReadFloat("FX", "fParticleLifeMax");
	info.fDirection = (float)((ini.ReadInt("FX", "Direction"))*M_PI_180);
	info.fSpread = (float)((ini.ReadInt("FX", "Spread"))*M_PI_180);
	info.Relative = ini.ReadInt("FX", "Relative");
	info.fSpeedMin = ini.ReadFloat("FX", "fSpeedMin");
	info.fSpeedMax = ini.ReadFloat("FX", "fSpeedMax");
	info.fGravityMin = ini.ReadFloat("FX", "fGravityMin");
	info.fGravityMax = ini.ReadFloat("FX", "fGravityMax");
	info.fRadialAccelMin = ini.ReadFloat("FX", "fRadialAccelMin");
	info.fRadialAccelMax = ini.ReadFloat("FX", "fRadialAccelMax");
	info.fTangentialAccelMin = ini.ReadFloat("FX", "fTangentialAccelMin");
	info.fTangentialAccelMax = ini.ReadFloat("FX", "fTangentialAccelMax");
	info.fSizeStart = ini.ReadFloat("FX", "fSizeStart");
	info.fSizeEnd = ini.ReadFloat("FX", "fSizeEnd");
	info.fSizeVar = ini.ReadFloat("FX", "fSizeVar");
	info.fSpinStart = ini.ReadFloat("FX", "fSpinStart");
	info.fSpinEnd = ini.ReadFloat("FX", "fSpinEnd");
	info.fSpinVar = ini.ReadFloat("FX", "fSpinVar");
	info.dwColorStart = ini.ReadDWORD("FX", "dwColorStart");
	info.dwColorEnd = ini.ReadDWORD("FX", "dwColorEnd");
	info.fColorVar = ini.ReadFloat("FX", "fColorVar");
	info.fAlphaVar = ini.ReadFloat("FX", "fAlphaVar");
	return;

}

void ParticleSystem::Update(void)
{
	DWORD tm = ::timeGetTime();
	if(!dwUpdatetm)
	{
		dwUpdatetm = tm;
		return;
	}
	float fDeltaTime = ((float)(tm - dwUpdatetm))/1000;
	if(fUpdSpeed == 0.0f) 
	{
		Update(fDeltaTime);
	}
	else
	{
		fResidue += fDeltaTime;
		if(fResidue >= fUpdSpeed)
		{
			Update(fUpdSpeed);
			while(fResidue >= fUpdSpeed) 
			{
				fResidue -= fUpdSpeed;
			}
		}
	}

	dwUpdatetm = tm;
}

void ParticleSystem::FireAt(float x, float y)
{
	Stop();
	MoveTo(x, y);
	Fire();
}

void ParticleSystem::Fire()
{
	if(info.fLifetime == -1.0f) 
	{
		fAge = -1.0f;
	}
	else 
	{
		fAge = 0.0f;
	}
	fResidue = 0.0;
}

void ParticleSystem::Stop(bool bKillParticles)
{
	fAge = -2.0f;
	if(bKillParticles) 
	{
		nParticlesAlive = 0;
	}
}

void ParticleSystem::MoveTo(float x, float y, bool bMoveParticles)
{
	int i;
	float dx,dy;

	if(bMoveParticles)
	{
		dx = x - vecLocation.x;
		dy = y - vecLocation.y;

		for(i=0; i<nParticlesAlive; i++)
		{
			particles[i].vecLocation.x += dx;
			particles[i].vecLocation.y += dy;
		}

		vecPrevLocation.x = vecPrevLocation.x + dx;
		vecPrevLocation.y = vecPrevLocation.y + dy;
	}
	else
	{
		if(fAge == -2.0) // 已结束
		{ 
			vecPrevLocation.x = x; 
			vecPrevLocation.y = y; 
		}
		else 
		{ 
			vecPrevLocation.x = vecLocation.x;	
			vecPrevLocation.y = vecLocation.y; 
		}
	}

	vecLocation.x = x;
	vecLocation.y = y;
}

void ParticleSystem::Update(float fDeltaTime)
{
	int i;
	float ang;
	Particle *par;
	Vector2D vecAccel, vecAccel2;

	if(fAge >= 0)
	{
		fAge += fDeltaTime;
		if(fAge >= info.fLifetime) 
		{
			fAge = -2.0f;
		}
	}

	// update all alive particles
	par = particles;
	for(i=0; i<nParticlesAlive; i++)
	{
		par->fAge += fDeltaTime;
		if(par->fAge >= par->fTerminalAge)
		{
			nParticlesAlive--;
			memcpy(par, &particles[nParticlesAlive], sizeof(Particle));
			i--;
			continue;
		}

		vecAccel = par->vecLocation - vecLocation;
		vecAccel.Normalize();
		vecAccel2 = vecAccel;
		vecAccel *= par->fRadialAccel;		//射线加速度(与中心点的距离无关)

		// vecAccel2.Rotate(M_PI_2);
		ang = vecAccel2.x;
		vecAccel2.x = -vecAccel2.y;
		vecAccel2.y = ang;					//逆时针方向转90度

		vecAccel2 *= par->fTangentialAccel; //切线加速度
	//	Vector2D v0 = par->vecVelocity;
		par->vecVelocity += (vecAccel + vecAccel2)*fDeltaTime; //vt = v0 + at
		par->vecVelocity.y += par->fGravity*fDeltaTime;  //重力加速度

	//	Vector2D tempos = par->vecLocation;
		par->vecLocation += par->vecVelocity;
	//	par->vecLocation.x = (par->vecVelocity.x+v0.x)/2*fDeltaTime+tempos.x;
	//	par->vecLocation.y = (par->vecVelocity.y+v0.y)/2*fDeltaTime+tempos.y;
	/*	static float bbs = 0;
		static bool add = 0;
		if(add)
		{
			bbs+=0.1;
		}
		else
		{
			bbs-=0.1;
		}
		if(bbs>=3.0f)
		{
			bbs-=0.1;
			add=0;
		}
		if(bbs<=-3.0f)
		{
			bbs+=0.1;
			add=1;
		}
		
		//if(bbs)
		//par->vecLocation.x += bbs;*/

		par->fSpin += par->fSpinDelta * fDeltaTime;		//旋转
		par->fSize += par->fSizeDelta * fDeltaTime;		//大小

		par->fAColor += par->fADelta*fDeltaTime;		//颜色
		par->fRColor += par->fRDelta*fDeltaTime;
		par->fGColor += par->fGDelta*fDeltaTime;
		par->fBColor += par->fBDelta*fDeltaTime;

		par++;
	}

	// generate new particles
	if(fAge != -2.0f)
	{
		int nParticlesCreated = 0; 
		if(info.EmissionNum>0)
		{
			if(nParticlesAlive<info.EmissionNum)
			{
				nParticlesCreated = info.EmissionNum-nParticlesAlive;
			}
		}
		else
		{
			float fParticlesNeeded = info.fEmission*fDeltaTime + fEmissionResidue;
			nParticlesCreated = (unsigned int)fParticlesNeeded;
			fEmissionResidue = fParticlesNeeded - nParticlesCreated;
		}

		par=&particles[nParticlesAlive];

		for(i=0; i<nParticlesCreated; i++)
		{
			if(nParticlesAlive>=MAX_PARTICLES) break;

			par->fAge = 0.0f;
			par->fTerminalAge = RandomFloat(info.fParticleLifeMin, info.fParticleLifeMax); //生存时间

			par->vecLocation = vecPrevLocation+(vecLocation-vecPrevLocation)*RandomFloat(0.0f, 1.0f);//位置
			par->vecLocation.x += RandomFloat(info.fXPosMin, info.fXPosMax);
			par->vecLocation.y += RandomFloat(info.fYPosMin, info.fYPosMax);//位置变化

			ang=info.fDirection-(float)M_PI_2+RandomFloat(0, info.fSpread)-info.fSpread/2.0f;
			if(info.Relative) 
			{
				float anglePos = (vecPrevLocation-vecLocation).Angle();
				if(anglePos>=0.001f)
				{
					ang += anglePos+(float)M_PI_2;
				}
			}
			par->vecVelocity.x = cosf(ang);
			par->vecVelocity.y = sinf(ang);
			par->vecVelocity *= RandomFloat(info.fSpeedMin, info.fSpeedMax); //速度

			par->fGravity = RandomFloat(info.fGravityMin, info.fGravityMax);				// 重力
			par->fRadialAccel = RandomFloat(info.fRadialAccelMin, info.fRadialAccelMax);	// 发射加速度
			par->fTangentialAccel = RandomFloat(info.fTangentialAccelMin, info.fTangentialAccelMax);//切线加速度

			par->fSize = RandomFloat(info.fSizeStart, info.fSizeStart+(info.fSizeEnd-info.fSizeStart)*info.fSizeVar);
			par->fSizeDelta = (info.fSizeEnd-par->fSize) / par->fTerminalAge;

			par->fSpin = RandomFloat(info.fSpinStart, info.fSpinStart+(info.fSpinEnd-info.fSpinStart)*info.fSpinVar);
			par->fSpinDelta = (info.fSpinEnd-par->fSpin) / par->fTerminalAge;


			par->fAColor = NormalValue(RandomFloat((float)(GetA(info.dwColorStart)), GetA(info.dwColorStart)+(GetA(info.dwColorEnd)-GetA(info.dwColorStart))*info.fAlphaVar));
			par->fRColor = NormalValue(RandomFloat((float)(GetR(info.dwColorStart)), GetR(info.dwColorStart)+(GetR(info.dwColorEnd)-GetR(info.dwColorStart))*info.fColorVar));
			par->fGColor = NormalValue(RandomFloat((float)(GetG(info.dwColorStart)), GetG(info.dwColorStart)+(GetG(info.dwColorEnd)-GetG(info.dwColorStart))*info.fColorVar));
			par->fBColor = NormalValue(RandomFloat((float)(GetB(info.dwColorStart)), GetB(info.dwColorStart)+(GetB(info.dwColorEnd)-GetB(info.dwColorStart))*info.fColorVar));

			par->fADelta = (NormalValue(GetA(info.dwColorEnd))-par->fAColor) / par->fTerminalAge;
			par->fRDelta = (NormalValue(GetR(info.dwColorEnd))-par->fRColor) / par->fTerminalAge;
			par->fGDelta = (NormalValue(GetG(info.dwColorEnd))-par->fGColor) / par->fTerminalAge;
			par->fBDelta = (NormalValue(GetB(info.dwColorEnd))-par->fBColor) / par->fTerminalAge;

			nParticlesAlive++;
			par++;
		}
	}

	vecPrevLocation = vecLocation;
}

void ParticleSystem::Render()
{
	Update();
	int i;
	Particle *par = particles;
	for(i=0; i<nParticlesAlive; i++)
	{
		RECT rc = 
		{ 
			(LONG)(par->vecLocation.x + fTx), 
			(LONG)(par->vecLocation.y + fTy), 
			(LONG)(par->vecLocation.x + fTx + par->fSize), 
			(LONG)(par->vecLocation.y + fTy + par->fSize) 
		};
	//	RECT src = { 32*3, 32*2, 32*4, 32*3 };
		::Render(hHandle, &rc, NULL, ARGBNORMAL(par->fAColor, par->fRColor, par->fGColor, par->fBColor));
	//	info.sprite->RenderEx(par->vecLocation.x+fTx, par->vecLocation.y+fTy, par->fSpin*particles[i].fAge, par->fSize);
		par++;
	}
}


ParticleManager::ParticleManager()
{
	nPS = 0;
	tX = tY = 0.0f;
}

ParticleManager::~ParticleManager()
{
	for(int i=0; i<nPS; i++) 
	{
		delete psList[i];
	}
}

void ParticleManager::Update()
{
	for(int i=0; i<nPS; i++)
	{
		psList[i]->Update();
		if(psList[i]->GetAge()==-2.0f && psList[i]->GetParticlesAlive()==0)
		{
			delete psList[i];
			psList[i]=psList[nPS-1];
			nPS--;
			i--;
		}
	}
}

void ParticleManager::Render()
{
	Update();
	for(int i=0; i<nPS; i++) 
	{
		psList[i]->Render();
	}
}

ParticleSystem* ParticleManager::AddPS(const char *pFileName)
{
	if(nPS==MAX_PSYSTEMS) 
	{
		return 0;
	}
	psList[nPS] = new ParticleSystem;
	psList[nPS]->LoadIniFile(pFileName);
	psList[nPS]->Fire();
	nPS++;
	return psList[nPS-1];
}

bool ParticleManager::IsPSAlive(const ParticleSystem *ps)
{
	for(int i=0; i<nPS; i++) 
	{
		if(psList[i]==ps) 
		{
			return true;
		}
	}
	return false;
}

void ParticleManager::Transpose(float x, float y)
{
	for(int i=0; i<nPS; i++)
	{
	//	psList[i]->Transpose(x, y);
	}
	tX = x; 
	tY = y;
}

void ParticleManager::RemovePS(const ParticleSystem *ps)
{
	for(int i=0; i<nPS; i++)
	{
		if(psList[i]==ps)
		{
			delete psList[i];
			psList[i] = psList[nPS-1];
			nPS--;
			return;
		}
	}
}

void ParticleManager::RemoveAll()
{
	for(int i=0; i<nPS; i++) 
	{
		delete psList[i];
	}
	nPS=0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -