首先,我的粒子是采取广告板的方式来表现的,因为这样才能给我实现多样化粒子系统的能力.
具体做法是,将广告版看成是Leaf,而粒子系统看成Composite,那么利用Composite模式既可以让广告板单独使用,又可以用多个广告板组成复杂的粒子系统,这是灵活性1.
另外,我们知道Composite模式是可以组成一个树型结构的,那么粒子系统需要树型结构吗,答案是肯定的,比如你模拟火,火的粒子系统是树根,而象由火产生的烟雾等,都可以看成火的儿子.所以灵活性之二就是可以自由的抽象出象这样的结构.
下面我用控制台程序模拟了这一过程:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Spirit3DComponent{
public:
Spirit3DComponent(){};
Spirit3DComponent( string name ) : m_name( name ){};
virtual void Add( Spirit3DComponent* comPtr ) = 0;
virtual void Remove( Spirit3DComponent* comPtr ) = 0;
virtual void Display() = 0;
string GetName(){
return m_name;
}
protected:
string m_name;
};
class ParticleSystem : public Spirit3DComponent{
//输出名字
class DisplayName{
public:
void operator()( Spirit3DComponent* p ){
if( p ){
p->Display();
}
}
};
//删除谓词
class DeletePtr{
public:
void operator()( Spirit3DComponent* p ){
if( p ){
delete p;
}
}
};
//移出谓词
class RemovePtr{
public:
RemovePtr( Spirit3DComponent* p ) : m_p( p ){}
bool operator()( Spirit3DComponent* p ){
if( p->GetName() == m_p->GetName() ){
return true;
}
else{
return false;
}
}
protected:
Spirit3DComponent* m_p;
};
public:
typedef vector< Spirit3DComponent* > compositevec;
typedef compositevec::iterator IteratorCom;
typedef compositevec::const_iterator ConstIteratorCom;
ParticleSystem(){};
~ParticleSystem(){
for_each( m_comVec.begin(), m_comVec.end(), DeletePtr() );
}
ParticleSystem( string name ) : Spirit3DComponent( name ){};
virtual void Add( Spirit3DComponent* comPtr ){
m_comVec.push_back( comPtr );
}
virtual void Remove( Spirit3DComponent* comPtr ){
IteratorCom newEnd = remove_if( m_comVec.begin(), m_comVec.end(), RemovePtr( comPtr ) );
for( IteratorCom i = newEnd; newEnd != m_comVec.end(); ++i ){
m_comVec.erase( i++ );
}
}
virtual void Display(){
cout<<"例子系统属于:"<<m_name<<endl;
cout<<"组成部分:"<<endl;
if( m_comVec.empty() ){
cout<<"无"<<endl;
}
else{
for_each( m_comVec.begin(), m_comVec.end(), DisplayName() );
}
cout<<endl;
}
protected:
compositevec m_comVec;
};
class BillBoard : public Spirit3DComponent{
public:
BillBoard(){};
BillBoard( string name ) : Spirit3DComponent( name ){};
virtual void Add( Spirit3DComponent* comPtr ){}
virtual void Remove( Spirit3DComponent* comPtr ){}
virtual void Display(){
cout<<"粒子名:"<<m_name<<endl;
}
};
int main(){
Spirit3DComponent* cSmoke = new ParticleSystem( "烟" );
cSmoke->Add( new BillBoard( "烟" ) );
cSmoke->Add( new BillBoard( "烟" ) );
cSmoke->Display();
Spirit3DComponent* cFire = new ParticleSystem( "火" );
cFire->Add( new BillBoard( "火" ) );
cFire->Add( new BillBoard( "火" ) );
cFire->Add( cSmoke );
cFire->Display();
return 0;
}