「えぐぜりにゃ〜」ソース解説
色々と勉強になった「えぐぜりにゃ〜」のソースをkenmoなりに解説してみます。
シーンの状態遷移
まずはシーンの遷移について解説します。
34行目〜41行目の定数に注目します。
// 遷移状態ステート #define STATE_TITLE_INIT 0 #define STATE_TITLE 1 #define STATE_GAME_INIT 2 #define STATE_GAME 3 #define STATE_OVER_INIT 4 #define STATE_OVER 5 #define STATE_QUIT 99
これらはシーンを切り替える状態遷移の定数です。
変数「state」にいずれかの値が入り、各状態に応じて処理を分岐していきます。
遷移図としては、以下のようになります。
エントリポイントは、177行目の
state = STATE_TITLE_INIT
ですね。
以降、*mainloopにジャンプし、
repeat ・ ・ ・ // メインルーチン if (state == STATE_TITLE_INIT) :gosub *statetitleinit if (state == STATE_TITLE) :gosub *statetitle if (state == STATE_GAME_INIT) :gosub *stategameinit if (state == STATE_GAME) :gosub *stategame if (state == STATE_OVER_INIT) :gosub *stateoverinit if (state == STATE_OVER) :gosub *stateover if (state == STATE_QUIT) :break ・ ・ ・ loop
該当する処理(サブルーチン)を呼び出し、少しの処理を行い、
何らかの変化があった場合に、状態(state)を遷移させていきます。
例えば、stateがSTATE_TITLE_INITであった場合、
ラベル*statetitleinitを呼び出し、「タイトル画面の初期化」をして、
またこのループに帰ってきます。
さて、この状態遷移の方法を知らない人にとっては、
「なんだか面倒なことをしているなー」
という印象があるかもしれません。
では、なぜこのような面倒なことをするのかというと、
- シーンの区切りがハッキリする
- シーンの追加・削除がカンタン!
というメリットがあるからです。
例えば、ゲームオーバー時に「ハイスコアを記録・表示するシーン」を追加するとします。
その場合は、
- stateがSTATE_OVERのときの遷移先を「ハイスコアを記録・表示するシーン」にする
- そのシーンの遷移先をSTATE_TITLE_INITにする
という手順を踏むことで実現できます。
このように「遷移先の付け替え」がカンタンになる、
というのが、この方法の利点です。
他の部分でも、この方法は使われています。
それは96〜110行目にはアンカーの状態遷移定数で、変数「anchor_state」に代入されます。
// アンカー遷移状態 #define ANCHOR_STATE_STANDBY 1 #define ANCHOR_STATE_THROW 2 #define ANCHOR_STATE_GRAB 3 #define ANCHOR_STATE_RETURN 4
ゲームオブジェクト
ゲームオブジェクトには、以下のものがあります。
変数名 | オブジェクト | 配列 |
---|---|---|
mychar | プレイヤー | × |
anchor | アンカー | × |
enemy | 敵 | ○ |
grabenemy | 掴んだ敵 | × |
threnemy | 投げられた敵 | ○ |
effect | エフェクト | ○ |
画面上に複数表示する必要のあるものは、配列になっています。
各オブジェクトが持つ値の一覧です。
(※ソース上の変数名は「オブジェクト変数名」+「_」+「値の変数名」になります)
変数名 | 意味 | mychar | anchor | enemy | grabenemy | threnemy | effect |
---|---|---|---|---|---|---|---|
x | X座標 | ○ | ○ | ○ | ○ | ○ | ○ |
y | Y座標 | ○ | ○ | ○ | ○ | ○ | ○ |
sx | X移動量 | ○ | ○ | ○ | × | ○ | ○ |
sy | Y移動量 | ○ | ○ | ○ | × | ○ | ○ |
ssx | X慣性 | ○ | × | × | × | × | × |
ssy | Y慣性 | ○ | × | × | × | × | × |
size | 大きさ | × | × | × | × | × | ○ |
rotate | 回転角度 | × | × | ○ | ○ | ○ | ○ |
gr_rotate | 画像の回転角度 | ○ | × | × | × | × | × |
anc_rotate | アンカーの回転角度 | ○ | × | × | × | × | × |
timer | タイマー | × | × | ○ | × | × | ○ |
dam_timer | ダメージタイマー | ○ | × | × | × | × | × |
life | 体力 | ○ | × | ○ | ○ | ○ | × |
type | 種類 | × | × | ○ | ○ | ○ | × |
state | 状態 | × | ○ | × | × | × | × |
flag | フラグ | × | × | ○ | × | × | × |
それぞれの値については、ほとんど「意味」のままなのですが、
すこしだけ詳細を解説します。
「x,y」は中心座標です。
そして、「sx,sy」は移動量です。
それぞれの移動関数で「x,y」に足しこまれます。
(※移動関数については次の項で解説します)
「ssx,ssy」はプレイヤーを操作したときに少しだけ発生する慣性です。
操作したときに、フワッとするのは、この変数があるためです。
「timer」というは、敵が持っているカウンターのようなもので、移動関数を呼ぶたびにカウントされます。
この数値が一定の値になるたびに、攻撃方法や移動パターンが変化します。
「dam_timer」というのは、連続でダメージを食らって秒殺されないようにするための変数です。
ダメージを受けたときに、このタイマーがセットされ、移動関数を呼ぶたびに減少します。
これが1以上の場合は、敵にぶつかっても体力が減らないようになっています。
最後の「flag」は牛乳とプリンの行動パターン格納するフラグです。
これにより、4wayやにんじんショットを切り替えたりしています。
ゲームオブジェクトの移動関数
とりあえず、ざっくりと解説します。
sx,syを持っているオブジェクト(grabenemy以外)は、それぞれ移動関数を持っています。
「moveXXXX」とついているラベルがそれです。
これは、「各オブジェクトに関連する処理」を実行する関数です。
移動関数は主に以下の処理を行います。
- オブジェクトの移動
- 他のオブジェクトとの当たり判定
- 状態遷移
オブジェクトの移動
オブジェクトの移動では、主に、
- 「中心座標」に「移動量」を足しこむ
- 「移動量」の減衰
- 「キー入力」に対応する移動
を行っています。
他のオブジェクトとの当たり判定
以下のような関係があります。
(※横から見ていき、○で当たり判定を行っています)
  | mychar | anchor | enemy | threnemy | grabenemy |
---|---|---|---|---|---|
mychar | − | − | ○ | − | − |
anchor | − | − | ○ | − | − |
enemy | − | − | − | ○ | − |
threnemy | − | − | − | − | − |
grabenemy | − | − | ○ | − | − |
状態遷移
プレイヤーの状態遷移は特にありません。
アンカーについては、定数で宣言されているように4種類の状態遷移があります。
これはゲームクリエーターズバイブルにのっている状態遷移の書き方です。
四角が「状態」で、丸が「外部からの入力」になります。
例えば、「待機」状態においてボタン1の押下があった場合、
赤い線を辿って「射出」状態になる、といった感じです。
敵は「enemy」「threnemy」「grabenemy」という別オブジェクト扱いになっていますが、
- 通常状態
- 掴まれ状態
- 投げられ状態