📄 firework.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 + -