具體的粒子系統:雪,焰火,粒子槍

現在讓我們開始從PSystem製作幾個具體的粒子系統。這些系統已經做了簡單的説明和處理,不需要PSystem類那樣的靈活的屬性。我們實現雪,火焰和槍粒子系統。這些系統的命名漂亮的計算系統他們的模型。雪系統模型落下雪花,火焰系統發出火苗。粒子槍從攝影機位置在鍵盤按下,到火焰的位置;這是它看起來我們的火苗粒子子彈和在遊戲中使用基本的粒子系統。

注意,通常的完成代碼項目説明這些系統可以被在這章。 Note: As usual,the complete code projects illustrating these systems can be found in the companion files for this chapter.

圖14.2:一個雪花飛舞的展示。

雪花系統的類定義:

class Snow:public PSystem{ public: Snow(d3d::BoundingBox* boundingBox,int numParticles); void resetParticle(Attribute* attribute); void update(float timeDelta); }

評論:記住簡單的接口在雪花系統裏,因為父類照顧了大部分的工作。事實上,所有三個粒子系統在本章實現上都有簡單的接口和容易實現的關係。

構造一個範圍盒的指針和一定數量的粒子。這個範圍盒子描述了秋天的雪花。如果雪花出了範圍,他們就被殺死和respawned.這樣,雪花系統總是有一部分粒子是活動的。構造的代碼如下:

Snow::Snow(d3d::BoundingBox* boundingBox,int numParticles) { boundingBox = *boundingBox; size = 0.8f; vbSize = 2048; vbOffset = 0; vbBatchSize = 512; for(int i=0;i;i++)>

我們也指定了頂點緩衝和片段大小,和開始的偏移量。

resetParticle方法創建了x和z座標的隨機的範圍盒子且在Y座標上在頂端。它給雪花速度和向下落。學花是白色的:

void Snow::resetParticle(Attribute* attribute) { attribute->_isAlive = true; d3d::GetRandomVector( &attribute->position, &boundingBox,min, &_boundingBox,_max); attribute->_position.y = _boundingbox._max.y; attribute->velocity.x = d3d::GetRandomFloat(0.0f,1.0f)*-3.0f; attribute->velocity.y = d3d::GetRandomFloat(0.0f,1.0f)*-10.0f; attribute->velocity.z = 0.0f; attribute->color = d3d::WHITE; }

更新方法更新粒子的位置然後測試,如果離子超過了範圍盒子。如果它已經超過範圍盒子,我們重畫它。

void Snow::update(float timeDelta){ std::list::iterator i; for(i = particles.begin();i!=particles.end();i++) { i->position += i->velocity * timeDelta; if(boundingBox.isPointInside(i->position) == false) { resetParticle(&(*i)); } } }

火焰粒子系統類被定義為:

class Firework:public PSystem{ public: Firework(D3DXVECTOR3* origin,int numParticles); void resetParticle(Attribute* attribute); void update(float timeDelta); void preRender(); void postRender(); };

構造函數在起初系統和粒子系統。這種情況下,原點系統將使用爆炸效果。

resetParticle方法初始化粒子到原點和在球上創建。每個粒子在火焰系統隨機顏色。最後,我們在兩次定義粒子。

void Firework::resetParticle(Attribute* attribute){ attribute->isAlive = true; attribute->position = origin; D3DXVECTOR3 min = D3DXVECTOR3(-1.0f,-1.0f,-1.0f); D3DXVECTOR3 max = D3DXVECTOR3(1.0f,1.0f,1.0f); d3d::GetRandomVector( &attribute->velocity, &min, &max); D3DXVec3Normalize( &attribute->velocity, &attribute->velocity); attribute->velocity *= 100.0f; attribute->color = D3DXCOLOR( d3d::GetRandomFloat(0.0f,1.0f), d3d::GetRandomFloat(0.0f,1.0f), d3d::GetRandomFloat(0.0f,1.0f), 1.0f); attribute->age = 0.0f; attribute->lifeTime = 2.0f; }

更新方法更新每個像素和被殺粒子的位置指定在生命器。注意這個系統不要移動死的粒子。我們這麼做因為當我們想創建一個新的火眼,我們將簡單的重新設置存在的死的火眼。這被保存在新的和粒子頻率裏。

void Firework::update(float timeDelta){ std::list::iterator i; for(i=particles.begin();i!=particles.end();i++){ if(i->isAlive) { i->position += i->velocity * timeDelta; i->age += timeDelta; if(i->age > i->lifeTime) i->isAlive = false; } } }

火焰系統使用不同的混合因素在渲染過程中。更進一步的關閉寫入到深度緩衝。我們容易的改變從默認重寫PSystem::preRender和postRender方法的因素。這個重寫執行為:

void Firework::preRender(){ PSystem::preRender(); device->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE); device->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE); device->SetRenderState(D3DRS_ZWRITEENABLE,false); } void Firework::postRender(){ PSystem::postRender(); device->SetRenderState(D3DRS_ZWRITEENABLE,true); }

注意:兩個版本調用父類版本。這樣,我們再次調用父類的最小指定的改變。

最後一個槍粒子略 譯自《Introduction to 3D Programming with DirectX 9》 microsoftxiao

終於譯完了,該死的英語。