📄 particle.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 + -