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

📄 firework.h

📁 VC++ DEMO, used for the beginners and the amour
💻 H
字号:
#ifdef CGE_HEADER_H
#ifndef CGE_FIREWORK_H
#define CGE_FIREWORK_H

#include "PARTICLE.H"

namespace CGE
{
	namespace PARTICLE_SYSTEM
	{
		typedef class FIREWORK:public SYSTEM_NODE
		{
			public:
				FIREWORK();
				VOID BeginBehavior(LPPARTICLE pParticle);
				VOID CourseBehavior(D3DXVECTOR3 * vPrePosition,LPPARTICLE pParticle,FLOAT fElpasedTime);
				VOID EndBehavior(LPPARTICLE pParticle);

				FLOAT fBeginSize;
				FLOAT fVarSize;
				FLOAT fEndSize;

				D3DXCOLOR clrBegin;
				D3DXCOLOR clrVar;
				D3DXCOLOR clrEnd;

				D3DXVECTOR3	vPosition;
				D3DXVECTOR3 vGravity;
				D3DXVECTOR3 vWindVel;
				D3DXVECTOR3 vVelocity;

				FLOAT fSize;
				FLOAT fLife;
				FLOAT fVarLife;

		}*LPFIREWORK;

		CGE_INLINE
			FIREWORK::FIREWORK()
		{
			clrBegin = D3DXCOLOR(1.0f,1.0f,1.0f,1.0f);
			clrVar = D3DXCOLOR(0.0f,0.0f,0.0f,0.0f);
			clrEnd = D3DXCOLOR(0.0f,0.0f,0.0f,0.0f);

			vPosition = D3DXVECTOR3(0,0,0);
			vGravity = D3DXVECTOR3(0,0,0);
			vVelocity = D3DXVECTOR3(0,0,0);
			vWindVel = D3DXVECTOR3(0,0,0);

			fLife = 0.0f;
			fSize = 0.5f;
			fVarLife = 0.0f;
		}

		CGE_INLINE VOID
			FIREWORK::BeginBehavior(LPPARTICLE pParticle)
		{
			
			D3DXVECTOR3 vRandomVec;				
			FLOAT Radius = RANDOM_RANGE( -0.1f, 0.1f );	
			FLOAT Angle1 = RANDOM_RANGE( D3DX_PI / 4, D3DX_PI * 3 / 4 );
			FLOAT Angle2 = RANDOM_RANGE( 0,2 * D3DX_PI);
			vPosition.x = Radius * cosf(Angle2);
			vPosition.z = Radius * sinf(Angle2);
			vPosition.y = 0.0f;

			vRandomVec.y = cosf(Angle1);
			vRandomVec.x = (FLOAT)cosf(Angle2) * sinf(Angle1);
			vRandomVec.z = (FLOAT)sinf(Angle2) * sinf(Angle1);
			D3DXVec3Normalize(&vRandomVec,&vRandomVec);
			pParticle->vCurVel = vVelocity;
			pParticle->vCurVel += vRandomVec * 1.5f;
			
			pParticle->fLifeTime  = fLife + RANDOM_FLOAT * fVarLife;
			pParticle->fPassedTime = 0.0f;

			pParticle->vCurPos    = vPosition;
			pParticle->fSize = fSize;
			pParticle->clrColor = clrBegin + RANDOM_FLOAT * clrVar;
		}
		
		CGE_INLINE VOID
			FIREWORK::CourseBehavior(D3DXVECTOR3 * vPrePosition,LPPARTICLE pParticle,FLOAT fElpasedTime)
		{
			
			pParticle->vCurVel += (vWindVel - pParticle->vCurVel) * fElpasedTime;
			*vPrePosition = pParticle->vCurPos;
			pParticle->vCurPos += pParticle->vCurVel * fElpasedTime;

			FLOAT S = pParticle->fPassedTime / pParticle->fLifeTime;

			D3DXColorLerp( &pParticle->clrColor,&clrBegin,&clrEnd,S);
		}
		
