タスクシステム4
タスク同士の当たり判定
ここが超重要です。はいはいテストに出ますよー(何のテストじゃ)
例えば、ブロック崩し(こればっかですね)において、
以下のタスクがぶつかった場合、何らかのやり取りを考えなければなりません。
- ボールvs壁
- ボールvsパドル
- ボールvsブロック
1,2の場合は、ボール自身が跳ね返るだけですが、
3の場合、ブロックを破壊する必要があります。
ただ、全ての場合において、
- どれにぶつかったのか?
- どれと跳ね返るのか?
- どれを破壊するのか?
ということを調べる必要がありますよね。
ということで、これを解決するためには、
タスクに「グループ属性」を追加します。
// グループ列挙 enum GROUP { PADOL = 0x01, BALL = 0x02, BLOCK = 0x04, WALL = 0x08, }; struct TCB { ・ ・ GROUP group; // グループ属性 ・ ・ };
これにより、チェックしたいタスクを
IsHit(ball->rect, (GROUP)(PADOL | BLOCK | WALL));
として渡し、
void IsHit(RECT rect, GROUP group) { // タスクリストを全チェック while(taskList->next != NULL) { ・ ・ // パドルとぶつかっているか? if(taskList->group == (group & PADOL)) { // ぶつかっていたら、ボールの移動量を反転する } ・ ・ } }
というようにチェックを行うことができます。
最適化の方針として、タスクリストを、
グループごとに分けるという方法があります。
例えば、シューティングゲームなら、
- 自弾タスクリスト
- 敵機タスクリスト
- 敵弾タスクリスト
といった感じです。
これで、呼び出すタスクリストを節約できるので、
高速化が計れるわけです。
描画関数の扱いについて
これも結構重要です。
たとえば、実行関数ポインタの中で描画を行うものとします。
と、これはこれで楽なのですが、以下の問題があります。
- Zバッファ
- 描画の処理落ち
Zバッファというのは、「描画順」のことです。
例えば、シューティングゲームでは、
自機→自弾→敵機→敵弾
の順番で描画を行う必要があります
(実装により多少順番が変わるかもしれませんが…(∀`;
というのも最近の弾避けシューティングで、
自機や自弾の下に敵弾が隠れてしまったら、
間違いなくシューターから暴動が起こります(きっと)
ということで、「描画順」はとっても重要なのですが、
現在のタスクにはそういった指定はないですよね。
そこで、実行関数ポインタから描画関数を分離して、
「グループ」別に描画を行うようにすることで、
Zバッファの問題を回避します。
あと、描画の処理落ちということですが、
重い処理を行う場合には、描画の処理を省略して、
処理を軽くしたいというときがあります。
あるはずです。あるにちがいありません。
きっと、、、。
そういう場合に、描画関数を分離しておくと、
描画処理を省略できるわけです。
その他の機能
タスクの優先順位
タスクを実行する優先順位を属性に持たせます。
例えば、、、。
親子タスク
これです。
これが優先順位に関係あります。
と、その前に親子タスクの説明。
「親子タスク」とは、例えばシューティングにおける、
ボスの本体と手足です。
本体がやられると、手足も爆発します。
この場合、本体が「親」、手足が「子」になります。
この様なつながりを「親子タスク」といいます。
で、優先順位の話に戻ると、
あるフレームで、本体を破壊しました。
そして通常、そのフレーム内で手足も破壊されます。
しかし、手足タスクを先に実行してしまったとします。
そうすると、手足タスクが爆発するのは次フレームになってしまいます。
これは不自然ですよね。
ということで、本体タスクの優先順位を高くする必要があるわけです。
これが優先順位の必要性です。
全タスクの削除
これはあると便利ですね。
例えば、達人ボム発動時とか、ステージクリア時に使えますね。
(つづく)