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

📄 game_particle.cpp

📁 我做的毕业设计
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "Game_User.h"


const DWORD CParticleSystem::POINTVERTEX::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;


CParticleSystem::CParticleSystem(LPDIRECT3DDEVICE9 pDevice,char *strTexture)
{
	m_dwType			= 1;
	m_pDevice			=pDevice;
	m_EmitVel			=1.0f;			//范围
	m_EmitRate			= 30;			//速度
	m_EmitAngle			=D3DX_PI*0.02f; //角度

	m_fTime				=0.0f;			//开始时间
	m_fGravity			=-9.8f;			//地心引力
	m_fParticleLife		=1.0f;			//生命期
	m_fParticleFade		=2.0f;			//淡出
	m_fParticleSize		=100.0f;		//粒子的大小

	m_dwParticles		= 0;
	m_dwParticlesLim	= 50 ;

	m_bMoving			= false;
	m_bLive				= false;
	m_dwAttackNum		= 0;
	m_dwMagicNum		= 0;

	m_dwFlush			= 512;//512;			//小块粒子
	m_dwDiscard			= m_dwFlush*64;	//缓冲区大小
	m_dwBase			= m_dwDiscard;	//缓冲区的起始位置



	m_vPosition			=D3DXVECTOR3(0,50,0);
	m_vIntersectPoint	=D3DXVECTOR3(0,-50,0);
	m_clrEmit			=0xFFFF8040;
	m_clrFade			=0x018080FF;

	m_fYaw				=D3DX_PI*1.5f;	//水平角
	m_fPitch			=D3DX_PI*0.0f;	//垂直角
	m_vDirection		= D3DXVECTOR3(cosf(m_fYaw)*cosf(m_fPitch),sinf(m_fPitch),sinf(m_fYaw)*cosf(m_fPitch));

	m_pTexture			= NULL;			//  纹理
	m_pParticles		= NULL;			//生存粒子
	m_pParticlesFree	= NULL;			//消亡粒子
	m_pVB				= NULL;			//顶点缓冲

	D3DXCreateTextureFromFile(m_pDevice,strTexture,&m_pTexture);//从文件加载纹理

	RestoreDeviceObjects(); 
}

CParticleSystem::~CParticleSystem()
{

	InvalidateDeviceObjects();

	while( m_pParticles )
	{
		PARTICLE* pSpark = m_pParticles;
		m_pParticles = pSpark->m_pNext;
		delete pSpark;
	}

	while( m_pParticlesFree )
	{
		PARTICLE *pSpark = m_pParticlesFree;
		m_pParticlesFree = pSpark->m_pNext;
		delete pSpark;
	}
}

HRESULT CParticleSystem::RestoreDeviceObjects()
{
	HRESULT hr;

	if(FAILED(hr = m_pDevice->CreateVertexBuffer( m_dwDiscard * 
		sizeof(POINTVERTEX), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | D3DUSAGE_POINTS, 
		POINTVERTEX::FVF, D3DPOOL_DEFAULT, &m_pVB, NULL )))
	{
		return E_FAIL;
	}
	return S_OK;
}

HRESULT CParticleSystem::InvalidateDeviceObjects()
{
	SAFE_RELEASE(m_pTexture); 
	SAFE_RELEASE(m_pVB );
	return S_OK;
}

