Objective-Cを使用してiPhoneの終了時にゲームの状態を保存する


回答:


7

これが私のゲームで使用した方法です。

まず、永続化する必要があるすべてのオブジェクトは、NSCodingプロトコルを実装する必要があります。モデルデータのみを保存し、現在のプロセスに固有のものは何も保存しません。これは、OSが実行時に提供するポインターやリソースIDを永続化できないことを意味します。ポインターについては、ポインター自体ではなく、ポインターが指すオブジェクトを確実にエンコードすることで、これを簡単に修正できます。他のリソースについては、実行時にオブジェクトを新しいリソースにフックする方法が必要になります。

次に、すべてのゲームオブジェクトが単一のルートオブジェクトを通じてアクセスできることを確認します。このオブジェクトは、たとえば、ゲーム状態全体のマスターオブジェクトになる可能性があります。別の可能性は、それらをFoundationコレクションクラス(NSMutableArray、NSMutableSet、NSMutableDictionary)のいずれかに格納できることです。

アプリケーションがバックグラウンド(applicationDidEnterBackground)に移行することを通知されたら、NSKeyedArchiverを使用して状態全体をファイルに保存する必要があります。そのファイルは、アプリケーションのドキュメントディレクトリにある必要があります。これがどのように行われるかを示すコードの一部を次に示します。

NSArray *docDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [docDirectories objectAtIndex:0];
NSString *saveFile = [docsPath stringByAppendingPathComponent:SAVE_STATE_FILENAME];
[NSKeyedArchiver archiveRootObject:gameState toFile:saveFile;

フォアグラウンドに戻ったことを検出した場合は、保存ファイルを削除して、次にアプリケーションを起動したときの混乱を防ぐ必要があります。

アプリケーションの起動時に、保存ファイルの存在を確認する必要があります。持っている場合は、次のようにロードします。

NSArray *docDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [docDirectories objectAtIndex:0];
NSString *saveFile = [docsPath stringByAppendingPathComponent:SAVE_STATE_FILENAME];
[gameState release];
gameState = [[NSKeyedArchiver unarchiveObjectWithFile:saveFile] retain];

デザインによっては、ゲームの状態を確認し、永続化できなかったリソースを再接続する必要がある場合があります。これは、モデルコードがレンダリングコードからどの程度明確に分離されているかによります。

この時点で、作成しているゲームの種類に応じて、ゲームを一時停止状態にすることができます。

うまくいけば、これはiPhoneにゲームの節約を実装しようとしている他の誰かを助けるでしょう。


2

ゲームの状態を保存する方法は、ゲーム自体の設定方法に大きく依存する複雑な問題です。

iPhoneでは具体的には、あなただけにフックする必要があります-(void)applicationWillTerminate:あなたの中UIApplicationDelegateのアプリケーションがユーザーのアクションから、あるいはそうでない場合は、終了するときキャッチします。ただし、OSがプロセスを強制終了する前に、短時間で作業を行うことができます。


2
applicationWillTerminateは、マルチタスクをサポートしないアプリケーションまたは4.0より前のSDKでのみ機能します。4.0以降のコードでapplicationDidEnterBackgroundを使用することをお勧めします。
Dennis Munsie 2010

1

それは、ゲームのコーディング方法に大きく依存します。いくつかのivarまたはより重要なものを追跡していますか?

それがほんの数個のivarである場合、おそらくそれらをバックグラウンドのplistに書き込み、起動時にそれをロードします。

さらに多くのivarがある場合は、CoreDataを使用することをお勧めします(および/またはすべてを閉じるウィンドウに収めようとするのではなく、値が変化するときにそれらを保存します)。


OSがシャットダウンするまでの時間で、実際に多くのことを行うことができます。その時に私が回答で説明した方法を使用して、かなりの数のゲームオブジェクト(少なくとも数百)を永続化することができました。遅い1G iPod touchでも。作成しているゲームの種類によっては、アプリの終了時にCoreDataソリューションが適切に機能する場合がありますが、ゲームプレイが遅くなります。
Dennis Munsie 2010

1

ユーザーが終了せずに保存ゲームにぶつかったときに保存するのと同じ方法。

ゲームの状態を保存する方法についての質問ですか?または、アプリの出口で何かをするにはどうすればよいですか?

後者の場合、答えは次のとおりです。appWillTerminate(またはappWillResignActive)。iOS4以降では、保存ゲームに時間がかかる場合、追加の時間(Google "iOS-4 request extra time")をリクエストできます。

ゲーム状態を保存する方法を質問している場合、私はNSDictionaryの大ファンであり、継続してゲームエンジンによって値を簡単に再読み取りできます。

NSMutableDictionary *saveDict = [NSMutableDictionary dictionary];
[saveDict setValue: [NSNumber numberWithInt: currentScore] forKey: @"currentScore"];
// etc...
[saveDict writeToFile: saveFilePath atomically: YES];

必要に応じて、「署名」(つまり、md5など)を追加して、ゲームを続行し、誰かがファイルをだまして不正行為を試みていないことを確認できます。


1

私はそうはしません。アプリが終了するときではなく、ゲームにとって意味のあるときに保存してください。たとえば、これがターンベースのゲームである場合、各ターンの終わりにセーブします。レベルベースのゲームの場合は、各レベルの最後に保存します。これにはいくつかの理由があります。

  • モバイルの使用は非常に予測不可能です。はい、アプリの終了時にiPhone SDKから通知を受けますが、途中で発生する可能性があります。また、移行は単に「終了」するだけでなく、通話の受信やテキストの取得なども行います。
  • アプリの終了時にゲームをシャットダウンする時間とリソースが非常に限られています。そのほとんどは、ゲームを一時停止してメモリをクリーンアップするだけで消費されます。ゲームの状態を保存してその負荷を増やす必要はありません。
  • ほとんどのゲームには、保存に意味のある自然な一時停止があります。これらの一時停止を利用してゲームの状態をシームレスに保存でき、ユーザーは追加のリソースを消費していることに気付くことはありません。
  • ゲームのプレイ中に段階的に保存することにより、保存するデータの量は保存ごとに少なくなります。

1

次に、「マップ」クラスと「プレーヤー」クラスの例にNSCodingプロトコルを実装する方法の例を示します。

http://deadpanic.com/howtosave

次に、DennisのNSKeyedArchiverメソッドを使用してオブジェクトを保存できます。

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