Objective-C ile iPhone'da çıkışta oyun durumunu saklama


Yanıtlar:


7

İşte oyunlarımda kullandığım yöntem.

İlk olarak, kalıcı olması gereken her nesne NSCoding protokolünü uygulamalıdır. Sadece model verilerinizi saklamak istiyorsunuz ve mevcut işleme özgü bir şey yok. Bu, işletim sisteminin size çalışma zamanında verdiği işaretçileri veya kaynak kimliklerini kaldıramayacağınız anlamına gelir. İşaretçiler için, işaretçilerin kendileri yerine işaret ettikleri nesneleri kodladığınızdan emin olarak bunu kolayca düzeltebilirsiniz. Diğer kaynaklar için, çalışma zamanında nesnenizi yeni kaynağa bağlamanın bir yoluna ihtiyacınız olacaktır.

İkinci olarak, tüm oyun nesnelerinize tek bir kök nesne üzerinden erişilebildiğinden emin olun. Bu nesne, örneğin tüm oyun durumu için bir ana nesne olabilir. Başka bir olasılık, bunları Foundation koleksiyon sınıflarından birinde (NSMutableArray, NSMutableSet, NSMutableDictionary) saklayabilmenizdir.

Uygulamanızın arka plana geçtiğini bildirdiğinizde (applicationDidEnterBackground), tüm durumu bir dosyaya kaydetmek için NSKeyedArchiver kullanmanız gerekir. Bu dosya, uygulamanızın belgeler dizininde olmalıdır. İşte bunun nasıl yapıldığını göstermek için biraz kod:

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

Ön plana geri döndüğünüzü algıladığınızda, uygulamanızın bir sonraki açılışında karışıklığı önlemek için kaydetme dosyasını kaldırmanız gerekir.

Uygulama başlatıldığında, kayıt dosyasının varlığını kontrol etmeniz gerekir. Eğer bir tane varsa, böyle yüklersiniz:

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

Tasarımınıza bağlı olarak, oyun durumunu gözden geçirmeniz ve devam edemediğiniz kaynakları yeniden bağlamanız gerekebilir. Bu gerçekten, model kodunuzun oluşturma kodunuzdan ne kadar temiz ayrıldığına bağlıdır.

Bu noktada, ne tür bir oyun yaptığınıza bağlı olarak oyununuzu duraklatılmış bir duruma getirmek isteyebilirsiniz.

Umarım bu, iPhone'da oyun tasarrufu yapmaya çalışan başka birine yardımcı olur.


2

Oyun durumunun depolanması, oyununuzu nasıl ayarladığınıza büyük ölçüde bağlı olan karmaşık bir sorudur.

Özellikle iPhone'da , uygulamanın ne zaman çıkacağını, kullanıcı işleminden veya başka bir şekilde yakalamak -(void)applicationWillTerminate:için içine girmeniz UIApplicationDelegategerekir. Yine de işletim sistemi sürecinizi öldürmeden önce işinizi yapmak için kısa bir süreniz vardır.


2
applicationWillTerminate yalnızca çoklu görevleri desteklemeyen uygulamalar veya 4.0 öncesi SDK için çalışır. 4.0 sonrası kod ile applicationDidEnterBackground kullanmak daha iyidir.
Dennis Munsie

1

Bu büyük ölçüde oyununuzun nasıl kodlandığına bağlı olacaktır. Birkaç ivar veya daha önemli bir şey mi takip ediyorsunuz?

Sadece birkaç ivarsa, onları muhtemelen arka planda bir plist'e yazar ve başlangıçta yüklerim.

Daha fazla ivar varsa, CoreData ile daha iyi olabilirsiniz (ve / veya her şeyi kapat penceresine sığdırmak yerine değiştikçe değerlerini kaydedebilirsiniz).


İşletim sisteminin size kapanmasını sağladığı zamanla çok şey yapabilirsiniz. O zaman cevabımda tarif ettiğim yöntemi kullanarak birkaç oyun nesnesini (en azından birkaç yüz) devam ettirebildim. Yavaş 1G iPod touch'ta bile. Yaptığınız oyunun türüne bağlı olarak, CoreData çözümü, uygulama sonlandırıldığında daha iyi çalışabilir, ancak daha yavaş oyun oynama pahasına.
Dennis Munsie

1

Aynı şekilde, kullanıcı bir kaydetme oyununu çıkmadan çıkardığında kaydettiğiniz gibi kaydedin.

Bu soru oyun durumunun nasıl kaydedileceği ile ilgili mi? Veya uygulama çıkışında bir şey nasıl yapılır?

İkincisi için cevap şudur: appWillTerminate (veya appWillResignActive.) İOS4 veya sonraki bir sürümde, kaydetme oyununuz biraz zaman alıyorsa ek süre isteyebilirsiniz (Google "iOS-4 ek süre isteyin").

Oyun durumunu nasıl kaydedeceğinizi soruyorsanız, devam eden oyun motoru tarafından kolayca okunabilen değerleri saklamak için NSDictionary büyük bir hayranıyım.

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

İsterseniz , birisinin hile yapmaya çalışmak için dosyayla uğraşmadığından emin olmak için oyunun devam ettiğini doğrulamak için bir "imza" ( yani md5 veya benzeri gibi) ekleyebilirsiniz.


1

Yapma derdim. Uygulamadan çıkarken değil, oyun için anlamlı olduğunda kaydedin. Örneğin, bu sıra tabanlı bir oyunsa, her turun sonunda kaydedin. Seviye tabanlı bir oyunsa, her seviyenin sonunda kaydedin. Bunun birkaç nedeni var:

  • Mobil kullanım çok öngörülemez. Evet, uygulama kapanırken iPhone SDK tarafından bilgilendirilirsiniz, ancak her şeyin ortasında olabilir ve geçiş sadece "çıkmaz", aynı zamanda bir çağrı alır, bir metin alır, vb.
  • Uygulama çıkışında oyununuzu kapatmak için çok sınırlı zamanınız ve kaynaklarınız var. Bunların çoğu muhtemelen oyununuzu duraklatmak ve hafızayı temizlemekle tüketilecektir. Oyun durumunu kaydederek bu yüke eklemenize gerek yok.
  • Çoğu oyunda tasarruf için anlamlı olan doğal duraklamalar vardır. Oyun durumunu sorunsuz bir şekilde saklamak için bu duraklamalardan yararlanabilirsiniz ve kullanıcı hiçbir zaman ekstra kaynak tükettiğinizi fark etmez.
  • Oyun sırasında aşamalı olarak kaydedildiğinde, kaydedilecek veri miktarı her kayıt için daha az olacaktır.

1

Bazı örnek "map" ve "player" sınıfları için NSCoding protokolünün nasıl uygulanacağına ilişkin bir örnek:

http://deadpanic.com/howtosave

Sonra nesneleri Dennis'in NSKeyedArchiver yöntemini kullanarak kaydedebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.