HRESULT CParticleSystem::Update( float fSecsPerFrame)
{
	PARTICLE *pParticle, **ppParticle;

	D3DMATRIX matLocal;	//用于将粒子的本地坐标,转换到世界空间的矩阵
	D3DVECTOR vDirLocal;   //粒子的本地坐标
	D3DVECTOR vPosLocal;	

	//本地坐标矩阵的z方向
	matLocal._31=m_vDirection.x;
	matLocal._32=m_vDirection.y;
	matLocal._33=m_vDirection.z;

	//本地坐标矩阵的x方向
	if(fabsf(m_vDirection.y)<1)
	{
		matLocal._11=m_vDirection.z;
		matLocal._12=0 ;
		matLocal._13=-m_vDirection.x;
	}
	else 
	{
		matLocal._11=1;
		matLocal._12=0;
		matLocal._13=0;
	}

	//本地坐标矩阵的y方向
	matLocal._21=-matLocal._12*matLocal._33+matLocal._13*matLocal._32;
	matLocal._22=-matLocal._13*matLocal._31+matLocal._11*matLocal._33;
	matLocal._23=-matLocal._11*matLocal._32+matLocal._12*matLocal._31;

	matLocal._41=0;
	matLocal._42=0;
	matLocal._43=0;
	matLocal._44=1;

	m_fTime += fSecsPerFrame;

	ppParticle = &m_pParticles;
	//更新粒子状态
	while( *ppParticle )
	{    pParticle = *ppParticle;
		// 计算新位置
		float fT = m_fTime - pParticle->m_fTime0;

		//设置加速度
		//落下时
		//衰减
		pParticle->m_fFade -= fSecsPerFrame;

		pParticle->m_vPos    = pParticle->m_vVel0 * fT + pParticle->m_vPos0;
		pParticle->m_vPos.y += (0.5f * m_fGravity) * (fT * fT);
		pParticle->m_vVel.y  = pParticle->m_vVel0.y + m_fGravity * fT;


		//删除旧粒子,落地的粒子
		if( pParticle->m_vPos.y <0 || m_fTime-pParticle->m_fTime0>m_fParticleLife )// m_fRadius)
		{
			//删除这个粒子,把它加入到消亡链表
			*ppParticle = pParticle->m_pNext;		
			pParticle->m_pNext = m_pParticlesFree;
			m_pParticlesFree = pParticle;

			m_dwParticles--;
		}
		else
		{  
			ppParticle = &pParticle->m_pNext;
		}
	}

	//发射新粒子,每次至少发射一个粒子
	DWORD dwParticlesEmit = m_dwParticles+
	DWORD(fSecsPerFrame*m_EmitRate>=1?m_EmitRate*fSecsPerFrame:	//发射率算出来的数量大于1
	fmodf(m_fTime,1/m_EmitRate)<fSecsPerFrame?1:0);			//波形分析,t2=t%T2<T1时,应该发射一个粒子

	while( m_dwParticles < m_dwParticlesLim && m_dwParticles < dwParticlesEmit )
	{
		if( m_pParticlesFree )	//如果消亡粒子链表里有,就从消亡链表里取出一个节点
		{
			pParticle = m_pParticlesFree;
			m_pParticlesFree = pParticle->m_pNext;
		}
		else					//如果没有,就再创建
		{
			if( NULL == ( pParticle = new PARTICLE ) )
				return E_OUTOFMEMORY;
		}

		pParticle->m_pNext = m_pParticles;	//加入到活动链表
		m_pParticles = pParticle;			
		m_dwParticles++;					


		FLOAT fRand1 = ((FLOAT)rand()/(FLOAT)RAND_MAX) * D3DX_PI * 2.0f;
		FLOAT fRand2 = ((FLOAT)rand()/(FLOAT)RAND_MAX) * m_EmitAngle*0.5f;	//	m_EmitAngle锥形角度,所以是一半
		FLOAT Speed  = ((FLOAT)rand()/(FLOAT)RAND_MAX*0.2f+0.8f) * m_EmitVel;
		//初始化新加入的粒子
		vDirLocal.x=Speed*	cosf(fRand1) * sinf(fRand2);
		vDirLocal.y=Speed*	sinf(fRand1) * sinf(fRand2);
		vDirLocal.z=Speed*	cosf(fRand2);

		fRand1=((FLOAT)rand()/(FLOAT)RAND_MAX*2);
		fRand2=((FLOAT)rand()/(FLOAT)RAND_MAX*2);

		switch(m_dwType)
		{
		case EMITTERTYPE_PLANAR_QUADRATE:
			vPosLocal.x=fRand1*m_EmitWidth;
			vPosLocal.y=fRand2*m_EmitWidth;  
			vPosLocal.z=0; 	
			break;
		case EMITTERTYPE_PLANAR_ROUND:
			fRand2*=D3DX_PI;
			fRand1*=m_EmitWidth; 
			vPosLocal.x=fRand1*sinf(fRand2);  
			vPosLocal.y=fRand1*cosf(fRand2);
			vPosLocal.z=0; 
			break;

		default:
			vPosLocal.x=0;
			vPosLocal.y=0;
			vPosLocal.z=0;
			break;

		}

		pParticle->m_vVel0.x  =vDirLocal.x*matLocal._11+vDirLocal.y*matLocal._21+vDirLocal.z*matLocal._31;//10* cosf(fRand1) * sinf(fRand2) * 2.5f;
		pParticle->m_vVel0.y  =vDirLocal.x*matLocal._12+vDirLocal.y*matLocal._22+vDirLocal.z*matLocal._32;//10* cosf(fRand1) * sinf(fRand2) * 2.5f;
		pParticle->m_vVel0.z  =vDirLocal.x*matLocal._13+vDirLocal.y*matLocal._23+vDirLocal.z*matLocal._33;//10* cosf(fRand1) * sinf(fRand2) * 2.5f;
	
		pParticle->m_vPos0.x  =m_vPosition.x+vPosLocal.x*matLocal._11+vPosLocal.y*matLocal._21+vPosLocal.z*matLocal._31;//10* cosf(fRand1) * sinf(fRand2) * 2.5f;
		pParticle->m_vPos0.y  =m_vPosition.y+vPosLocal.x*matLocal._12+vPosLocal.y*matLocal._22+vPosLocal.z*matLocal._32;//10* cosf(fRand1) * sinf(fRand2) * 2.5f;
		pParticle->m_vPos0.z  =m_vPosition.z+vPosLocal.x*matLocal._13+vPosLocal.y*matLocal._23+vPosLocal.z*matLocal._33;//10* cosf(fRand1) * sinf(fRand2) * 2.5f;

		pParticle->m_vPos = pParticle->m_vPos0;
		pParticle->m_vVel = pParticle->m_vVel0;

		pParticle->m_clrEmit=m_clrEmit;
		pParticle->m_clrFade=m_clrFade;

		pParticle->m_fFade      = m_fParticleFade;
		pParticle->m_fTime0     = m_fTime;
	}

	return S_OK;
}
//
bool CParticleSystem::MoveTo(D3DXVECTOR3 IntersectPoint,D3DXVECTOR3 * vPosition,float tFrameTime, float Speed)
{
	static float disXZ = 0.0f, dist = 0.0f;
	disXZ = DistanceXZOfTwoVec3(IntersectPoint, *vPosition);
	dist = DistanceOfTowVec3(IntersectPoint, *vPosition, disXZ);
	m_fYaw = GetYaw(IntersectPoint, *vPosition);
	m_fPitch = GetPitch(IntersectPoint, *vPosition);
	vPosition->x += tFrameTime*Speed*sinf(m_fYaw)*cosf(m_fPitch);
	vPosition->z += tFrameTime*Speed*cosf(m_fYaw)*cosf(m_fPitch);
	vPosition->y += tFrameTime*Speed*sinf(m_fPitch);

	if(dist <= tFrameTime*Speed)
	{
		return false;
	}		
	else
		return true;

}

