パラレル・フォースではスプライト関連処理として下記のクラスを用意しています。
(多分そのうちまた増えますが、現状はこんな感じ。
- 外部公開クラス
- ISprite: スプライトの基底クラス(インタフェース)
- FillSprite: 単一色の塗りつぶしスプライト
- ImageSprite: イメージ描画スプライト
- TextSprite: テキスト描画スプライト
- SpriteManager: スプライト管理
- Screen: スクリーン管理
- ISprite: スプライトの基底クラス(インタフェース)
- 内部管理クラス
- ScreenDrawer: スクリーン分割領域の描画
- SpriteResourceHolder: 非同期描画のためのリソース延命
- FpsTimer: FPS タイマー
Screen クラスでは描画フレーム管理を行っており、フレーム単位のタスク処理を外部から登録することができます。
typedef std::function<const bool (Screen&)> ScreenTaskProc; class Screen { void addTask(const std::int32_t iTaskID, ScreenTaskProc iTaskProc); void removeTask(const std::int32_t iTaskID); };
登録すると FPS に合わせて登録したファンクタがコールバックされます。C++0x のおかげで、タスク登録時のコードの書き方がちょっと変わりました。C++0x 前後でクライアント コードを比較してみます。
// C++0x 前 enum { screenTask1, screenTask2 }; struct task1 { const bool operator(Screen& iScreen) const { /* do task 1. */ } }; struct task2 { const bool operator(Screen& iScreen) const { /* do task 2. */ } }; void testTask() { aScreen->addTask(screenTask1, task1()); aScreen->addTask(screenTask2, task2()); }
C++0x より前だと、ファンクタである task1, task2 というシンボルが出現し、これにより『タスク』それ自体が強調されており、本来表現したい『タスクを登録する』という処理があまり伝わってきません。
C++0x だと、これが下記のように変わります。
// C++0x enum { screenTask1, screenTask2 }; void testTask() { aScreen->addTask(screenTask1, [=](Screen& iScreen) -> const bool { /* do task 1. */ }); aScreen->addTask(screenTask2, [=](Screen& iScreen) -> const bool { /* do task 2. */ }); }
C++0x だとラムダ式として無名ファンクタを定義できるので、ファンクタのシンボルが不要になり、『タスク』それ自体の強調が回避されます。まぁ、こまかいこと差っぴいても、すごくすっきりします。ラムダ式って素敵。
で、これだけでもすっきりするのですが、繰り返し登録するようなタスクは下記のように書くようにしています。
enum { screenTask1, screenTask2 }; void addTask1() { aScreen->addTask(screenTask1, [=](Screen& iScreen) -> const bool { /* do task 1. */ }); } void addTask2() { aScreen->addTask(screenTask2, [=](Screen& iScreen) -> const bool { /* do task 2. */ }); } void testTask() { addTask1(); addTask2(); }
これでタスク登録の表現が下記のように変わりました。
タスク登録の際、C++0x のおかげで本当に書きたい処理が書けるようになった気がします。考えすぎかな。