ゲーム状態システムの代替手段?


30

私の知る限り、ほとんどのゲームには、異なるゲーム状態を切り替える「ゲーム状態システム」があります。これらは、「Intro」、「MainMenu」、「CharacterSelect」、「Loading」、「Game」などです。

一方では、これらを状態システムに分離することは完全に理にかなっています。結局のところ、それらはバラバラであり、そうでなければ、明らかに乱雑な大きなswitchステートメントである必要があります。そして、それらは確かに状態システムによってうまく表されています。しかし、同時に、「ゲーム」状態を見て、この状態システムのアプローチに何か問題があるのではないかと考えています。それは部屋の象のようなものだからです。それは巨大で明白ですが、ゲームの状態システムのアプローチに疑問を呈する人はいません。

「ゲーム」が「メインメニュー」と同じレベルに置かれているのは馬鹿げているようです。しかし、「ゲーム」状態を解除する方法はありません。

ゲーム状態システムが最善の方法ですか?「ゲームの状態」を管理するための、より良いテクニックはありますか?映画を描いてエンターをリッスンするイントロ状態、リソースマネージャーでループするローディング状態、そして実際にすべてを行うゲーム状態を持つことは大丈夫ですか?これもあなたにとっては不均衡に思えませんか?何か不足していますか?

回答:


30

ここでセマンティクスを主張しているだけだと思います。それは有限状態機械のように振る舞うため、ゲーム状態と呼ばれます。これは、有限数の状態とそれらの間の遷移を持ちます。「Game State System」の「Game」はシステム全体を指し、「Loading」、「MainMenu」などはゲームの状態です。これらは簡単に「シーン」または「スクリーン」または「レベル」と呼ばれます。その意味論。

厳密なFSMがもう適用されるかどうかはわかりません。私の実装では、状態を「スクリーン」と呼び、それらをスタック可能にします。画面を他の画面の上に描画して、その下の画面を更新または描画するかどうかを制御できます。このようにして、他の画面を気にすることなく、その画面に固有の自己完結型のロジックとコードを使用して、複数の画面を同時にアクティブにすることができます。

たとえば、メインのゲームプレイ画面の上に一時停止画面を開くと、更新は許可されませんが、その下に描画できます。キャラクターのインベントリ画面では、描画と更新の両方が可能になるため、インベントリで作業している間、ゲームはプレイし続けます。


これはまさにその方法です。画面には、ツリーのようなアーキテクチャで他の複数の画面を含めることができる必要があります。そのため、プログラムにはゲーム画面が含まれます。ゲーム画面には、オーディオ設定画面とゲーム設定画面が含まれる一時停止メニュー画面が含まれます。など
イアン

1
このためのソースコードの例を見てみたいです!(C ++ / C#/ Javaが望ましい)
ゾロモン

1
残念ながら、現時点では製品コードしかありませんが、XNA Game Stateサンプルには同様のコンセプトがあります:creators.xna.com/en-GB/samples/gamestatemanagement
DrDeth

7

ゲームの状態が巨大であることは確かですが、ゲームの状態自体がそのデータを管理するための状態マシンを含むことができないという理由はありません。階層状態マシンは便利です。


4

私は常に、各「状態」を「シーン」として考えるのが好きです。したがって、オープニングビデオはシーンであり、単なる静的なものです。クレジットはシーンです。メニューはシーンです。それらすべての唯一の違いは、対話性とゲームロジックのレベルです。


3

私も実際に問題があります。

ゲームがあるとしましょう。

「ゲーム」を「読み込み中」、「メインメニュー」などの状態にする代わりに-IMOでは、ゲームいくつかの状態を持たせることをお勧めします。

「読み込み中」 - 「メニューを表示中」 - 「一時停止中」など

ゲームはまだ実行中ですが、メインメニューが表示されると「メニューを表示」モードになります。

そして、ゲームが特定の状態にないときは、ただ実行されています。

少なくとも私にとっては、もっと理にかなっています。:)


同意する。Pause-Stateに入るためだけにGame-Stateを終了したい人はいません。一方、それはまだ状態システムです..ちょうどネストされた:)
bummzack

2

オンラインプログラム(従来のオンラインの意味、つまり、インターネットに接続された意味ではなく、継続的に実行され、入力に応答する)は、通常3つのもので構成されます。

  • 入力の収集と処理
  • ロジックの更新
  • 出力

一般的に、これら3つは関連しており、同時に変化します。たとえば、スプラッシュ画面を表示する場合、すべてのキーを「画面を閉じる」コマンドにマッピングし、更新ではグラフィックがゆっくりとフェードインし、出力にはそのグラフィックが表示されるだけです。しかし、ゲームをプレイするとき、キーはすべて異なるコマンドにマッピングされる場合があり、更新により多くのゲーム内オブジェクトのプロパティが変更されます。

このように表示する場合、イントロをキャラクター作成とゲーム固有から分離することは理にかなっています。それぞれに独自の入力、更新、および出力ルールのセットがあります。それらは、データとライブラリコードを共有する自己完結型プログラムのようなものです。そして、これを念頭に置いて、ゲームプレイは全体を通してかなり均一であるため、通常、ゲームの状態を1つだけにすることが理にかなっています。

