●ビートバイスのシューティングアルゴリズム | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
第五回目は当初の予定を変更してビートバイスのシューティング部分のアルゴリズムについて解説していくことにいたします。風雅システムはリボルティーIIというシューティンゲームでデビューしましたから、ある程度のノウハウは存在していましたが、横スクロールシューティングとしては初の作品でした。(実際にはOEMとして提供したゲーム中にもあり、ビートバイスで3作目になります。) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
非ビットマップと非スプライト | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
今となっては「しなくてよい苦労」となっているのが、V-RAMの構造とスプライトに関する仕様による問題の回避です。第二回の高速横スクロールやGRCGの項でも触れましたが、PC-9801という機種のV-RAMは1ドットが1バイトや1ワードに対応している「ビットマップタイプ」とは異なり、1ドットが1ビットに対応したモノクロ画面が重なっている「プレーンタイプ」でした。このためグラフィックパターンを1ドット単位で高速に移動して見せることが困難でした。(今にして思えば)非力なCPUであったため、ビートバイスでは1ドット単位での移動をあきらめ、横方向8ドット、縦方向4ドット(※1)を移動の最小単位としました。 この点、当時のファミコンやMSX、SORD-M5、RX-78などのスプライトをハードウェア的に持つ機種では楽なものです。スプライトとは「妖精」という意味が一般的ですが、この場合は「移動画面」という意味です。特定のサイズの移動画面がいくつも用意されており、この画面に機体や弾丸、ビームなどのパターンをあらかじめ描画(登録)しておくのです。すると、この移動画面は背景となる画面の任意の場所にハードウェア的に合成表示可能なため、縦横それぞれ1バイト(0〜255)の座標を書き換えるだけで、グラフィックパターンを移動させることができるというわけです。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
余談になりますが、実際にはスプライトはいろいろな制約も受けます。サイズが8×8・16×16・32×32程度であり「デカキャラ」には使いにくいとか、色数が2色〜8色程度と少なく、2枚以上重ねて使わないと綺麗に見えないとか、同一捜査線上に一定の数を超えて表示されようとすると超えた分が消えてしまうとかです。しかし、これらの制約もDirectXのDirectDraw(3D)の一般化で無に等しくなっています。ただし、DirectXによるスプライトは「疑似スプライト」であり、完全にハードウェアで実現しているものではありません。でも、この方が理想的なスプライトではありますが。(^_^) ちなみに富士通のFM-TOWNSもいちはやくこの疑似スプライトを取り入れていました。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
また、VGAを擁するDOS/V機はスプライトこそ持っていませんでしたが、プレーンタイプと同時にビットマップタイプのV-RAMもサポートしていたため、PC-9801に比べてずっとシューティングゲームが作りやすくなっていました。また、画面の解像度も320×240ドット×256色モードを持っているなど、速度的にもかなり有利でした。逆に言うと、それだけPC-9801がシューティングゲームに不向きな機種だったのです。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
キャラクタの制御 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
およそシューティングゲームには数多くのグラフィックパターン(キャラクタ)が刻々と表示されていきます。自機、敵機、弾丸、ビーム、爆発パターン、デカキャラ、ミサイルなど、多種多様です。そして、これらがそれぞれ個性的な動きを見せ、消滅、出現、変形、分裂というように生物を思わせる変化を見せたりします。これらをどのように制御するかが、シューティングゲームの最も重要で難しい部分でもあります。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
このころ、シューティングゲーム作成の参考書があるわけもなく、試行錯誤を交えながら辿り着いたのが、今で言うところの「クラス」を利用した手法です(正確にはちょっと違いますが)。各キャラクタごとにすべて共通のクラスオブジェクトを持たせます。そしてキャラクタの「動き」を定義したスクリプトを別途用意し、専用のコンバータ(アセンブラマクロを利用)で変換したオブジェクトへのポインタをクラスに持たせます。クラスの中にはそのキャラクタが現時点で出現しているか否かをはじめ、座標、当たり判定エリア、爆発カウント(被弾爆発フラグ含む)、硬さ、スコアなどの情報の他、動き制御スクリプト用の変数ワークエリア(数十バイト)などの領域が確保されています。メソッドに相当する関数も数多く用意してあり、動き制御スクリプトから呼び出されます。 このような「キャラクタ制御クラスオブジェクト」のポインタテーブルを用意し、キャラクタの「出現」と「消滅」に合わせて逐次更新していきます。さらにこのテーブルはキャラクタのプライオリティ(表示優先順位)も決定します。触手や蛇キャラには必須の機能ともいえます。 もちろんこれらのプログラムはアセンブラで記述してあるため実行は高速です。制御スクリプトの実行も最適化されたジャンプテーブルにより、あたかもアセンブラプログラムの一部のように実行するようになっています。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
下はごく簡単な実際の動き制御スクリプトソースの一例です。アセンブラのマクロ機能を利用した独自の専用言語形式になっています。コメントを見ていただければおおよその仕組みは理解してもらえると思います。 このような専用言語スクリプトを用いることによって、速度的には多少のペナルティーを受けますが、毎回実行ファイルをアセンブル(コンパイル)することなく、複数人が手軽にデバッグをすることが可能になります。ターンアラウンドタイムを短くできるということも大きなメリットです。ビートバイスの敵機行動プログラムを書いた人は5人以上にもなります。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ちなみに自機も敵機などと全く同様の仕組みで動かしています。異なるのは後述する「当たり判定」の処理と動き制御スクリプト内で「キー(ジョイスティック)入力をチェック」していることくらいです。このように専用ルーチンで処理せずに、できるだけ汎用ルーチンとして処理することでプログラム構造があまり複雑にならないように工夫しています。 ただ、ビートバイスでは自機や敵機、デカキャラなどの「キャラクタ」と自機や敵機の発射する「弾丸」とは区別しています。敵機のビームや特殊兵器のようなものはキャラクタとして処理していますが、弾丸は大きさが3種類のみで直進しかしないため、高速化のために別扱いとしています。同時に画面に表示される数もかなり多いですから・・・・(いちおうビートバイスでは最大32個、ビートバイス+では40個に制限していますが)。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
当たり判定 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
シューティングゲームにつきもの(?)なのがこの「当たり判定」です。これがないとゲームにならないということは容易にご理解いただけると思います(^_^o)。ハードウェアスプライトを持つ機種では、スプライト同士が重なると割り込みが発生する機能がある場合が多いので、判定は無駄なく簡潔に行うことができます。もちろんPC-9801にはこのような機能はありません。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
当たり判定は敵機同士で行う必要はありません。また、敵機と敵機の発射した弾丸やビーム同士でも不要です。自機と判定が必要なのは、敵機、および敵機の発射した弾丸やビーム、フィールドの障害物の3種類になります。また、敵機側からすると、自機、および自機の発射した弾丸やビーム類、フィールドの障害物の3種類になります。ただ、敵機が自らフィールド障害物には決して当たらないという仕様であれば、最後の敵機とフィールド障害物との当たり判定は省くことができます。しかし、敵機を誘導して障害物にぶつけて破壊する戦術も考えられますから、最初から考えないのではなく、「考慮しておく」というのがよいでしょう。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
当たり判定を考えるときに戸惑いがちなのが、弾が機体に当たるのか、機体に弾が当たるのかという部分です。つまり、弾が移動したときにその弾が機体の当たり判定エリアに入っているか否かを調べるのか、機体の移動処理時に弾が自分の当たり判定エリアに入っているか否かを調べるのかということです。どちらでも構わないようにも思えるのですが、これは後者の方が処理が簡潔でわかりやすくなります。基本的に弾は発射された後は直進し、機体や障害物に衝突するか、画面の外に出てしまうまで生存するという性質があります。弾の移動制御はこれだけでよいわけです。ここに複雑な当たり判定処理を入れるよりも、もともと弾よりも複雑な動きをする機体の動き制御処理に組み込んだ方がすっきりします。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
具体的に言うと、機体の動き制御の流れの中で、新しい位置に移動したときに現在生存している弾の座標をサーチし、自分の当たり判定エリアに入っていないかをすべて調べます。入っていれば、その弾を消滅させ、機体を爆発させるか、ダメージを加算するかするわけです。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
また、当たり判定は弾と機体だけではなく、機体と障害物、自機体と敵機体の間でも必要です。このとき、障害物側を主体とした当たり判定は現実的ではありません。機体側で障害物に接触したか否かをチェックすることになるはずです。このように考えても、機体の動き制御の中で当たり判定を行う方が都合がよいと感じてもらえると思います。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
また、当たり判定の難しさのひとつに、「プレイヤーを納得させられるかどうか」という問題があります。特に自機の当たり判定、障害物の当たり判定には気を配る必要があります。「なんで今のが当たってないんだ?!」とか「ちょっと自機が擦った程度でこのダメージかよ!」とか、プレイヤーの立場で当たり判定を設定しないと、プレイヤーにストレスか溜まってしまい、シューティングゲームの命ともいえる「爽快感」が台無しになってしまうからです。 ビートバイスでは自機の当たり判定エリアは、敵弾に対してと敵機および障害物に対してとは異なっています。敵弾に対しては自機パターンに完全に隠れる矩形範囲になっていますが、敵機や障害物に対しては「自機の重心」になっています(重心といっても厳密に計算されているわけではありません)。つまり「点」ですね。これだと擦ったくらいではダメージを受けませんし、精神的に余裕を持ってプレイすることができます。自機の当たり判定はぬるめに、敵機はきつめにするのが、気持ちよくプレイしてもらえるコツともいえるでしょう。何しろ多勢に無勢なのがシューティングゲームなのですから、この程度のハンディキャップは当然といえば当然かもしれません。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
爆発 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
これはシューティングゲームには必須ともいえる効果です。デザイナ陣も爆発アニメーションのパターン作りには特に力を入れます。敵を破壊した達成感と爽快感を演出する最も大きなファクターだからです。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
また、中ボスのような大型の敵の爆発は、爆発が始まってから順次、「出現してすぐに爆発するキャラクタ」を適当な位置に重ねて発生させることで表現しています。 ただし、ステージ最後の大ボスの爆発は例外で、専用のプログラムで派手な爆発効果を演出しています(ビートバイス+)。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
特殊兵器 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
シューティングをより戦術的に、より派手に演出するのが特殊兵器群です。自機の場合は単純に前方に弾丸を発射し、敵機の場合は自機に狙いを定めて、あるいは固定方向に弾丸を発射する・・・・・これだけではごく単調なシューティングになってしまいがちです。 そこで登場するのが特殊兵器です。ビームをはじめ、誘導弾やエナジー砲など、プレイヤーも敵側(コンピュータ)も多種多様な攻撃パターンを構築することができるようになります。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
制御スクリプトの中では自機との相対座標や相対距離などが取得できるので、誘導弾やパトリオット式炸裂弾(目的物に近づいて炸裂)なども容易に実現できます。また、任意の数値テーブルの登録と参照も可能になっているので、サインテーブルや放物線テーブルを使用して自然な動きを演出することもできます。 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ちなみにビートバイスでは通常兵器のバルカン砲も含め、自機側の兵器はすべてテキスト画面で表現しています。これは広い面積の画面合成の負荷を減らし、迫力を演出するためです。実際に、パワーボールやサンダーテンペストといった派手な特殊兵器を発射していてもスクロール速度が低下することはほとんどありません。
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
柔軟性と生産性 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
シューティングの面白さは「変化」と「攻略」にあると考えます。もし、敵機の攻撃パターンが数種類しかなかったとしたら、もし背景が単調な宇宙空間だけだったとしたら、もし自機の武器が一門の連射砲だけだったとしたら・・・・いかに工夫しても単調さは拭えないでしょう。わくわく感、どきどき感、達成感、これらを演出するには変化に富んだステージとプレイヤーに頭を使ってもらう仕掛けが必要です。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ステージにバライエティーを持たせるためには、敵機やスクロールを制御する仕組みに工夫が必要になります。これが結構悩ましいところなのです。比較的簡単に制御できるように仕様を作ると、できることの制約が大きくなります。ツクール系ソフトなどもかなり工夫をして制約が小さくなるように努力されているようですが、やはり限界があります。かといって制約がないようにしようとするとスキルの高いプログラマしかできなくなってしまいます。このトレードオフをどうするかが、シューティングを作るときのコンセプトとも絡んできます。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
前出の制御スクリプトを見てもらえればわかると思いますが、ビートバイスでは生産性よりも柔軟性を重視しています。原則、制御スクリプトでできないことはありません。これは当然のことで、「こういうことをさせたい!」という希望が上がってきたら、制御スクリプトを拡張してしまうからです。例えば、「ビームを跳ね返す敵機を作りたい」という要望があれば、当たり判定命令"HIT"でビームか否かをチェックする機能を追加するといった具合です。もちろん、ビーム処理ルーチンにも手を入れてビームが一定の条件で反射するようにする必要もあります。また、これによってプレイヤーは敵機を見て判断し、ビームではない武器に切り替える必要が生まれます。直前までビームを使うと効率良く落とせる敵を出現させておけば、これは顕著になります。面倒ですが、ツクール系ソフトではまず実現できないことでもあります。生産性よりも柔軟性を重視してこそ、プレイヤーに伝えられるものがあると信じます。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||