		CGE_INLINE VOID
			FIREWORK::EndBehavior(LPPARTICLE pParticle)
		{
			
		}
		typedef struct PLANE
		{
			D3DXVECTOR3 vNormal;
			D3DXVECTOR3 vPoint;
			FLOAT       fBounceFactor;
			INT			nBarResult;
			PLANE      *pNext;
			INT LabelPoint(D3DXVECTOR3 vPt);
		}*LPPLANE;

		CGE_INLINE INT PLANE::LabelPoint(D3DXVECTOR3 vPt)
		{
			D3DXVECTOR3 vDirection = vPoint - vPt;
			FLOAT fResult = D3DXVec3Dot( &vDirection, &vNormal );		
			if( fResult < -0.001f )
				return PE_FRONT;				
			if( fResult >  0.001f )
				return PE_BACK;				
			return PE_ONPLANE;
		}

		typedef class PARTICLE
		{
		public:
			FLOAT		fSize;
			FLOAT       fLifeTime;
			FLOAT		fPassedTime;
			FLOAT		fVirtualTime;
			D3DXVECTOR3 vInitPos;
			D3DXVECTOR3 vCurPos;
			D3DXVECTOR3 vInitVel;
			D3DXVECTOR3 vCurVel;
			D3DXCOLOR	clrColor;	
			PARTICLE    *pNext;
		}*LPPARTICLE;

		DWORD FtoDW( FLOAT f ) { return *((DWORD*)&f); }
		
		typedef class SYSTEM_NODE
		{
			public:
				SYSTEM_NODE();
				virtual ~SYSTEM_NODE();
				FLOAT	    m_fCurrentTime;
				FLOAT		m_fLastUpdateTime;
				FLOAT		m_fIntervalue;	
				FLOAT		m_fSize;
				
				FLOAT		m_fEmissionResidue;
				LONG	    m_ParticlesAlive;
	
				
				FLOAT		m_fNumberToAddPerSecond;
				LONG		m_NumberOfLimit;

				LPPLANE		m_BarSurfaceList;
				LPPARTICLE	m_ParticleAliveList;
				LPPARTICLE	m_ParticleDeathList;

				VOID	SetBarSurface( D3DXVECTOR3 vSurfaceNormal, 
									   D3DXVECTOR3 vPoint,
									   FLOAT fBounceFactor, 
									   INT nBarResult );
				VOID	DrawAliveParticleList(LPDIRECT3DDEVICE8 DEVICE,
											  LPDIRECT3DVERTEXBUFFER8 VB);
				LONG	UpdateBehavior( FLOAT fElapsedTime );
				virtual VOID BeginBehavior(LPPARTICLE pParticle) {}
				virtual VOID CourseBehavior(D3DXVECTOR3 * vPrePosition,
											LPPARTICLE pParticle,
											FLOAT fElpasedTime) {}
				virtual VOID EndBehavior(LPPARTICLE pParticle) {}
		}*LPSYSTEM_NODE;

		CGE_INLINE SYSTEM_NODE::SYSTEM_NODE()
		{
			m_ParticlesAlive = 0;
			m_fNumberToAddPerSecond = 80.0f;
			m_fEmissionResidue = 0.0f;
			m_fCurrentTime = 0;
			m_NumberOfLimit = 1000;
			m_fLastUpdateTime = 0.0f;

			m_fIntervalue = 0.0f;
			m_fSize = 0.0f;
			m_BarSurfaceList = 0;
			m_ParticleAliveList = 0;
			m_ParticleDeathList = 0;
		}

		CGE_INLINE SYSTEM_NODE::~SYSTEM_NODE()
		{
			LPPARTICLE pParticle = NULL;
			while( m_ParticleAliveList )
			{
				pParticle = m_ParticleAliveList;
				m_ParticleAliveList = (LPPARTICLE)pParticle->pNext;
				delete pParticle;
			}
			while( m_ParticleDeathList )
			{
				pParticle = m_ParticleDeathList;
				m_ParticleDeathList = (LPPARTICLE)pParticle->pNext;
				delete pParticle;
			}
			LPPLANE	pPlane = NULL;
			while( m_BarSurfaceList )
			{
				pPlane = m_BarSurfaceList;
				m_BarSurfaceList = m_BarSurfaceList->pNext;
				delete pPlane;
			}
			
		}

