タスクシステムと描画管理
タスクマネージャの実装についてid:a_little_bit:20050323氏がNested Classというテクニックを紹介されている。なるほどこんなテクニックもあるのか、凄い。というわけでタスクシステムと描画管理について考えてみる。
-
-
-
-
- ここから完全にチラシの裏。
-
-
-
今のところ漏れはこういう実装にしている。
class CTaskBase { virtual void onUpdate() = 0; virtual void isVisible(); virtual int getDrawPriority(); virtual void onDraw(); .... }; class CTaskManager { void callUpdate(); void callDraw(); vector<CTaskBase*> taskList; vector<CTaskBase*> drawList; ... };
CTaskManager::callUpdate()はtaskListに登録されている全てのクラスのonUpdate()を呼び出す。この時点でisVisible()がtrueであるタスクはdrawListに登録される。
CTaskManager::callDraw()でdrawListに登録されたタスクが描画優先順でソートされてCTaskBase::onDraw()が呼び出され、drawListは消去されるという仕組み。
気に入らないのは、CTaskBase::onDraw()やisVisible()などの関数が増えてしまうこと。描画だけならまだしも、衝突管理やタスク間メッセージのやりとりまで盛り込んで行くと、CTaskBaseやCTaskControlがどんどん肥大化していく。そもそもタスクを管理するのが仕事のCTaskControlが描画順の管理まで行うのは正しい設計ではないのでは?
そこで描画管理を専門に行うCDrawControlTaskというタスクを新たに作ることを考えた。描画インターフェースクラスであるIDrawableも新たに作る。
class IDrawable { virtual void onDraw() = 0; virtual int getDrawPriority() = 0; }; class CDrawControlTask: public CTaskBase { void addDrawable(IDrawable*); vector<IDrawable*> drawList; }; class CMyShip : public CTaskBase, public IDrawable { virtual void onUpdate(); virtual void onDraw(); .... };
CDrawControlTaskは特殊なシステムタスクとして、実行フェイズを全てのタスクの最後にずらしてやる必要がある。こうすれば、CTaskControlは描画順の管理から開放されるし、CTaskBaseも余計なメンバを持たずに済む。
多重継承はプログラムの見通しが悪くなりそうで、あんまり好きでなかったけれど、こういう使い方はいいかも。衝突管理やメッセージの送受信も似たような設計でいけるかな。