HRESULT CParticleSystem::Render(float tFrame,D3DXVECTOR3 * IntersectPoint)
{
	if(IntersectPoint->y >=0)
		m_vIntersectPoint.y = IntersectPoint->y+50;
	m_vIntersectPoint.x = IntersectPoint->x;
	m_vIntersectPoint.z = IntersectPoint->z;
	

	Update2(tFrame); 
	HRESULT hr;

	D3DMATRIX matWorld;
	memset(&matWorld,0,sizeof(matWorld));
	matWorld._11=1;
	matWorld._22=1;
	matWorld._33=1;
	matWorld._44=1;

	m_pDevice->SetTransform(D3DTS_WORLD,&matWorld);

	m_pDevice->SetTexture(0,m_pTexture); 

	m_pDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
	m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
	m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
	m_pDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
	m_pDevice->SetRenderState( D3DRS_LIGHTING,FALSE);


	
	m_pDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
	m_pDevice->SetRenderState( D3DRS_POINTSCALEENABLE,  TRUE );
	m_pDevice->SetRenderState( D3DRS_POINTSIZE,     FtoDW(m_fParticleSize) );
	m_pDevice->SetRenderState( D3DRS_POINTSIZE_MIN, FtoDW(0.00f) );
	m_pDevice->SetRenderState( D3DRS_POINTSCALE_A,  FtoDW(0.00f) );
	m_pDevice->SetRenderState( D3DRS_POINTSCALE_B,  FtoDW(0.00f) );
	m_pDevice->SetRenderState( D3DRS_POINTSCALE_C,  FtoDW(1.00f) );
	m_pDevice->SetStreamSource( 0, m_pVB, 0, sizeof(POINTVERTEX) );
	m_pDevice->SetFVF( POINTVERTEX::FVF );

	PARTICLE*    pParticle = m_pParticles;
	POINTVERTEX* pVertices;
	DWORD        dwNumParticlesToRender = 0;


	//锁定顶点缓冲区,以小块填充,如果所有的小块都填充了,就绘制它们,然后再锁定下一个块,
	//如果空间用完了,就从头开始,使用DISCARD方式销毁

	m_dwBase += m_dwFlush;

	if(m_dwBase >= m_dwDiscard)
		m_dwBase = 0;

	//dwBase开始是没有使用的缓冲区, 要使用m_dwFlush个顶点
	if( FAILED( hr = m_pVB->Lock( m_dwBase * sizeof(POINTVERTEX), m_dwFlush * sizeof(POINTVERTEX),
		(void**) &pVertices, m_dwBase ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD ) ) )
	{
		return hr;
	}

	//	借助 D3DLOCK_NOOVERWRITE 对 VB 进行 Lock (锁定)。这告知 Direct3D 和驱动程序,
	//	您将要添加顶点,而并不修改您先前批处理过的顶点。 因此,如果当时正在进行一项 DMA 
	//	操作,则并不中断该操作.

	// Render each particle
	while( pParticle )
	{
		D3DXVECTOR3 vPos(pParticle->m_vPos);
		D3DXVECTOR3 vVel(pParticle->m_vVel);
		FLOAT       fLengthSq = D3DXVec3LengthSq(&vVel);
		UINT        dwSteps;

		if( fLengthSq < 1.0f )        dwSteps = 2;
		else if( fLengthSq <  4.00f ) dwSteps = 3;

⌨️ 快捷键说明

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