Tuesday 9 August 2011

How to easily keep track of save games

This is just a simple method on how to create local save files for a level system. For the app I'm making, there are several levels and the player only unlocks the next level if the previous one is complete. To do this I'm just using plists.

Create plists with this sort of structure. There will be 1 plist for saves.




Now create a class which will be used to manage this data.

//
//  scoreAndSaveClass.h
//  Ant Run
//
//  Created by Peter Lockhart on 05/08/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>


@interface scoreAndSaveClass : NSObject {

}
+(void) getPathOfSaveList;
+(BOOL) checkCompletedLevels:(int) thisIndex andTheDifficulty:(NSString*) difficulty;
+(void) setLevelCompleted:(int) thisIndex andTheDifficulty:(NSString*) difficulty;


@end

//
//  scoreAndSaveClass.m
//  Ant Run
//
//  Created by Peter Lockhart on 05/08/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "scoreAndSaveClass.h"


@implementation scoreAndSaveClass

NSString* pathOfPlist;

+(void) getPathOfSaveList{
    
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    pathOfPlist = [documentsDirectory stringByAppendingPathComponent:@"saveFiles.plist"]; 
    
    NSFileManager *fileManager = [NSFileManager defaultManager];
    
    if (![fileManager fileExistsAtPath: pathOfPlist]) 
    {
        NSString * bundle = [[NSBundle mainBundle] pathForResource: @"saveFiles" ofType:@"plist"];
        
        [fileManager copyItemAtPath:bundle toPath: pathOfPlist error:&error]; 
    }
}


+(BOOL) checkCompletedLevels:(int) thisIndex andTheDifficulty:(NSString*) difficulty{
    //set the string  of plathofPlist to be that of the level plist
    [self getPathOfSaveList];
    
    //this is the root of the plist
    NSMutableDictionary * indexOfPlist = [[[NSMutableDictionary alloc] initWithContentsOfFile:pathOfPlist] autorelease];
    
    //get the array under the level category (defined by the string "difficulty", which is set when the method is called)
    NSMutableArray *arrayOfLevelSaves = [indexOfPlist objectForKey:difficulty];
    //get the boolean for the level that needs checked
    BOOL test = [[arrayOfLevelSaves objectAtIndex:thisIndex] boolValue];
    
    //check if level is completed
    if (test == YES) {
        return YES;
    }
    return NO;
}

+(void) setLevelCompleted:(int) thisIndex andTheDifficulty:(NSString*) difficulty{
    [self getPathOfSaveList];
    
    NSMutableDictionary * indexOfPlist = [[[NSMutableDictionary alloc] initWithContentsOfFile:pathOfPlist] autorelease];
    
    NSMutableArray *arrayOfLevelSaves = [indexOfPlist objectForKey:difficulty];
    
    //create a temp boolean to replace the original value of the array of saves
    BOOL done = YES;
    //make the level specified be completed
    [arrayOfLevelSaves replaceObjectAtIndex:thisIndex withObject:[NSNumber numberWithBool:done]];

    //update the dictionary in the plist so that its array of save files is the newest version
    [indexOfPlist setValue:arrayOfLevelSaves forKey:difficulty];
    
    //write the plist to memory
    [indexOfPlist writeToFile: pathOfPlist atomically:YES];
    
}
@end

Don't be put off by it, its really not too bad.

I've declared a string at the top of the .m file, which will hold the path of the save file. This will change depending on if you are accessing the save file plist or the scores plist (which will be in a later tutorial). The getPathOfSaveList function will not get called by you, so don't worry about remembering to call it (saves headache when we implement local scores later).

The code in the function is pretty self explanatory. It searches in the iphones memory to find the specified file and if it doesn't exists then it creates the file (but it should always exist because we created the plist in xcode in the project file).


 

No comments:

Post a Comment