Menyimpan status permainan saat keluar pada iPhone dengan Objective-C

10

Bagaimana Anda menyimpan status permainan saat keluar untuk permainan iPhone yang ditulis dalam Objective-C?

Dennis Munsie
sumber

Jawaban:

7

Inilah metode yang saya gunakan dalam game saya.

Pertama, setiap objek yang perlu dipertahankan harus mengimplementasikan protokol NSCoding. Anda hanya ingin menyimpan data model Anda dan tidak ada yang spesifik untuk proses saat ini. Ini berarti bahwa Anda tidak dapat mempertahankan pointer atau id sumber daya apa pun yang diberikan oleh OS saat runtime. Untuk pointer Anda dapat memperbaikinya dengan mudah hanya dengan memastikan bahwa Anda menyandikan objek yang mereka tuju bukan pointer itu sendiri. Untuk sumber daya lain, Anda akan memerlukan cara untuk menghubungkan objek Anda ke sumber daya baru saat runtime.

Kedua, pastikan bahwa semua objek game Anda dapat diakses melalui satu objek root. Objek ini bisa menjadi objek utama untuk seluruh kondisi permainan, misalnya. Kemungkinan lain adalah Anda dapat menyimpannya di salah satu kelas koleksi Foundation (NSMutableArray, NSMutableSet, NSMutableDictionary).

Ketika Anda diberi tahu bahwa aplikasi Anda bergerak ke latar belakang (applicationDidEnterBackground), Anda perlu menggunakan NSKeyedArchiver untuk menyimpan seluruh status file. File itu harus ada di direktori dokumen untuk aplikasi Anda. Berikut adalah sedikit kode untuk menunjukkan bagaimana hal itu dilakukan:

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

Ketika Anda mendeteksi bahwa Anda telah kembali ke latar depan, Anda harus menghapus file save untuk mencegah kebingungan saat aplikasi Anda diluncurkan.

Saat memulai aplikasi, Anda perlu memeriksa keberadaan file simpan. Jika Anda memilikinya, Anda memuatnya seperti ini:

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

Bergantung pada desain Anda, Anda mungkin perlu melewati kondisi permainan dan menyambungkan kembali sumber daya yang tidak dapat Anda pertahankan. Ini benar-benar tergantung pada seberapa bersih kode model Anda dari kode rendering Anda.

Pada titik ini, Anda mungkin ingin menempatkan permainan Anda ke dalam keadaan dijeda, tergantung pada jenis permainan yang Anda buat.

Semoga ini membantu orang lain di luar sana yang mencoba menerapkan penghematan permainan di iPhone.

Dennis Munsie
sumber
2

Cara menyimpan status permainan adalah pertanyaan kompleks yang sangat bergantung pada cara Anda menyiapkan game itu sendiri.

Di iPhone khusus, Anda hanya harus menghubungkan ke -(void)applicationWillTerminate:dalam Anda UIApplicationDelegateuntuk menangkap saat aplikasi akan keluar, dari tindakan pengguna atau sebaliknya. Anda memiliki waktu singkat untuk melakukan pekerjaan Anda sebelum OS akan mematikan proses Anda.

Tetrad
sumber
2
applicationWillTerminate hanya berfungsi untuk aplikasi yang tidak mendukung multitasking atau untuk SDK pra-4.0. Lebih baik menggunakan applicationDidEnterBackground dengan kode post-4.0.
Dennis Munsie
1

Itu akan sangat tergantung pada bagaimana game Anda dikodekan. Apakah Anda melacak beberapa ivar atau sesuatu yang lebih besar?

Jika hanya beberapa ivar, saya mungkin akan menuliskannya di plist di latar belakang dan memuatnya saat startup.

Jika ada lebih banyak ivars, Anda mungkin lebih baik dengan CoreData (dan / atau menyimpan nilai-nilai mereka saat mereka berubah daripada mencoba memasukkan semuanya ke jendela tutup).

BarrettJ
sumber
Anda benar-benar dapat menyelesaikan banyak hal dengan waktu yang diberikan OS kepada Anda untuk dimatikan. Saya dapat bertahan beberapa objek game (setidaknya beberapa ratus) menggunakan metode yang saya jelaskan dalam jawaban saya pada waktu itu. Bahkan pada iPod touch 1G yang lambat. Tergantung pada jenis permainan yang Anda buat, solusi CoreData dapat bekerja lebih baik untuk saat aplikasi berhenti, tetapi dengan mengorbankan bermain game lebih lambat.
Dennis Munsie
1

Cara yang sama Anda menyimpannya saat pengguna menabrak save-game tanpa keluar.

Apakah pertanyaan ini tentang cara menyimpan status permainan? Atau bagaimana melakukan sesuatu di app-exit?

Untuk yang terakhir, jawabannya adalah: appWillTerminate (atau appWillResignActive.) Di iOS4 atau yang lebih baru, Anda dapat meminta waktu tambahan (Google "iOS-4 meminta waktu tambahan") jika permainan simpanan Anda membutuhkan waktu.

Jika Anda bertanya bagaimana cara menyelamatkan game-state sama sekali, saya penggemar berat NSDictionary untuk menyimpan nilai-nilai yang mudah dibaca kembali oleh mesin-game pada lanjutan.

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

Jika mau, Anda dapat menambahkan "tanda tangan" ( mis. , Seperti md5 atau sejenisnya) untuk memverifikasi pada game, terus memastikan bahwa seseorang belum mengotori file untuk mencoba menipu.

Olie
sumber
1

Saya akan mengatakan tidak. Simpan saat masuk akal untuk gim, bukan saat aplikasi keluar. Misalnya, jika ini adalah game berbasis giliran, maka simpan di akhir setiap putaran. Jika ini adalah game berbasis level, simpan di akhir setiap level. Ada beberapa alasan untuk ini:

  • Penggunaan ponsel sangat tidak terduga. Ya, Anda akan diberi tahu oleh iPhone SDK ketika aplikasi ditutup, tetapi bisa saja di tengah-tengah apa pun, dan transisi tidak hanya "keluar" tetapi juga menerima panggilan, mendapatkan teks, dll.
  • Anda memiliki waktu dan sumber daya yang sangat terbatas untuk mematikan game saat keluar dari aplikasi. Sebagian besar dari itu mungkin akan dikonsumsi hanya dengan menjeda permainan Anda dan membersihkan memori. Tidak perlu menambah beban itu dengan menyimpan status game.
  • Sebagian besar permainan memiliki jeda alami yang masuk akal untuk disimpan. Anda dapat memanfaatkan jeda ini untuk menyimpan kondisi permainan dengan mulus, dan pengguna tidak akan pernah melihat bahwa Anda menghabiskan sumber daya tambahan.
  • Dengan menyimpan secara bertahap selama permainan, jumlah data yang akan disimpan akan lebih kecil per penyimpanan.
Chris Garrett
sumber
1

Berikut adalah contoh cara mengimplementasikan protokol NSCoding untuk beberapa contoh kelas "map" dan "player":

http://deadpanic.com/howtosave

Kemudian Anda dapat menyimpan objek menggunakan metode Dennis 'NSKeyedArchiver.

pukulan keras
sumber