シューティングゲーム制作基礎講座その1

of自分by自分for自分。
どのくらい続くかっていうかそもそもその2があるのかも不明ですが、とりあえず今回はシューティングに限らずアクションゲーム全般にかかわる事項を。

メインループでの処理

ゲームのメイン処理は大きく分けて次の3つのフェーズからなる。

  1. キャラクタの移動
  2. 描画
  3. 当たり判定

ここでまず注意しなければならないのは、各処理フェーズを全てのキャラに対して実行すること。つまり、全キャラの移動処理をしてから全キャラを描画し、全キャラの当たり判定を行う、という感じ。キャラAについて移動し、描画し、当たり判定を行い、次にキャラBについて・・・とやっていくと、Aの当たり判定の時点ではAとBが当たっていたのに、Bの当たり判定の時点ではBが移動したので当たっていない、というふうに1フレーム内で整合性がとれなくなる。また後述の当たり判定の重複にも絡んでくるので、基本だが注意。
それから、処理はなるべく上の順番でやること。もし、移動→当たり判定→描画という順番だと、まず内部で座標の移動が行われ、それから内部で当たり判定が行われる。この時点でもし自機が弾に当たっていたら、もちろん自機は撃墜となる。しかしこの時点で画面に描画されているのは移動が起こる前のフレーム、つまり自機と弾が当たっていない状態の画面である。そして次の描画処理では自機が撃墜された画面が映るだろう。これではプレイヤーには、「弾には当たっていないのにいきなり墜ちた」ように見えてしまう。だから処理の順番は、移動して、自機と弾が当たっているところを描画し、納得させたところで当たり判定を行う、というのが厳密には正しい。しかし弾と自機が当たってるところが描画されるのはたったの1フレームだから、普通の人はどちらにしろ見えないかもしれない。まあそれでも、低速な弾なら「ああ当たりそうだな」ってのが数フレーム前からわかるだろうからいいが、高速な弾(特に単発のもの)はちゃんと当たったところを描画しておかないと、高レベルなプレイヤーの方々から苦情が来るのではないかと思われるが実際のところどうなんだろう。
高速弾が出てきたところでそれにまつわる話をもう一つ。最近多い、自機や弾の当たり判定が異常に小さい(数ドット)ゲームで、かつ弾が高速の場合に起こりうる現象がある。そう、自機と弾の相対速度が当たり判定より大きいと、どうみてもすり抜けです。本当にありがとうございました。になる。このような場合は1フレーム前の座標との間に線分を引いて、その交差判定をしたりして対処する必要が出てくる。正確にやるには交差角度なども考慮しなければならないため、大変厄介なことになる。まあこういう現象がおきない程度のバランスにするのが望ましいかな。

当たり判定について

移動と描画は全てのキャラの「存在」について行う処理である。当たり判定については、そのようにとることもできるが、2体のキャラの「関係」に対して行う処理であると考えることもできる。したがって、「存在」でとらえて全てのキャラについて他のキャラと当たっているか判定し、当たっていたら自分の「当たりました処理」を行う方法と、「関係」でとらえて片方のキャラだけに当たり判定を行い、当たっていたら両者の「当たりました処理」を行う方法の二つがある。
わかりにくいかもしれないので具体的に。まず今、自機、敵機、自機のショット、敵機の弾の4種類のキャラクタがいるとする。前者の方法を採るなら、最初に自機について調べる。ショットと自機は普通当たらないだろうから、敵機と弾に当たっているか判定を行う。そして当たっていたら、自機のダメージや撃墜処理を行う。当たった相手の処理はこの段階では行わない。同じように敵機について、ショットについて、弾について、全て総当りで判定を行う。
しかしよく考えるとこの方法では不具合が生じる。ある敵機が自機のショットに当たったとしよう。敵機の当たり判定でショットに当たっていたので、敵機は撃墜、消滅となる。しかしそうするとその相手のショットの当たり判定の時には、相手の敵機はすでに消滅しているので、当たっていないことになり、ショットは消えず敵機を貫通してしまう。
つまりこの方法を採る場合、キャラの生存判定は1フレームの間ずっと同じ状態で保持しておき、全ての当たり判定が終わってから初めて消滅させなければならない。そうすると1つのショットが複数の敵機を落とすという事態が生じうる。これを許容するかどうかは製作者の意図によるだろう。しかしとにかく設計がややこしくなりそうなのでこの方法は好ましくないように思える(実際自分が使っているのは後者の方法)。
そこで後者の方法をとってみるとどうか。まず自機について判定する。全ての敵機と弾について当たっているかどうか判定し、当たっていたら自機と敵機or弾の両方の「当たりました処理」を呼び出す。次にショットについて、敵機と弾に対して同じように判定する。これで終了。
これなら前者の方法で起きるような問題は生じないが、一つだけよく考えたほうがいいのは処理するキャラの順番。これはあるキャラが2体以上のキャラに当たっている場合に影響する。たとえばある敵機がショットと自機の両方に接触していたとき、自機を先に処理すれば、(ルールはゲームによるだろうが)自機と敵機が落ちて、ショットは当たらず素通りになる。逆にショットを先に処理すると敵機が撃墜されてショットが消え、自機は生存する。このあたりの調整はゲームによりけりだろうが、まあ細かく作るなら気をつけるべきだろう。
今回はこんなところで。文章だらけで読みづらいなあ・・・。