Як би ви зберігали свій ігровий стан при виході для гри на iPhone, написаної в Objective-C?
Як би ви зберігали свій ігровий стан при виході для гри на iPhone, написаної в Objective-C?
Відповіді:
Ось метод, який я використовував у своїх іграх.
По-перше, кожен об'єкт, який потрібно зберегти, повинен реалізувати протокол кодування NSC. Ви хочете зберігати лише дані своєї моделі та нічого конкретного для поточного процесу. Це означає, що ви не можете зберігати покажчики або будь-які ідентифікатори ресурсів, які ОС дає вам під час виконання. Для покажчиків ви можете це легко виправити, просто переконавшись, що ви кодуєте об'єкти, на які вони вказують, замість самих покажчиків. Для інших ресурсів вам знадобиться спосіб підключення вашого об'єкта до нового ресурсу під час виконання.
По-друге, переконайтесь, що до всіх ваших ігрових об’єктів можна отримати доступ через один кореневий об’єкт. Наприклад, цей об'єкт може бути головним об'єктом для всього ігрового стану. Інша можливість полягає в тому, що ви можете зберігати їх в одному з колекційних класів 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.
Як зберігати стан гри - це складне питання, яке сильно залежить від того, як ви налаштували свою гру.
На iPhone конкретно, ви просто повинні вклинитися -(void)applicationWillTerminate:
в вашому UIApplicationDelegate
зловити , коли додаток буде виходити з дій користувача або іншим чином . У вас є невеликий проміжок часу, щоб виконати свою роботу, перш ніж ОС вб'є ваш процес.
Це багато в чому залежатиме від того, як була закодована ваша гра. Ви відстежуєте кілька іварів чи щось більш суттєве?
Якщо це всього лише кілька іварів, я, мабуть, напишу їх у пліст на тлі та завантажую його при запуску.
Якщо є більше ivars, вам може бути краще з CoreData (та / або збереження їх значень, коли вони змінюються, а не намагатися помістити все у закрите вікно).
Тим самим способом ви зберігаєте його, коли користувач натискає гру збереження, не виходячи з неї.
Це питання про те, як зберегти ігровий стан? Або як зробити щось при виході з програми?
На останнє, відповідь: appWillTerminate (або appWillResignActive.) В iOS4 або новіших версіях ви можете запитати додатковий час (Google "iOS-4 запит на додатковий час"), якщо ваша збережена гра займе певний час.
Якщо ви запитуєте, як взагалі зберегти ігровий стан, я великий фанат NSDictionary, щоб зберігати значення, які легко перечитуються ігровим механізмом при продовженні.
NSMutableDictionary *saveDict = [NSMutableDictionary dictionary];
[saveDict setValue: [NSNumber numberWithInt: currentScore] forKey: @"currentScore"];
// etc...
[saveDict writeToFile: saveFilePath atomically: YES];
Якщо ви хочете, ви можете додати "підпис" ( наприклад , як md5 або подібне), щоб перевірити, чи продовжується гра, щоб переконатися, що хтось не заблокував файл, щоб спробувати обдурити.
Я б сказав, що ні. Збережіть це, коли це має сенс для гри, а не тоді, коли додаток закривається. Наприклад, якщо це покрокова гра, тоді зберігайте в кінці кожного ходу. Якщо це гра на основі рівня, збережіть в кінці кожного рівня. Для цього є кілька причин:
Ось приклад того, як реалізувати протокол NSCoding для деяких прикладів класів "map" та "player":
http://deadpanic.com/howtosave
Потім ви можете зберегти об'єкти за допомогою методу NSKeyedArchiver Dennis.