www.pudn.com > GameEngine.rar > GameEngine_Particle.cpp, change:2005-09-26,size:6339b
#include "..\GameEngine_Common.h"
#include "..\GameEngine_SceneManager\GameEngine_SceneManager.h"
#include "..\GameEngine_Texture\GameEngine_Texture.h"
#include "GameEngine_Particle.h"
CGameEngine_Particle::CGameEngine_Particle(){
}
CGameEngine_Particle::~CGameEngine_Particle(){
Closedown();
}
bool CGameEngine_Particle::Init(int iNumParticle,
CGameEngine_SceneManager* pGameSceneManager,
TCHAR* szTextureFile){
m_iNumParticle=iNumParticle;
m_pParticles=new PARTICLE[m_iNumParticle];
m_pParticleTexture=NULL;
m_lVBOffset=0;
m_lBlockSize=500;
if(m_pParticles==NULL)
return false;
m_pGameSceneManager=pGameSceneManager;
//
if(szTextureFile!=NULL){
m_pParticleTexture=new CGameEngine_Texture(pGameSceneManager);
m_pParticleTexture->LoadTexture(szTextureFile);
}
//
if(FAILED(m_pGameSceneManager->GetDevice()->CreateVertexBuffer(
m_iNumParticle*sizeof(PARTICLE_RENDERSTRUCT),
D3DUSAGE_DYNAMIC|D3DUSAGE_POINTS|D3DUSAGE_WRITEONLY,PARTICLE_FVF,
D3DPOOL_DEFAULT,&m_pParticleVB,NULL))){
return false;
}
return true;
}
//创建一个粒子
void CGameEngine_Particle::CreateParticle(float fVX,float fVY,float fVZ){
int iDeadIndex=-1;
//回收一个已死粒子空间
for(int i=0;i<m_iNumParticle;i++){
if(m_pParticles[i].m_fLife=0.0f){
iDeadIndex=i;
break;
}
}
//所有粒子仍活着,无须创建,返回
if(iDeadIndex==-1)
return;
//生成一个新粒子
m_pParticles[iDeadIndex].m_fLife=m_fLife;
m_pParticles[iDeadIndex].m_vPosition=m_vPosition;
m_pParticles[iDeadIndex].m_fFriction=m_fFriction;
m_pParticles[iDeadIndex].m_Color=m_Color;
m_pParticles[iDeadIndex].m_fMass=m_fMass;
m_pParticles[iDeadIndex].m_fSize=m_fSize;
//设置初速度
m_pParticles[iDeadIndex].m_vVelocity=D3DXVECTOR3(fVX,fVY,fVZ);
}
//更新粒子状态
void CGameEngine_Particle::UpdateParticles(){
int iRandom;
for(int i=0;i<m_iNumParticle;i++){
//存活期递减1
m_pParticles[i].m_fLife-=1;
//存活期递减后,粒子仍然活着,进行其他状态更新
if(m_pParticles[i].m_fLife>0.0f){
//调整位置
m_pParticles[i].m_vPosition+=m_pParticles[i].m_vVelocity*m_pParticles[i].m_fMass;
//阻力速度减少
m_pParticles[i].m_vVelocity*=1-m_pParticles[i].m_fFriction;
//重力使速度增加
m_pParticles[i].m_vVelocity+= m_vGravity;
//粒子颜色
iRandom=rand()%3;
if(iRandom==0)
m_pParticles[i].m_Color=HEIGHT_YELLOW;
else if(iRandom==1)
m_pParticles[i].m_Color=MIDDLE_YELLOW;
else
m_pParticles[i].m_Color=LOW_YELLOW;
}
}
}
//设置粒子渲染状态
void CGameEngine_Particle::SetParticleRS(){
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_LIGHTING,false);
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_POINTSPRITEENABLE,true);
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_POINTSCALEENABLE,true);
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_POINTSIZE,FToW(m_fSize));
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_POINTSIZE_MIN,FToW(0.0f));
//
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_POINTSCALE_A,FToW(0.0f));
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_POINTSCALE_B,FToW(0.0f));
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_POINTSCALE_C,FToW(1.0f));
//
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE,true);
m_pGameSceneManager->GetDevice()->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
m_pGameSceneManager->GetDevice()->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);
}
//恢复粒子渲染状态
void CGameEngine_Particle::UnSetParticleRS(){
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_POINTSPRITEENABLE,false);
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_POINTSCALEENABLE,false);
m_pGameSceneManager->GetDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE,false);
}
void CGameEngine_Particle::Render(){
m_pGameSceneManager->GetDevice()->SetFVF(PARTICLE_FVF);
if(m_pParticleTexture!=NULL)
m_pGameSceneManager->SetTexture(0,m_pParticleTexture);
m_pGameSceneManager->GetDevice()->SetStreamSource(
0,m_pParticleVB,
0, sizeof(PARTICLE_RENDERSTRUCT));
//分块写入数据,并渲染
if(m_lVBOffset >= (long)(m_iNumParticle * sizeof(PARTICLE_RENDERSTRUCT)))
m_lVBOffset=0;
//
PARTICLE_RENDERSTRUCT* pVBData=NULL;
//已初始化500个粒子为一个Block
m_pParticleVB->Lock(m_lVBOffset * sizeof(PARTICLE_RENDERSTRUCT),
m_lBlockSize * sizeof(PARTICLE_RENDERSTRUCT),
(void**)&pVBData,D3DLOCK_DISCARD);
//已写入的粒子数
long lNumInBlock=0;
//分块渲染
for(int i=0;i<m_iNumParticle;i++){
if(m_pParticles[i].m_fLife>0.0f){ //活着的粒子才写入缓冲区
pVBData->m_vPosition=m_pParticles[i].m_vPosition;
pVBData->m_Color=m_pParticles[i].m_Color;
pVBData++;
lNumInBlock++;
//
if(lNumInBlock==m_lBlockSize){
m_pParticleVB->Unlock();
m_pGameSceneManager->GetDevice()->DrawPrimitive(
D3DPT_POINTLIST,
m_lVBOffset,
m_lBlockSize);
//下一个Block块
m_lVBOffset+=m_lBlockSize;
m_pParticleVB->Lock(m_lVBOffset*sizeof(PARTICLE_RENDERSTRUCT),
m_lBlockSize*sizeof(PARTICLE_RENDERSTRUCT),
(void**)&pVBData,D3DLOCK_DISCARD);
lNumInBlock=0;
}
}
}
//补充渲染最后一个Block
m_pParticleVB->Unlock();
if(lNumInBlock){
m_pGameSceneManager->GetDevice()->DrawPrimitive(
D3DPT_POINTLIST,
m_lVBOffset,
lNumInBlock);
}
m_lVBOffset=0;
}
//爆炸,初始化所有粒子属性
void CGameEngine_Particle::Explode(int iNumParticle){
float fAlfa;
float fBeta;
while(iNumParticle>0){
fBeta=fRANDOM*D3DX_PI/2.0f;
fAlfa=fRANDOM*2.0f*D3DX_PI;
//创建粒子
CreateParticle((cosf(fBeta))*(sinf(fAlfa))*(m_fRadius*fRANDOM),
(cosf(fBeta))*(cosf(fAlfa))*(m_fRadius*fRANDOM),
(sinf(fBeta))*(m_fRadius*fRANDOM));
iNumParticle--;
}
}
void CGameEngine_Particle::Closedown(){
delete[] m_pParticles;
m_pGameSceneManager=NULL;
if(m_pParticleTexture!=NULL){
m_pParticleTexture->Closedown();
m_pParticleTexture=NULL;
}
SafeRelease(m_pParticleVB);
}