		CGE_INLINE
			VOID SYSTEM_NODE::SetBarSurface( D3DXVECTOR3 vSurfaceNormal, D3DXVECTOR3 vPoint, 
						   FLOAT fBounceFactor, INT nBarResult )
		{
			LPPLANE pPlane = new PLANE;			
			pPlane->vNormal          = vSurfaceNormal;
			pPlane->vPoint           = vPoint;
			pPlane->fBounceFactor    = fBounceFactor;
			pPlane->nBarResult = nBarResult;
			pPlane->pNext = m_BarSurfaceList;
			m_BarSurfaceList = pPlane;
		}
		
		CGE_INLINE LONG SYSTEM_NODE::UpdateBehavior(FLOAT fElpasedTime)
		{
			LPPARTICLE pParticle, *ppParticle;
			LPPLANE	pPlane, *ppPlane;
			ppParticle = &m_ParticleAliveList;	

			D3DXVECTOR3 vPrePosition;

			m_fCurrentTime += fElpasedTime;

			while( *ppParticle )
			{
				pParticle = *ppParticle;

				pParticle->fPassedTime += fElpasedTime;
				if ( pParticle->fPassedTime >= pParticle->fLifeTime )
				{
					EndBehavior(m_ParticleAliveList);
					*ppParticle = pParticle->pNext;
					pParticle->pNext = m_ParticleDeathList;
					m_ParticleDeathList = pParticle;	
					m_ParticlesAlive--;					
				}
				else
				{
					CourseBehavior(&vPrePosition,pParticle,fElpasedTime);
					ppPlane = &m_BarSurfaceList;
					while( *ppPlane )
					{
						pPlane = *ppPlane;

						INT Result = pPlane->LabelPoint( pParticle->vCurPos );
						
						if( Result == PE_BACK || Result == PE_ONPLANE  )
						{
							if( pPlane->nBarResult == CR_BOUNCE )
							{
								pParticle->vCurPos = vPrePosition;
								FLOAT fBounce = pPlane->fBounceFactor;
								D3DXVECTOR3 Vn = D3DXVec3Dot( &pPlane->vNormal, &pParticle->vCurVel ) * pPlane->vNormal;
								D3DXVECTOR3 Vt = pParticle->vCurVel - Vn;
								D3DXVECTOR3 Vp = Vt - fBounce * Vn;								
								pParticle->vCurVel = Vp;
							}
							else if( pPlane->nBarResult == CR_RECYCLE )
							{
								pParticle->fPassedTime += pParticle->fLifeTime;
							}
							
							else if( pPlane->nBarResult == CR_STICK )
							{
								pParticle->vCurPos = vPrePosition;
								pParticle->vCurVel = D3DXVECTOR3(0.0f,0.0f,0.0f);
							}
						}
						
						ppPlane = &pPlane->pNext;
					}					
					ppParticle = (LPPARTICLE*)&pParticle->pNext;
				}
			}
			// Add Particles;
			FLOAT fParticlesNeed = m_fNumberToAddPerSecond * fElpasedTime + m_fEmissionResidue;
			LONG ParticlesCreated = (LONG) fParticlesNeed;
			m_fEmissionResidue = fParticlesNeed - ParticlesCreated;
			
			if ( m_fCurrentTime - m_fLastUpdateTime >= m_fIntervalue )
			{
				m_fLastUpdateTime = m_fCurrentTime;
				
				for ( LONG i = 0; i < ParticlesCreated; ++i )
				{		
					if( m_ParticlesAlive >= m_NumberOfLimit) break;//是否达到粒子限制数量		
					
					if( m_ParticleDeathList )
					{
						pParticle = m_ParticleDeathList;
						m_ParticleDeathList = pParticle->pNext;
					}
					else
					{
						if( NULL == ( pParticle = new PARTICLE ) )
							return NULL;
					}
					
					if ( pParticle != NULL )
					{
						//
						BeginBehavior(pParticle);
						pParticle->pNext = m_ParticleAliveList;
						m_ParticleAliveList = pParticle;
						m_ParticlesAlive++;
					}
				}
			}
			return m_ParticlesAlive;
		}

