In Listing 3–28, you saw code for pausing the game when the iPhone gets aninterrupting notification or when it is locked, and code for resuming the game. This codealso called the saveGameState and loadGameState methods in the view controller. Thissection will examine these methods and explain one technique for saving and loadinggame state with the Cocoa Touch frameworks.
Cocoa Touch provides the class NSUserDefaults for saving data and looking it up at alater time. You obtain an instance to the default data store with the NSUserDefaultsclass method standardUserDefaults. Then you use this instance with methods likesetObject:forKey:, setInteger:forKey:, and setDouble:forKey:, to assign each pieceof data you want to save a key and a value. Later on, you use the key to read the data,using the default data store instance with a method such objectForKey:, stringForKey:,integerForKey:, or doubleForKey:. Listing 3–29 shows an implementation of themethods saveGameState and loadGameState using NSUserDefaults.
Listing 3–29. Implementing saveGameState and loadGameState using NSUserDefaultsNSString *kLivesKey = @"IVBrickerLives";
NSString *kScoreKey = @"IVBrickerScore";
- (void)saveGameState {
[[NSUserDefaults standardUserDefaults] setInteger:lives forKey:kLivesKey];
[[NSUserDefaults standardUserDefaults] setInteger:score forKey:kScoreKey];
}
- (void)loadGameState {
lives = [[NSUserDefaults standardUserDefaults] integerForKey:kLivesKey];
livesLabel.text = [NSString stringWithFormat:@"%d", lives];
score = [[NSUserDefaults standardUserDefaults] integerForKey:kScoreKey];
scoreLabel.text = [NSString stringWithFormat:@"%d", score];
}
Besides using saveGameState and loadGameState in the app delegate app termination,inactivate and reactivate notification methods, you should save game state when theuser loses or wins a game. Just insert a call to saveGameState in the gameLogic methodin the code sections for winning or losing. Listing 3–30 has the necessary changes to thecode in bold.
Listing 3–30. The changes to the game logic code.
if (!there_are_solid_bricks) {
[self pauseGame];
isPlaying = NO;
lives = 0;
[self saveGameState];
messageLabel.text = @"You Win!";
messageLabel.hidden = NO;
}
if (ball.center.x > 310 || ball.center.x < 16)
ballMovement.x = -ballMovement.x;
if (ball.center.y < 32)
ballMovement.y = -ballMovement.y;
if (ball.center.y > 444) {
[self pauseGame];
isPlaying = NO;
lives--;
livesLabel.text = [NSString stringWithFormat:@"%d", lives];
if (!lives) {
[self saveGameState];
messageLabel.text = @"Game Over";
} else {
messageLabel.text = @"Ball Out of Bounds";
The viewDidLoad method should also be changed to load the game state at game launch
time. Listing 3–31 shows the changes to the viewDidLoad method in bold.
Listing 3–31. The changes made to the viewDidLoad method to load the game state at game launch.
- (void)viewDidLoad {
[super viewDidLoad];
[self loadGameState];
[self initializeBricks];
[self startPlaying];
}
By including the code in Listing 3–31, the game state gets loaded from previous runs ofthe app.
When designing your game, you should determine what kind of state it makes sense tosave in your game when the user is interrupted. In this chapter’s trivial game example,we save the score and the number of lives, by way of example. We could also save theball position and the current alpha value of the bricks.
A more complex arcade game with multiple levels would also save the current gamelevel. In a real-time combat strategy game, you could choose to save the state of eachgame unit at different checkpoints in the current mission. The point is to try as much aspossible to allow the player to resume play without needing to start the game or thecurrent level from the beginning.