ゲーム状態の保存/読み込み?


12

ゲームの状態(プロファイル)を保存するために最もよく使用される方法やアルゴリズム、データベーステキストファイル、暗号化の方法、関連するものは何ですか。

Caesar IVがmySQLを使用しているのを見ました。

助言がありますか。

回答:


20

ほとんどの場合、プロプライエタリ(バイナリ)形式で行われます。使用するゲーム状態構造体から各変数をファイルに書き込むか、そのファイルを構造体のインスタンスに読み込みます。たとえば、C ++では、オブジェクトをバイト配列のように扱い、ファイルにfwrite()するか、ファイルからfread()してオブジェクト形式にキャストし直すことができます。

Javaまたは別の言語を使用している場合、タスクを本当に簡単にするためにシリアル化を使用することを選択できます。Javaの説明はこの回答の下部にあります。他の言語(C ++よりも高レベル)には、独自のシリアル化ライブラリまたは組み込み関数も必ずあります。これらは使用することを選択する必要があります。シリアル化ルーチンがどれほど効率的でなくても、特にゲームの状態をまったく大きくすべきではない場合は特に、最近のハードドライブのスペースは安価であり、書き込みや保守ができなくなります。、独自のシリアル化ルーチンをする。

MySQL を絶対に使用しないでください(このレビューの最初の文を読んでください)。何らかの理由でリレーショナルデータベースが本当に必要な場合は、SQLiteを使用してください。これは軽量のデータベースシステムであり、単一のデータベースファイルに存在します。しかし、ほとんどのゲームでは、リレーショナルデータベースは使用できません。それらを使用しようとする企業は通常、真のリレーショナルデータベースではなく、キーと値のルックアップテーブルとして使用します。

ローカルディスクファイルのあらゆる種類の暗号化は難読化のみです。ハッカーは、プログラムが復号化した直後にデータを盗聴します。私は個人的にその種のことに反対しています、特にワンプレイヤーゲームでは。私の見解では、ゲームの所有者(顧客に支払いをする、気にしないでください)は、必要に応じてゲームをハッキングすることを許可されるべきです。場合によっては、コミュニティの感覚を高めることができます。また、ゲーム用に「mod」を開発して、より多くの顧客を獲得できます。思い浮かぶ最も最近の例は、最近リリースされたMinecraft mod のポータルです。インターネット上のゲーマーニュースサイトで公開されており、Minecraftの売り上げを押し上げたに違いありません。


何らかの理由で、私と同じようにゲーム開発にJavaを使用することに夢中になっている場合は、Javaでのシリアル化について簡単に説明します。

すべてのゲーム状態データを1つのクラスに保持し、実装することでクラスをシリアル化可能にし、特別なインスタンス化された変数をクラスに混在させる場合Serializabletransientキーワードを使用し(一時オブジェクトはシリアル化されません)、ObjectOutputStreamファイルへの書き込みとファイルObjectInputStreamからの読み取りに使用します。それでおしまい。


2
ふふ、ウィッチャーはデータを暗号化しませんでした。16進エディターでセーブゲームファイルを開くのは非常に簡単で、少し混乱させて、すべての裸のひよこカードを取得します...ああ、すみません!
アンソニー

ゲームを保存するために.NETバイナリシリアル化を使用しましたが、C#はおそらく、ゲームを開発するJavaよりも少し合理的なプラットフォームです。オブジェクトグラフ全体を自動的に保存する方法が気に入っています。これは以前よりもはるかに困難でした。もちろん、テクスチャのような不要な部分を除外するという課題がありますが、それは達成するのに大したことではありません。
BlueMonkMN

ゲームを開発する上で、C#がJavaよりもやや人気があることに異論はありません。より合理的であることはある程度の主観性を意味し、XNAとJavaの両方の開発者として、私はJavaを好みます。必要に応じて、C#でのシリアル化の手順も自由にリストしてください。私はそれをやったことがありませんが、それを編集して回答に入れることができます。Javaのシリアル化はオブジェクトグラフ全体を保存し、変数の 'transient'キーワードはテクスチャなどの不要な部分を除外します。非一時的なメンバーはSerializableである必要があります。そうでない場合は、カスタムのwriteObjectメソッドを記述して回避できます。
リケット

Pythonのpickleはオブジェクトグラフ全体も保存するため、使いやすく簡単です。:それは時間が来るとき、あなたが簡単に円グラフとして、バック完全に水和オブジェクトを渡されるデシリアライズするdocs.python.org/library/pickle.html
drhayes

ビルトインバイナリフォーマッタを使用する場合、C#/。NETでのシリアル化から特定のフィールドを除外することは、[NonSerialized]属性で装飾するのと同じくらい簡単です。ただし、見落としやすいのは、コンパイラが生成したイベント(つまり、カスタムの追加/削除演算子のないイベント)が、サブスクライバーを格納するためのバッキングフィールドを作成することです。したがって、シリアル化されたオブジェクトグラフに誤って(そして無意識のうちに)イベントハンドラーを含めるのは簡単です。これを回避するには、イベントの宣言にNonSerialized属性を追加する必要がありますが、「フィールド:」を追加する必要があり修飾子:[field: NonSerialized]
マイク・ストローベル