もちろん、異なる入力、更新、出力の異なるゲームプレイ(例:RPGの例-World Map、Town Map、Cutscene、Combat)を実際に使用している場合、そこに複数の状態を設定できない理由はありませんただ1つのゲーム状態ではなく。しかし、それはあなたのゲームに依存します。


1

私はそれを他の方法で見ます。「Menu」、「HighScores」、「credits」またはwhathaveyouは単なる別のレベルと見なすことができ、その状態は「ゲーム」状態よりも必ずしも軽いわけではありませんとは異なりますが、最終的にはエンティティがより予測可能な動作を示し、「マップ」が一般的に複雑ではない単なる別のレベルです)。
考えを変えると、間違いなく「退屈なメニュー」症候群から抜け出します。


私は同じことを言っていました...すべての私のメニュー、画面、何でも、ちょうど別のレベルです。
スピーダー

1

私のゲームには、次のものがあります。

Execution Managerは、アプリケーション(ゲーム)を初期化し、リソースをロードし、アプリケーションの終了時にリソースを解放します。ApplicationEngine、GameViewEngine、GameLogicEngineを初期化します。

GameLogic Managerに常駐し、ゲームのメインループに関連するもの(衝突検出、物理計算、キーボード読み取り、数学演算など)の制御を担当するGame State Manager

最初は、GameLogicEngineの一部であるGame State Managerが1つしかありませんでした。ただし、メインサブシステム(GameLogic、ApplicationEngine、...)の初期化を制御するのは困難でした。できたかもしれませんが、もっと面倒でした。

今では物事は私にとってより透明に見え、デザインに満足しています。


0

「ゲーム」状態の名前を「ゲームプレイ」などに変更します。そうすれば、あなたの論理は良くなったようです。再生を停止してメニューに移動します。Gameplay状態を終了してMainMenu状態に移動します。

また、一時停止など、ゲームを一時停止したときと同じ状態にする必要があるものは、別の状態にすべきではないと思います。おそらく子の状態とネスト?ゲームプレイには一時停止メニューがあります。


0

ゲーム状態スタックと呼ばれる良い方法があると思います。私はそれについての論文や記事を見たことはありませんが、それは声で少し広がっています。基本的に、スタックの一番上のゲーム状態が最初に呼び出され、入力/レンダリングなどで何でもやりたいことができます。一番上のゲーム状態は、状態をプッシュまたはポップできる唯一のゲーム状態です。

私のエンジンでは、ゲーム状態は実際には単なるゲームエンティティのリストです。次に、メニューとして機能するエンティティがあります。私のメニュー状態は、ゲームを一時停止します(スタック上の次のアイテムを更新しないことにより)背面にゲームのレンダリングがあります。

ステートマシンに基づいていない、少し異なるシステムのアイデアが得られることを願っています。


0

映画を描いてエンターをリッスンするイントロ状態、リソースマネージャーでループするローディング状態、そして実際にすべてを行うゲーム状態を持つことは大丈夫ですか?これもあなたにとっては不均衡に思えませんか?何か不足していますか?

これはまったく問題ありません。または、少なくとも、「ゲームの状態に応じて大きないスイッチを持つ」よりも改善されています。

ほとんどのゲームでは、単純なエンティティAIを扱うために、すでに有限状態マシンが必要であることを指摘したいと思います。典型的な例は、アイドル状態、攻撃中、または死亡中の敵です。

十分に抽象化された有限状態マシンがある場合、それをゲームオブジェクトとAIの両方に再利用できます。突然、ゲームの状態に多くの労力を「投資」するのではなく、代わりに使用したコードを再利用しています。

恥知らずなセルフプラグが続いて:LuaゲームライブラリであるMiddleClass(具体的にはMindStateと呼ばれるアドオン)にこのような有限状態マシンを実装しました。以下に、Game Stateをどのように使用するかを示します


0

これに対する別のアプローチは、Discriminated Unionと呼ばれる関数型プログラミングの世界の概念を使用することです。これらは通常 FP言語にありますが、クラスを使用してエミュレートできます

基本的に、差別化ユニオンは常にnケースの1つであり、保存されるデータはケースごとに異なる可能性があります。

例えば:

type GameState =
  | Menu of MenuState
  | Playing of SimulationState

ここで、GameStateタイプはまたはのいずれMenuPlayingです。の場合MenuMenuStateオブジェクトが含まれます。の場合PlayingSimulationStateオブジェクトが含まれます。

更新するにはmatch、状態を変更し、それに応じて別の関数を呼び出します。

let update gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> updateMenu gameTime menuState
    | Playing simulationState -> updateSimulation gameTime simulationState

  // Mutate the current state
  gameState <- nextState

レンダリングについても同様です:

let render gameTime = 
  let nextState = 
    match gameState with
    | Menu menuState -> renderMenu menuState
    | Playing simulationState -> renderSimulation simulationState

このアプローチの利点の1つは、グローバルや「サービス」オブジェクトをやり取りすることなく、状態(リソースなど)全体をより簡単に処理できることです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.