使用Objective-C在iPhone出口处存储游戏状态


Answers:


7

这是我在游戏中使用的方法。

首先,每个需要保留的对象必须实现NSCoding协议。您只想存储模型数据,而不要存储当前过程的特定数据。这意味着您无法持久化操作系统在运行时为您提供的指针或任何资源ID。对于指针,只需确保您对它们指向的对象(而不是指针本身)进行编码,就可以轻松解决此问题。对于其他资源,您将需要一种在运行时将对象连接到新资源的方法。

其次,确保可以通过单个根对象访问所有游戏对象。例如,该对象可以是整个游戏状态的主对象。另一种可能性是,您可以将它们存储在Foundation集合类(NSMutableArray,NSMutableSet,NSMutableDictionary)中。

当通知您应用程序正在进入后台(applicationDidEnterBackground)时,您将需要使用NSKeyedArchiver将整个状态保存到文件中。该文件应位于您的应用程序的documents目录中。以下是一些代码来说明如何完成此操作:

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上实现游戏保存的人。


2

如何存储游戏状态是一个复杂的问题,在很大程度上取决于您如何设置游戏本身。

在iPhone特别,你只需要挂接到-(void)applicationWillTerminate:UIApplicationDelegate赶上当应用程序将退出,从用户操作或以其他方式。但是,在操作系统终止进程之前,您有很短的时间来完成工作。


2
applicationWillTerminate仅适用于不支持多任务处理的应用程序或4.0之前的SDK。最好将applicationDidEnterBackground与4.0后的代码一起使用。
丹尼斯·蒙西

1

那很大程度上取决于您的游戏编码方式。您是否正在跟踪一些错误或更重要的内容?

如果只是一些错误,我可能会在后台将它们写到plist并在启动时加载它。

如果存在更多错误,那么使用CoreData可能会更好(和/或在它们更改时保存它们的值,而不是尝试将所有内容都放入关闭的窗口中)。


您实际上可以在操作系统给您关机的时间上完成很多工作。使用当时我在回答中描述的方法,我能够保留很多游戏对象(至少几百个)。即使在速度较慢的1G iPod touch上。根据您制作的游戏类型,CoreData解决方案可能会在退出应用程序时更好地发挥作用,但会以降低游戏速度为代价。
丹尼斯·蒙西

1

与用户在不退出保存游戏的情况下保存保存内容的方式相同。

这是关于如何保存游戏状态的问题吗?还是在退出应用程序时如何做?

对于后者,答案是: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或类似)来验证游戏继续下去,以确保有人不与文件盖牌,试图作弊。


1

我会说不。在对游戏有意义的时候保存它,而不是在应用退出时保存。例如,如果这是一个基于回合的游戏,则在每个回合结束时保存。如果是基于关卡的游戏,请在每个关卡的末尾保存。造成这种情况的原因有两个:

  • 手机使用情况非常难以预测。是的,当应用程序关闭时,您会收到iPhone SDK的通知,但它可能处于任何中间状态,转换不仅是“退出”,而且还在接听电话,发送短信等。
  • 您在应用退出时关闭游戏的时间和资源非常有限。大部分可能只是暂停游戏和清理内存而消耗掉的。无需通过保存游戏状态来增加负载。
  • 大多数游戏都有自然的暂停时间,可以节省时间。您可以利用这些暂停来无缝存储游戏状态,并且用户永远不会注意到您正在消耗额外的资源。
  • 通过在游戏过程中逐步保存,每次保存将保存的数据量将更少。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.