		CGE_INLINE VOID 
			SYSTEM_NODE::DrawAliveParticleList(LPDIRECT3DDEVICE8 DEVICE,LPDIRECT3DVERTEXBUFFER8 VB)
		{
			register INT counter = 0;
			static LONG BASE = CONST_DISCARD;
			LONG       NumberParToRender = 0;
			LPPARTICLE    pParticle = m_ParticleAliveList;
			
			LPCOLORVERTEX  VERT;
			if ( pParticle == NULL )
				return;
			
			DEVICE->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
			DEVICE->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
			DEVICE->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
			DEVICE->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE  );	
			DEVICE->SetTextureStageState(0,D3DTSS_COLOROP, D3DTOP_MODULATE);
			DEVICE->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);	
			
			DEVICE->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
			DEVICE->SetRenderState( D3DRS_POINTSCALEENABLE,  TRUE );
			DEVICE->SetRenderState( D3DRS_POINTSIZE, FtoDW(m_fSize));
			DEVICE->SetRenderState( D3DRS_POINTSIZE_MIN, FtoDW(0.00f) );
			DEVICE->SetRenderState( D3DRS_POINTSCALE_A,  FtoDW(0.00f) );
			DEVICE->SetRenderState( D3DRS_POINTSCALE_B,  FtoDW(0.00f) );
			DEVICE->SetRenderState( D3DRS_POINTSCALE_C,  FtoDW(1.00f) );
			DEVICE->SetVertexShader( COLORVERTEX::FVF_FLAG );
			DEVICE->SetStreamSource( 0, VB ,sizeof(COLORVERTEX));
			
			BASE += CONST_FLUSH;
			if(BASE >= CONST_DISCARD)
				BASE = 0;
			
			if(FAILED(VB->Lock(BASE * sizeof(COLORVERTEX), CONST_FLUSH * sizeof(COLORVERTEX),
				(BYTE **) &VERT, BASE ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD)))
			{
				goto finally;
			}	
			
			while( pParticle )
			{
				D3DXVECTOR3 vPos(pParticle->vCurPos);
				D3DXVECTOR3 vVel(pParticle->vCurVel);
				
				FLOAT       fLengthSq = D3DXVec3LengthSq(&vVel);
				UINT        nStep = 1;
				/*
				if( fLengthSq < 1.0f )        nStep = 2;
				else if( fLengthSq <  4.00f ) nStep = 3;
				else if( fLengthSq <  9.00f ) nStep = 4;
				else if( fLengthSq < 12.25f ) nStep = 5;
				else if( fLengthSq < 16.00f ) nStep = 6;
				else if( fLengthSq < 20.25f ) nStep = 7;
				else                          nStep = 8;
				
				vVel *= -0.04f / (FLOAT)nStep;
				*/
				
				for( counter = 0; counter < nStep; counter++ )
				{
					VERT->dvX = vPos.x;
					VERT->dvY = vPos.y;
					VERT->dvZ = vPos.z;
					VERT->dcColor = (DWORD)pParticle->clrColor;
					VERT++;
					if( ++NumberParToRender == CONST_FLUSH )
					{	
						VB->Unlock();	
						if(FAILED(DEVICE->DrawPrimitive( D3DPT_POINTLIST, BASE, NumberParToRender)))
							goto finally;
						
						BASE += CONST_FLUSH;
						
						if(BASE >= CONST_DISCARD)
							BASE = 0;
						
						if(FAILED(VB->Lock(BASE * sizeof(COLORVERTEX), CONST_FLUSH * sizeof(COLORVERTEX),
							(BYTE **) &VERT, BASE ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD)))
						{
							goto finally;
						}
						NumberParToRender = 0;
					}
					
				//	vPos += vVel;
				}
				
				pParticle = pParticle->pNext;
			}
			
			VB->Unlock();
			
			// 渲染
			if( NumberParToRender )
			{
				if(FAILED(DEVICE->DrawPrimitive( D3DPT_POINTLIST, BASE, NumberParToRender )))
					goto finally;
			}
			// 重置渲染状态
			finally:			
			DEVICE->SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );
			DEVICE->SetRenderState( D3DRS_POINTSCALEENABLE,  FALSE );
			DEVICE->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
			DEVICE->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
		}
	}
}
#endif
#endif

⌨️ 快捷键说明

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