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); 
}