インベーダーゲームを作ってみる(5)状態遷移

インベーダーゲームに登場するオブジェクトは、これまでに説明したインベーダーと陣地を除くと
①自機
②UFO
③自機の弾
④敵の弾
があります。

これらのオブジェクトはいずれも、
出現→移動→(爆発)→消滅→出現・・・
という状態遷移をします。

プログラム中でも、オブジェクトごとに細かい違いはあるものの、大体この遷移に沿っています。
流れを把握する上で役立つと思いますので、これらの状態遷移を簡単に解説しておきます。

オブジェクトの基本的な状態は以下の2つです。

・READY
オブジェクトが画面に出現していない状態です。
トリガー(たとえば自機弾なら、発射ボタンを押す)によってACTIVEへ移行します。
移行する前に初期設定(座標の設定など)が必要です。

・ACTIVE
オブジェクトが画面に出現し、動くことができる状態です。
ACTIVEなオブジェクトの処理はオブジェクトの種類に依存します。
オブジェクトの消滅(たとえばUFOが画面端へ到達したとき)や爆発により、他の状態へ移行します。
どの状態へ移行しても、消滅したオブジェクトは最終的にREADYへ移行します。

iv09.png

ACTIVE状態からの移行は、以下の3つのパターンがあります。

(1)直接READYへ移行する
オブジェクトを画面から消去済みの場合、単にREADYへ移行します。

(2)RECYCLEへ移行する
次の画面更新のタイミングでオブジェクトを画面から消去する必要がある場合、RECYCLEへ移行します。
RECYCLE状態では、オブジェクトを画面から消去し、READYへ移行します。

(3)EXPLOSIONへ移行する
爆発のイメージを描画する場合はEXPLOSIONへ移行します。
プログラム内では、オブジェクトによって状態の名称は異なりますが、意味合いは同じです。
EXPLOSION状態はオブジェクトの爆発イメージを画面に描画後、タイマーでRECYCLEへ移行します。

状態はプログラム内では整数で表現しており、
EXPLOSION > RECYCLE = 1 > ACTIVE = 0 > READY = -1
となっています。
この整数はEXPLOSIONからRECYCLEへのカウントダウンタイマーを兼ねており(手抜き)、EXPLOSION > 状態 > RECYCLEのときは、ループ内で1ずつカウントダウンしていきます。

オブジェクトの状態遷移は、主に オブジェクト名_update() という関数で処理しています。
例としてufo_update()は以下のようになっています。

void ufo_update(struct ufo_t *u) {
switch (u->status) {
case OBJ_ACTIVE:
if (u->wait_ctr++ > UFO_WAIT) {
u->wait_ctr = 0;
ufo_move(u);
}
break;
case OBJ_READY:
ufo_appear(u);
break;
case OBJ_RECYCLE:
ufo_erase(u);
u->status = OBJ_READY;
break;
case UFO_EXPLOSION:
DRAW_BITMAP(u->x, UFO_TOP, ufo_score_img[u->img_idx], UFO_W, UFO_H, WHITE);
default:
u->status--;
}
}

statusが状態を表す変数です。
UFOは毎秒60回動かすと早すぎるので、wait_ctrでウエイトを入れています。
ufo_appear()はUFO出現条件が整っているかチェックし、整っていればUFOを出現させます。
UFO_EXPLOSIONでの処理は、爆発イメージを描画します。
UFO_EXPLOSIONからOBJ_RECYCLEまでカウントダウンする動作はdefaultの中で行っています。
なお、UFO_EXPLOSIONでの処理は最後にbreakが付いていないので、u->status–;まで実行されることに注意してください。

コメント