#include "EpParticleSystem.h"
#include <stdlib.h>
#include <time.h>
#include "EpLuaScriptEngine.h"
EpParticleSystem::EpParticleSystem( D3DVECTOR position, D3DVECTOR range,
D3DVECTOR acceleration, D3DVECTOR emitterPositionMin, D3DVECTOR emitterPositionMax,
D3DVECTOR velocityMin, D3DVECTOR velocityMax, D3DCOLORVALUE colorMin,
D3DCOLORVALUE colorMax, float psizeMin, float psizeMax,
int maxCount, int emitCount, float emitInterval,
LPDIRECT3DDEVICE9 device, const char *textureFileName )
{
m_Pos = position;
m_Range = range;
m_Accel = acceleration;
m_EmiPosMin = emitterPositionMin;
m_EmiPosMax = emitterPositionMax;
m_VeloMin = velocityMin;
m_VeloMax = velocityMax;
m_ColorMin = colorMin;
m_ColorMax = colorMax;
m_PSizeMin = psizeMin;
m_PSizeMax = psizeMax;
m_Count = 0;
m_MaxCount = maxCount;
m_EmiCount = emitCount;
m_EmiInterval = emitInterval;
m_Interval = 0.0f;
m_pDevice = device;
m_TexFileName = NULL;
if (textureFileName)
{
int length = strlen(textureFileName) + 1;
m_TexFileName = new char[length];
strcpy_s(m_TexFileName, length,textureFileName);
}
m_pTexture = NULL;
m_Particles = NULL;
m_pVB = NULL;
//随机数种子
srand( (unsigned)time( NULL ) );
//计算世界矩阵
D3DXMatrixTranslation(&m_WorldMat, m_Pos.x, m_Pos.y, m_Pos.z);
}
bool EpParticleSystem::Initialize()
{
if (m_pDevice == NULL)
{
return false;
}
//构建粒子池
m_Particles = new EpParticle[m_MaxCount];
if (m_Particles == NULL)
{
return false;
}
//创建顶点缓冲区
if(FAILED(m_pDevice->CreateVertexBuffer(sizeof(stParticleVertex) * m_MaxCount,
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | D3DUSAGE_POINTS,
D3DFVF_PARTICLE, D3DPOOL_DEFAULT, &m_pVB, NULL)))
return false;
//创建纹理
if (m_TexFileName != NULL)
{
D3DXCreateTextureFromFile(m_pDevice, m_TexFileName,&m_pTexture);
}
return true;
}
void EpParticleSystem::Update( float delta )
{
EpParticle *p = NULL;
for (int i = 0; i < m_Count; i++)
{
//改变粒子的速度与位置
p = &m_Particles[i];
p->pos += p->velo;
p->velo += m_Accel;
//检查粒子是否超出边界
if (!(p->pos.x <= m_Range.x/2 && p->pos.x >= -m_Range.x/2 &&
p->pos.y <= m_Range.y/2 && p->pos.y >= -m_Range.y/2 &&
p->pos.z <= m_Range.z/2 && p->pos.z >= -m_Range.z/2 ))
{
//将最后一个粒子移到该位置
m_Particles[i] = m_Particles[m_Count-1];
m_Count--; //抛弃最后一个粒子
i--; //重新检查该粒子
}
}
//发射粒子
m_Interval += delta;
if (m_Interval >= m_EmiInterval)
{
emit(m_EmiCount);
m_Interval -= m_EmiInterval;
}
}
//生成随机数
float rangeRand( float min, float max )
{
return (float)rand() / RAND_MAX * (max - min) + min;
}
//发射一定数量的粒子
void EpParticleSystem::emit( int emitCount )
{
EpParticle *p = NULL;
for (int i = 0; i < emitCount; i++)
{
if (m_Count == m_MaxCount) break;
p = &m_Particles[m_Count];
p->pos.x = rangeRand(m_EmiPosMin.x, m_EmiPosMax.x);
p->pos.y = rangeRand(m_EmiPosMin.y, m_EmiPosMax.y);
p->pos.z = rangeRand(m_EmiPosMin.z, m_EmiPosMax.z);
p->velo.x = rangeRand(m_VeloMin.x, m_VeloMax.x);
p->velo.y = rangeRand(m_VeloMin.y, m_VeloMax.y);
p->velo.z = rangeRand(m_VeloMin.z, m_VeloMax.z);
p->psize = rangeRand(m_PSizeMin, m_PSizeMax);
p->color.r = rangeRand(m_ColorMin.r, m_ColorMax.r);
p->color.g = rangeRand(m_ColorMin.g, m_ColorMax.g);
p->color.b = rangeRand(m_ColorMin.b, m_ColorMax.b);
p->color.a = rangeRand(m_ColorMin.a, m_ColorMax.a);
m_Count++;
}
}
bool EpParticleSystem::Render()
{
if (m_Count == 0)
{
return true;
}
//将粒子从粒子池转移到顶点缓冲区
stParticleVertex *p;
if(FAILED(m_pVB->Lock(0, sizeof(stParticleVertex) * m_Count, (void**)&p, 0)))
return false;
for (int i = 0; i < m_Count; i++)
{
p[i].pos = m_Particles[i].pos;
p[i].psize = m_Particles[i].psize;
p[i].color = D3DCOLOR_COLORVALUE(m_Particles[i].color.r,
m_Particles[i].color.g, m_Particles[i].color.b, m_Particles[i].color.a);
}
m_pVB->Unlock();
m_pDevice->SetTransform(D3DTS_WORLD, &m_WorldMat);
m_pDevice->SetTexture(0, m_pTexture);
m_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
m_pDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
m_pDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
m_pDevice->SetRenderState(D3DRS_POINTSCALE_A, FtoDW(0.0f));
m_pDevice->SetRenderState(D3DRS_POINTSCALE_B, FtoDW(0.0f));
m_pDevice->SetRenderState(D3DRS_POINTSCALE_C, FtoDW(10.0f));
m_pDevice->SetFVF(D3DFVF_PARTICLE);
m_pDevice->SetStreamSource(0, m_pVB, 0, sizeof(stParticleVertex));
m_pDevice->DrawPrimitive(D3DPT_POINTLIST, 0, m_Count);
m_pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
m_pDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
return true;
}
EpParticleSystem::~EpParticleSystem()
{
if (m_Particles != NULL)
{
delete[] m_Particles;
m_Particles = NULL;
}
if (m_pVB != NULL)
{
m_pVB->Release();
m_pVB = NULL;
}
if (m_pTexture != NULL)
{
m_pTexture->Release();
m_pTexture = NULL;
}
if (m_TexFileName != NULL)
{
delete[] m_TexFileName;
m_TexFileName = NULL;
}
}
EpParticleSystem * EpParticleSystem::CreateFromFile( LPDIRECT3DDEVICE9 device, const char *fileName )
{
if (!fileName) return NULL;
//初始化lua,加载粒子脚本
EpLuaScriptEngine lua;
lua.LoadScript(fileName);
D3DVECTOR position = {0}; //粒子系统的位置
lua.GetTFloat("position", 1, &position.x);
lua.GetTFloat("position", 2, &position.y);
lua.GetTFloat("position", 3, &position.z);
D3DVECTOR range = {0}; //长宽高范围
lua.GetTFloat("range", 1, &range.x);
lua.GetTFloat("range", 2, &range.y);
lua.GetTFloat("range", 3, &range.z);
D3DVECTOR accel = {0}; //加速度
lua.GetTFloat("accel", 1, &accel.x);
lua.GetTFloat("accel", 2, &accel.y);
lua.GetTFloat("accel", 3, &accel.z);
D3DVECTOR emiPosMin = {0}; //发射位置的范围
lua.GetTFloat("emiPosMin", 1, &emiPosMin.x);
lua.GetTFloat("emiPosMin", 2, &emiPosMin.y);
lua.GetTFloat("emiPosMin", 3, &emiPosMin.z);
D3DVECTOR emiPosMax = {0};
lua.GetTFloat("emiPosMax", 1, &emiPosMax.x);
lua.GetTFloat("emiPosMax", 2, &emiPosMax.y);
lua.GetTFloat("emiPosMax", 3, &emiPosMax.z);
D3DXVECTOR3 veloMin; //粒子初始速度范围
ZeroMemory(&veloMin,sizeof(veloMin));
lua.GetTFloat("veloMin", 1, &veloMin.x);
lua.GetTFloat("veloMin", 2, &veloMin.y);
lua.GetTFloat("veloMin", 3, &veloMin.z);
D3DXVECTOR3 veloMax;
ZeroMemory(&veloMax,sizeof(veloMax));
lua.GetTFloat("veloMax", 1, &veloMax.x);
lua.GetTFloat("veloMax", 2, &veloMax.y);
lua.GetTFloat("veloMax", 3, &veloMax.z);
D3DCOLORVALUE colorMin = {0}; //粒子颜色范围
lua.GetTFloat("colorMin", 1, &colorMin.a);
lua.GetTFloat("colorMin", 2, &colorMin.r);
lua.GetTFloat("colorMin", 3, &colorMin.g);
lua.GetTFloat("colorMin", 4, &colorMin.b);
D3DCOLORVALUE colorMax = {0};
lua.GetTFloat("colorMax", 1, &colorMax.a);
lua.GetTFloat("colorMax", 2, &colorMax.r);
lua.GetTFloat("colorMax", 3, &colorMax.g);
lua.GetTFloat("colorMax", 4, &colorMax.b);
float psizeMin = 0.0f; //粒子大小范围
lua.GetFloat("psizeMin", &psizeMin);
float psizeMax = 0.0f;
lua.GetFloat("psizeMax", &psizeMax);
int maxCount = 0; //最大粒子数量
lua.GetInt("maxCount", &maxCount);
int emiCount = 0; //每次发射数量
lua.GetInt("emiCount", &emiCount);
float emiInterval = 1.0f; //发射间隔时间
lua.GetFloat("emiInterval", &emiInterval);
const char *textureFile = NULL;
lua.GetString("texture", &textureFile);
EpParticleSystem *ps = new EpParticleSystem(position,range,accel,emiPosMin,
emiPosMax,veloMin,veloMax,colorMin,colorMax,psizeMin,psizeMax,maxCount,
emiCount,emiInterval,device,textureFile);
return ps;
}
- 1
- 2
前往页