みなさま、初めまして! Cygames エンジニアマネージャーの和泉澤と申します。
ゲーム業界歴20数年。メガドライブの時代よりゲームプログラミング一筋です。
時折、幾つかの知見をご紹介させて頂けましたらと思います。
昨今、様々なタイプのゲームが存在しており、その多様さたるや枚挙に暇もありません。幾多の現代ゲームプラットフォーム、幾多のデバイスにおいて、様々な操作方法や表現の上に、多くのゲームが生み出されています。
しかしながらどの様なゲームにおきましても、その根底を支える基本仕様や実装につきましては、ゲーム黎明期よりそうそう大きく変わってはいないとも言えましょう。
例えば、谷底へ落下すれば強制死亡としているゲームは少なくないように思います。
HP上限アップアイテムを沢山使っても、一定値でクランプされる仕様・実装は通例でしょう。
こうした極基本的な仕様・実装に対して、工夫する余地はそう多くは無いかもしれません。(*1)
もう少し複雑な例としまして、パッドの入力管理はどうでしょうか?
主人公を制御するパッド入力。ただ単にデバイスからの入力を司る機能を作り、それを利用すれば、一応、ゲーム制作を進める事は出来そうです。
しかしながら現実には、間に仮想的なレイヤーを挟まなければ、色々と不便な事が多いでしょう。
各プログラムがパッド情報を直接見に行っていたのでは、ボタン入力カスタマイズの実装すらままなりません。受け渡しを仲介する機能が存在していれば、例えば、自動入力によるモンキーデバッグ機能の追加も現実的でしょう。
単純実装可能で且つ利用者の多いモジュールや機能に関しましては、注意深い実装・設計が求められるシンプルな例です。
本稿におきましては、そうした基本的なゲーム機能の一つ「ゲーム内時間管理」へ注目してみたいと思います。
ゲーム内時間管理とは?
例えば、カードゲームにおいてある一枚のカードがデッキよりフィールドへ配置される際には、ゲーム内時間に沿ってカードの移動出現演出が「進行」している事でしょう。
アクションゲームならば、プレイヤーは走り、敵キャラクターは攻撃を繰り出し、それにより多数のエフェクトが焚かれるといった、様々な「進行する」オブジェクトが存在しているでしょう。
背景モデル上には草が風になびき、遠方では雄大な川が流れているかもしれません。彼らもまた、ゲーム内時間に沿って「進行」しています。
時間の種類
極当たり前の話ですが、ゲーム内には自身の進行を司る「時間」が流れています。
しかしながら、ゲーム内時間というものは一意の単なる時間に限りません。
例えば、可変長フレームレートにて駆動するゲームを設計する場合、ゲーム全体を司る大きな「絶対時間」といった概念を導入する必要があるかもしれません。
また、プレイヤーが敵キャラクターを攻撃した際、その両者には所謂「ヒットストップ」を発生させるという演出は通例でしょう。ここでも、固有の時間管理が発生します。
はたまた、一時的に敵全体の行動を遅くする事の出来る魔法、「ワールドスロー!」があるとします。この魔法をプレイヤーが唱えるかもしれません。ここで、全個体の中より「敵」と区分されるものだけに作用する時間管理が発生します。
ポーズボタンを押した際は? そうですね、広義においてはこの時も、「全ての時間」を一時停止させていると解釈する事も出来るでしょう。
実装方法の検討
これらを適切に実装する事で、様々な表現や機能を実現する事は可能ですが、さて、どの様な設計を行うべきでしょうか?
先述の「ワールドスロー!」という魔法。敵キャラクターを司るプログラムの中で、自陣に発生している時間的効果を検出するのでしょうか?
その実装の場合、敵キャラも「ワールドスロー!」を唱える事が出来るようになると厄介です。
更に、単純な「プレイヤーvs敵達」といった勧善懲悪構成ではなく、複数チーム戦の様な他陣営ゲームへ発展した際には、頭を抱える事になるでしょう。
ヒットストップはどうでしょうか?
プレイヤーの大剣なぎ払い攻撃が、周囲数体の敵にヒットしました。その当事者達のみへ上手く一定時間ストップなりスローを施す事は難しくはなさそうです。
しかし、その攻撃を食らっている敵キャラクター達の中に数体、「自身を守りながら空中を浮遊するビットを幾つも纏っている魔法使い」が居るかもしれません。
ビット達のプログラムに、親が受けている時間的効果を検出させるのでしょうか?
その最中に「ワールドスロー!」が発生した場合はどうなるのでしょう?
極初歩的な話ですが、この様に、都度対応していく実装はどのような形式のプログラムにおいても、大抵はなかなか上手くいきません。何か、一意に解決する方法が求められる場面です。
階層構造
ゲーム内の様々な要素を制御する考え方には多種あるかと思いますが、階層化するという選択は、多くの場面において良く機能します。
まず、世界を意味する「フィールド」を定義します。名称は何でも構いません。
フィールドには、「陣営」が属しています。「チーム」と読み替えて頂くと、所謂「チーム戦」の様に陣営が沢山存在するゲームでもイメージし易いかと思います。
各陣営には、個体が属します。プレイヤーや敵達でしょうか。
アイテムが落ちたらフィールドへ直接所属させようか? そうしたもの達だけを集めた「陣営」を用意しようか? ゲームによって色々な階層構造が考えられるでしょう。
ともあれ、まずは大枠の階層構造が出来上がりました。
この階層構造を、ゲーム内時間管理にも適用してみましょう。
それぞれの要素、「フィールド」「陣営」「プレイヤー」等など、どの要素へも全て、固有の「自身の速度係数」を持たせます。通常時、値は全て1.0です。
この構造とそれぞれの速度係数を元に、毎フレーム、各要素の実稼働時間を求めます。
まずは「フィールド」へ、フィールド自身の時間を進行させてみましょう。
「フィールドの持つ速度係数」は1.0ですので、「フィールド」は1.0だけ自分の時間を進行させます。
次に、結果である「1.0進んだ」という情報を、子供達「陣営1」「陣営2」へ伝えます。彼らは、受け取った「1.0」へ自身の速度を乗算し、結果をまた子供に伝えます。
個別の要素は、「自分の速度係数」だけを気にしていれば構いません。
演算結果を階層構造として伝えていく事で、ゲーム全体の一意な時間管理が可能です。
多様なゲーム内時間を管理する方法は幾つかあるかと思いますが、階層構造化は様々な場面で良く機能します。
みなさんのプロジェクトでも、是非採用を検討されてみては如何でしょうか?
(*1)実際には、HPの管理一つとっても大いに工夫の必要が御座います。その辺りはまた改めましてご紹介します。
Cygamesではゲーム開発を支える様々な技術研究にも取り組んでいます。
技術研究に興味があるかたは、是非Cygamesで一緒に働きませんか?
採用ページはこちらです。