3

C ++などで独自のコードを記述している場合、バイナリファイルを使用できます。バイナリファイルは、難読化による暗号化の形式を提供します。しかし、インターネット全体で文書化されているように、これは非常に弱いセキュリティ形態です。

または、人間が読めるソリューションが必要な場合は、RapidXMLなどを使用できます。

何らかのフレームワークを使用している場合は、ファイルサポート関数を調べてください。HTH


0

私が見たほとんどのゲームは、手書きのコードを使用してバイナリファイルを読み書きします。多くの場合、ディスク上の形式はオブジェクトのメモリレイアウトの正確なレプリカになるため、読み込みは次のようになります。

  1. ファイルをメモリに読み込みます。
  2. バッファへのポインタをオブジェクト型にキャストします。

高速ですが、維持するのが面倒で、プラットフォーム固有で、柔軟性がありません。

最近、いくつかのゲームがSQLiteを使用しているのを見てきました。私が話を聞いた人はそれが好きなようです。


0

シリアル化は他の回答のいくつかで言及されており、それが合理的な解決策であることに同意します。失敗する1つの方法はバージョン管理です。

ゲームをリリースすると、人々はそれをプレイし、セーブゲームを作成するとします。次に、後のパッチでバグを修正するか、いくつかの機能を追加します。単純なバイナリシリアル化メソッドを使用し、クラスにメンバーを追加すると、顧客がパッチをインストールしたときに、シリアル化が古いセーブゲームと互換性がない場合があります。

したがって、どのアプローチを使用する場合でも、ゲームを初めてリリースする前にこの問題を必ず考えてください!パッチを適用した後に最初からやり直す必要がある場合、顧客は満足しません。

これを回避する1つの方法は、各基本データタイプに、ゲームの各バージョンで保存およびロードするデータを把握できるほど賢いSave(version)およびLoad(version)メソッドを実装させることです。これにより、セーブゲームの後方互換性をサポートし、ユーザーが実行中のゲームよりも新しいバージョンからセーブゲームをロードしようとすると、正常に失敗します。


1
簡単なメモ:ゲームの各バージョンに「保存」および「ロード」機能を実装すると、すぐにメンテナンスの悪夢に変わります。より良い解決策は、バージョン番号を埋め込み、ゲームの現在のバージョンの「保存/読み込み」関数を記述し、最新の非最新バージョンから現在のバージョンに「変換」関数を記述することです。次に、すべての変換関数を保持します。10バージョン前のゲームをロードしようとすると、10個の変換関数が連続して実行され、次にネイティブの「現在のゲームバージョンをロード」関数が実行されます。
-ZorbaTHut

長期的なメンテナンスがはるかに簡単-一連の「以前のゲームファイルをすべて読み込む」機能を維持することで、多項式時間操作にすぐに変わります。
-ZorbaTHut

私が取り組んだゲームでは、それほど複雑ではありません-ロード/保存メソッドの複数のコピーを保持するのではなく、単一のメソッドがバージョン番号を使用して読み書きするバイトを決定します。これは、構造を書き込むだけでなく、プリミティブデータ型レベル(たとえば、ReadByte / ReadFload / etc)で操作として読み込みと保存を実装する場合にさらに簡単になります。次に、新しいメンバーを追加すると、if(version> 10){someNewByte = ReadByte(); }この方法で実装すると、異なるエンディアンプラットフォームのサポートも容易になります。
ケビン42

バージョン管理サポートの改善を回避する別の方法は、オブジェクトのシリアル化/逆シリアル化メソッドがストリームから個々の値を直接読み書きすることを回避することです。代わりに、オブジェクトはキー/値のペアを使用して所有データをプロパティバッグに書き込み、そのバッグをストリームに書き出すことができます。逆シリアル化中に、オブジェクトは名前からバッグから値を読み取ることができました。ただし、kevin42のように特定のバージョン番号チェックを行う代わりに、欠損値の処理方法に関するルールを設定することもできます(つまり、必要な値が袋に入っていない場合は標準のデフォルト値を使用します)。
マイクストロベル

0

レベルの保存に使用するのと同じ形式を使用できる場合は、ボーナスです。

たとえば、Peggleのようなゲームには、最初のボードレイアウト、ボールの数、現在のスコア(最初のボードの場合は0)などがあります。保存したゲームはまったく同じ形式を使用できます。

同じ形式を使用する場合、セーブゲームとレベルロードでコードを共有できるため、作業が簡単になります。

非常に大きなマップファイルを使用するゲームの場合、セーブゲームにはマップファイルを参照によって含めることができます。初期レベルのファイルは同じことをするかもしれませんが、何らかの理由でキャラクターが同じ場所に戻ってきた場合、一部のNPCが死んでおり、すべての死体が横たわっている場合を除き、そのマップに戻るのも簡単になります以上。

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