11

Java でグリッド ベースのゲームを作成しており、ゲームの記録と再生を実装したいと考えています。2つのアイデアを検討しましたが、これを行う方法がわかりません:

  1. 毎秒数回、ゲーム全体の状態を記録します。再生するには、状態を読み取るレンダラーを作成し、視覚的な表現を作成します。ただし、これを使用すると、保存ファイルが大きくなる可能性があり、再生を試みると顕著な遅延が発生する可能性があります.

  2. キーを押したりマウスをクリックしたりするたびに、保存ファイルに書き込むこともできます。これにより、ファイルが小さくなり、遅延が少なくなります。ただし、ゲーム開始時のわずかなエラー (たとえば、1 ミリ秒後の射撃) で、ゲームの数分後にゲームの状態が大きく異なります。

では、ゲームの再生を実装する最善の方法は何でしょうか?

編集 - 私のゲームがどれほど決定論的であるか正確にはわからないので、キーストロークとマウスのクリックだけを記録するだけでゲーム全体を正確につなぎ合わせることができるかどうかはわかりません.

4

8 に答える 8

14

優れた再生メカニズムは、大きな問題なしにゲームに簡単に追加できるものではありません。最善の方法は、それを念頭に置いてゲームインフラストラクチャを設計することです。コマンドパターンを使用して、このようなゲームインフラストラクチャを実現できます。

例えば:

public interface Command{
    void execute();
}
public class MoveRightCommand implements Command {
   private Grid theGrid;
   private Player thePlayer;

   public MoveRightCommand(Player player, Grid grid){
        this.theGrid = grid;
        this.thePlayer = player;
       }

   public void execute(){
     player.modifyPosition(0, 1, 0, 0);
   } 
}

そして、ユーザーがキーボードボタンを押したとき、マウスを動かしたとき、または再生メカニズムを使用してトリガーを使用しないときの両方で、コマンドを実行キューにプッシュできます。コマンドオブジェクトは、正確な再生のために(再生の開始に対して)タイムスタンプ値を持つことができます。

于 2009-04-28T22:17:35.447 に答える
8

ショーン・ハーグリーブスは、MotoGP でリプレイをどのように実装したかについて、彼のブログに最近投稿しました。いくつかの異なるアプローチとその長所と短所について説明します。

http://blogs.msdn.com/shawnhar/archive/2009/03/20/motogp-replays.aspx

于 2009-04-28T22:45:22.010 に答える
3

ゲームが決定論的であると仮定すると、ユーザーの入力を記録すれば十分かもしれません (オプション 2)。ただし、サーバーによって認識されたときなど、これらのイベントの正確で一貫した時間を認識していることを確認する必要があります。グリッドでイベントを処理する方法がわかりません。

私が心配しているのは、時間指定されたイベントを一様に参照できるメカニズムがない場合、コードが分散ユーザーを処理する方法に問題がある可能性があるということです。

たとえば、XBOX 360 の Halo 3 のようなゲームを考えてみましょう。各クライアントは、サーバーベースの修正を含め、ゲームのビューを記録します。

于 2009-04-28T22:06:31.243 に答える
2

これにどのようにアプローチするかは、ゲームで使用している言語によって大きく異なりますが、一般的には、大量のストレージを使用するか、遅延を必要とするかに応じて、多くのアプローチがあります。どのような犠牲を払っても構わないと思っているかについて、考えを述べていただけると助かります。

しかし、前述のように、ユーザーからの入力を保存し、ゲーム内のすべてのアクター/スプライトの位置を同時に保存することが最善の方法であると思われます。これは、方向を保存するのと同じくらい簡単です。 、速度、およびタイル x、y、またはすべてが決定論的である場合は、情報を取得できるため、アクター/スプライトを無視します。

ゲームがどの程度非決定論的であるかも、より良い提案をするのに役立ちます。

クラッシュ ダービーのように大量の動的な動きがある場合は、特定のフレームレートでプレーヤー/アクターを更新する必要があるため、フレームごとに情報を保存することをお勧めします。

于 2009-04-28T22:44:41.777 に答える
2

ゲームのリプレイを記録する最良の方法は、ゲームの性質に完全に依存していると簡単に言えます。グリッド ベースであることは問題ではありません。問題は、状態変化に続く予測可能な動作の仕方、システムへの新しい入力の頻度、任意の時点で注入されるランダム データがあるかどうかなどです。各動きを順番に記録するだけで、チェス ゲーム全体を保存できます。しかし、それは明確なターンがない一人称シューティング ゲームでは機能しません。各入力の正確な時間を記録することで一人称シューティングゲームを保存できますが、入力の結果がランダムなサイコロの結果によって変更される可能性がある RPG では機能しません。できるだけ頻繁にスナップショットを撮るという一見間違いのないアイデアでさえ、重要な情報が瞬時に表示され、それが表示されない場合は十分ではありません。」

興味深いことに、これはネットワークで発生する問題と非常によく似ています。ゲームの状態全体を非現実的な頻度で送信することなく、あるコンピューターが別のコンピューターにゲームの状態を認識させるにはどうすればよいでしょうか? 典型的なアプローチは、イベント通知と状態の更新をオーダーメイドで組み合わせることになります。これはおそらく、ここで必要になるものです。

于 2009-04-28T23:00:06.497 に答える
2

フレームごとにシーン内のすべてを保存する必要はありません。変更を段階的に保存し、適切な補間手法を使用してください。私は実際にはコマンド パターン ベースのアプローチを使用しませんが、すべてのゲーム オブジェクトに対して固定レートでチェックを行い、属性が変更されたかどうかを確認します。変更が何らかの適切なエンコードで記録され、リプレイがそれほど大きくならないという変更がある場合。

于 2009-04-28T22:36:22.420 に答える
2

1 秒間に数回記録してから、出力を圧縮するか、おそらく次のようにします。

recordInitialState();
...
runs 30 times a second:
recordChangeInState(previousState, currentState);
...

タイムスタンプを付けて状態の変化を記録するだけの場合 (それぞれの変化は小さく、変化がない場合は何も記録しない場合)、適切なファイル サイズになるはずです。

于 2009-04-28T22:03:08.570 に答える