Memorizzare lo stato del gioco all'uscita su iPhone con Objective-C


Risposte:


7

Ecco il metodo che ho usato nei miei giochi.

Innanzitutto, ogni oggetto che deve essere persistito deve implementare il protocollo NSCoding. Si desidera archiviare solo i dati del modello e nulla di specifico per il processo corrente. Ciò significa che non è possibile persistere puntatori o eventuali ID risorse che il sistema operativo fornisce in fase di esecuzione. Per i puntatori puoi risolverlo facilmente assicurandoti di codificare gli oggetti a cui puntano anziché i puntatori stessi. Per altre risorse, avrai bisogno di un modo per collegare il tuo oggetto alla nuova risorsa in fase di esecuzione.

In secondo luogo, assicurati che tutti gli oggetti di gioco siano accessibili tramite un singolo oggetto radice. Questo oggetto potrebbe essere un oggetto master per l'intero stato del gioco, ad esempio. Un'altra possibilità è che sia possibile memorizzarli in una delle classi di raccolta Foundation (NSMutableArray, NSMutableSet, NSMutableDictionary).

Quando ricevi una notifica che l'applicazione si sta spostando in background (applicationDidEnterBackground), dovrai utilizzare NSKeyedArchiver per salvare l'intero stato in un file. Tale file dovrebbe trovarsi nella directory dei documenti per l'applicazione. Ecco un po 'di codice per mostrare come è fatto:

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

Quando rilevi di essere tornato in primo piano, dovresti rimuovere il file di salvataggio per evitare confusione al successivo avvio dell'applicazione.

All'avvio dell'applicazione, è necessario verificare l'esistenza del file di salvataggio. Se ne hai uno, lo carichi in questo modo:

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];

A seconda del tuo progetto, potresti dover attraversare lo stato del gioco e riconnettere tutte le risorse che non potresti persistere. Questo dipende in realtà dalla separazione netta del codice del modello dal codice di rendering.

A questo punto, potresti voler mettere il gioco in uno stato di pausa, a seconda del tipo di gioco che stai realizzando.

Spero che questo aiuti qualcun altro là fuori che sta cercando di implementare il salvataggio del gioco su iPhone.


2

Come memorizzare lo stato del gioco è una domanda complessa che dipende fortemente da come si configura il gioco stesso.

Su iPhone in particolare, si sarebbe solo dovuto collegare in -(void)applicationWillTerminate:nella vostra UIApplicationDelegateper prendere quando l'applicazione uscirà, da azione dell'utente o in altro modo. Tuttavia, hai poco tempo per svolgere il tuo lavoro prima che il sistema operativo interrompa il processo.


2
applicationWillTerminate funziona solo per le applicazioni che non supportano il multitasking o per l'SDK pre-4.0. È meglio usare applicationDidEnterBackground con codice post-4.0.
Dennis Munsie,

1

Ciò dipende in gran parte da come il tuo gioco è stato codificato. Tieni traccia di qualche ivar o di qualcosa di più sostanziale?

Se sono solo pochi ivar, probabilmente li scriverei su un plist in background e lo caricare all'avvio.

Se ci sono più ivar, potresti stare meglio con CoreData (e / o salvare i loro valori mentre cambiano invece di cercare di adattare tutto nella finestra di chiusura).


Puoi effettivamente fare molto con il tempo che il sistema operativo ti dà di spegnere. Sono stato in grado di persistere un bel po 'di oggetti di gioco (almeno alcune centinaia) usando il metodo che ho descritto nella mia risposta in quel momento. Anche sul lento iPod touch 1G. A seconda del tipo di gioco che stai realizzando, la soluzione CoreData potrebbe funzionare meglio quando l'app viene chiusa, ma a spese di un gioco più lento.
Dennis Munsie,

1

Allo stesso modo in cui lo salvi quando l'utente salta un gioco di salvataggio senza uscire.

Questa domanda è su come salvare lo stato del gioco? O come fare qualcosa all'uscita dall'app?

Per quest'ultimo, la risposta è: appWillTerminate (o appWillResignActive.) In iOS4 o versioni successive, puoi richiedere tempi supplementari (Google "iOS-4 richiesta tempi supplementari") se il tuo gioco di salvataggio impiega un po 'di tempo.

Se mi stai chiedendo come salvare lo stato del gioco, sono un grande fan di NSDictionary per memorizzare i valori facilmente rileggibili dal motore di gioco su continue.

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

Se vuoi, puoi aggiungere una "firma" (ad esempio , come md5 o simile) per verificare sul gioco continuare ad assicurarti che qualcuno non abbia confuso il file per provare a imbrogliare.


1

Direi di no. Salvalo quando ha senso per il gioco, non quando l'app è in uscita. Ad esempio, se si tratta di un gioco a turni, salva alla fine di ogni turno. Se si tratta di un gioco basato sul livello, salva alla fine di ogni livello. Ci sono un paio di ragioni per questo:

  • L'uso del cellulare è molto imprevedibile. Sì, riceverai una notifica dall'SDK di iPhone quando l'app si sta chiudendo, ma potrebbe trovarsi nel mezzo di qualsiasi cosa e la transizione non sta semplicemente "uscendo", ma sta anche ricevendo una chiamata, ricevendo un SMS, ecc.
  • Hai tempo e risorse molto limitati per chiudere il gioco all'uscita dall'app. La maggior parte di ciò verrà probabilmente consumata solo con la pausa del gioco e la pulizia della memoria. Non c'è bisogno di aggiungere a quel carico salvando lo stato del gioco.
  • La maggior parte dei giochi ha pause naturali che hanno senso per il salvataggio. Puoi approfittare di queste pause per memorizzare senza problemi lo stato del gioco e l'utente non noterà mai che stai consumando risorse extra.
  • Salvando in modo incrementale durante il gioco, la quantità di dati da salvare sarà più piccola per salvataggio.

1

Ecco un esempio di come implementare il protocollo NSCoding per alcune classi "map" e "player" di esempio:

http://deadpanic.com/howtosave

Quindi è possibile salvare gli oggetti utilizzando il metodo NSKeyedArchiver di Dennis.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.