Wie würden Sie Ihren Spielstatus beim Beenden für ein in Objective-C geschriebenes iPhone-Spiel speichern?
Wie würden Sie Ihren Spielstatus beim Beenden für ein in Objective-C geschriebenes iPhone-Spiel speichern?
Antworten:
Hier ist die Methode, die ich in meinen Spielen verwendet habe.
Zunächst muss jedes Objekt, das beibehalten werden muss, das NSCoding-Protokoll implementieren. Sie möchten nur Ihre Modelldaten und nichts Spezielles für den aktuellen Prozess speichern. Dies bedeutet, dass Sie keine Zeiger oder Ressourcen-IDs beibehalten können, die Ihnen das Betriebssystem zur Laufzeit zur Verfügung stellt. Bei den Zeigern können Sie dies leicht beheben, indem Sie nur sicherstellen, dass Sie die Objekte codieren, auf die sie zeigen, anstatt die Zeiger selbst. Für andere Ressourcen benötigen Sie eine Möglichkeit, Ihr Objekt zur Laufzeit mit der neuen Ressource zu verbinden.
Stellen Sie zweitens sicher, dass auf alle Ihre Spielobjekte über ein einziges Root-Objekt zugegriffen werden kann. Dieses Objekt kann beispielsweise ein Master-Objekt für den gesamten Spielstatus sein. Eine andere Möglichkeit besteht darin, dass Sie sie in einer der Foundation-Auflistungsklassen (NSMutableArray, NSMutableSet, NSMutableDictionary) speichern können.
Wenn Sie benachrichtigt werden, dass Ihre Anwendung in den Hintergrund verschoben wird (applicationDidEnterBackground), müssen Sie NSKeyedArchiver verwenden, um den gesamten Status in einer Datei zu speichern. Diese Datei sollte sich im Dokumentenverzeichnis für Ihre Anwendung befinden. Hier ist ein bisschen Code, um zu zeigen, wie das gemacht wird:
NSArray *docDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [docDirectories objectAtIndex:0];
NSString *saveFile = [docsPath stringByAppendingPathComponent:SAVE_STATE_FILENAME];
[NSKeyedArchiver archiveRootObject:gameState toFile:saveFile;
Wenn Sie feststellen, dass Sie wieder in den Vordergrund zurückgekehrt sind, sollten Sie die Sicherungsdatei entfernen, um beim nächsten Start Ihrer Anwendung Verwirrung zu vermeiden.
Beim Start der Anwendung müssen Sie überprüfen, ob die Sicherungsdatei vorhanden ist. Wenn Sie eine haben, laden Sie sie wie folgt auf:
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];
Abhängig von Ihrem Design müssen Sie möglicherweise den Spielstatus durchlaufen und alle Ressourcen erneut verbinden, die Sie nicht beibehalten konnten. Dies hängt wirklich davon ab, wie sauber Ihr Modellcode von Ihrem Rendering-Code getrennt ist.
An diesem Punkt möchten Sie Ihr Spiel möglicherweise in einen angehaltenen Zustand versetzen, je nachdem, welche Art von Spiel Sie machen.
Hoffentlich hilft dies jemand anderem, der versucht, das Speichern von Spielen auf dem iPhone zu implementieren.
Das Speichern des Spielstatus ist eine komplexe Frage, die stark davon abhängt, wie Sie Ihr Spiel selbst einrichten.
Speziell auf dem iPhone müssten Sie sich nur -(void)applicationWillTerminate:
in Ihre einbinden UIApplicationDelegate
, um zu erkennen, wann die Anwendung beendet wird, von Benutzeraktionen oder auf andere Weise. Sie haben jedoch nur wenig Zeit, um Ihre Arbeit zu erledigen, bevor das Betriebssystem Ihren Prozess beendet.
Das hängt weitgehend davon ab, wie Ihr Spiel codiert wurde. Behalten Sie ein paar Ivar oder etwas Wesentlicheres im Auge?
Wenn es nur ein paar Ivar sind, würde ich sie wahrscheinlich auf eine Liste im Hintergrund schreiben und diese beim Start laden.
Wenn es mehr Ivars gibt, sind Sie mit CoreData möglicherweise besser dran (und / oder speichern ihre Werte, wenn sie sich ändern, anstatt zu versuchen, alles in das Schließfenster einzupassen).
Genauso wie Sie es speichern, wenn der Benutzer ein Speicherspiel stößt, ohne es zu beenden.
Ist diese Frage, wie man den Spielstatus speichert? Oder wie mache ich etwas beim App-Exit?
Für letzteres lautet die Antwort: appWillTerminate (oder appWillResignActive). In iOS4 oder höher können Sie zusätzliche Zeit anfordern (Google "iOS-4 zusätzliche Zeit anfordern"), wenn das Speichern Ihres Spiels eine Weile dauert.
Wenn Sie sich fragen, wie Sie den Spielstatus überhaupt speichern können, bin ich ein großer Fan von NSDictionary, um Werte zu speichern, die von der Game-Engine einfach weiter gelesen werden können, wenn Sie fortfahren.
NSMutableDictionary *saveDict = [NSMutableDictionary dictionary];
[saveDict setValue: [NSNumber numberWithInt: currentScore] forKey: @"currentScore"];
// etc...
[saveDict writeToFile: saveFilePath atomically: YES];
Wenn Sie möchten, können Sie eine „Signatur“ (hinzufügen dh , wie md5 oder ähnliches) auf Spiel , um sicherzustellen , weiterhin sicherstellen , dass jemand mit der Datei nicht ausgemistet hat , um zu versuchen zu betrügen.
Ich würde sagen nicht. Speichern Sie es, wenn es für das Spiel sinnvoll ist, nicht, wenn die App beendet wird. Wenn dies beispielsweise ein rundenbasiertes Spiel ist, speichern Sie es am Ende jeder Runde. Wenn es sich um ein Level-basiertes Spiel handelt, speichern Sie es am Ende jedes Levels. Dafür gibt es mehrere Gründe:
Hier ist ein Beispiel für die Implementierung des NSCoding-Protokolls für einige Beispielklassen "map" und "player":
http://deadpanic.com/howtosave
Anschließend können Sie die Objekte mit der NSKeyedArchiver-Methode von Dennis speichern.