Create Your Own Level Editor: Part 1/3

In this tutorial, you’ll learn how to make a level editor for the Cut the Rope clone that was previously covered on this site. Using the level editor you can easily make new levels. All you have to do is drag and drop the ropes and pineapples to where you like them. By Barbara Reichart.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 6 of this article. Click here to view the first page.

Create a Handler for File Access

If you want to read and write files, you first need to load them from their location in the file system. Since working with files is something that you’ll do many times in your level editor, you’ll create a new class that encapsulates this file handling functionality.

Your file handler should cover the following scenarios:

  • finding the full file path to a filename
  • checking for the existence of a file
  • creating a folder

Implement your file handler as follows.

Create a new file with the iOS\Cocoa Touch\Objective-C class template under the Utilities group. Name the class FileHelper, and make it a subclass of NSObject.

Open FileHelper.h and replace its contents with the following:

@interface FileHelper : NSObject

+(NSString*) fullFilenameInDocumentsDirectory:(NSString*) filename;
+(BOOL) fileExistsInDocumentsDirectory:(NSString*) fileName;
+(NSString *)dataFilePathForFileWithName:(NSString*) filename withExtension:(NSString*)extension forSave:(BOOL)forSave;
+(void) createFolder:(NSString*) foldername;

@end

These are the methods that FileHelper provides for doing common file-related tasks.

Next, you need to implement each of the above methods. This requires some knowledge of the iOS file system.

On a desktop computer, it is up to the programmer to decide the location of each file as desired. However, in iOS each app has to stick to a folder structure defined by Apple.

Basically, everything is stored under four folders:

  • /AppName.app: The bundle directory containing your app and all its resource files. This folder is read-only.
  • /Documents/: Storage for critical documents that your app cannot recreate, such as user-generated content. This folder is backed up by iTunes.
  • /Library/: A folder completely hidden from the user that’s used to store app-specific information that should not be exposed to the user.
  • /tmp/: For temporary files that do not need to persist between different sessions of your app.

If you want more detailed insight into the file structure you can look at Apple’s Documentation here:
File System Overview on iOS.

Okay, time for a quick pop quiz. Looking at the four storage areas above, which ones will your level editor need to access?

[spoiler]

  • Bundle directory: For reading preset level XML files from the app.
  • Documents directory: For saving edited files.

[/spoiler]

Now that you have a better idea about the structure of the iOS file system, you can implement your file handler methods.

File Handler: Getting the Full Path to a File

Add the following method implementation to FileHelper.m:

+(NSString*) fullFilenameInDocumentsDirectory:(NSString*) filename {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectoryPath = [paths objectAtIndex:0];
    NSString* filePath = [documentsDirectoryPath stringByAppendingPathComponent:filename];
    return filePath;
}

The above is a class method. Class methods are directly associated with a class instead of an instance. To call the method, you use the class name instead of an instance of the class. You indicate to the compiler that a method is a class method by using a + instead of a at the beginning of the method declaration.

The above method returns the full path for a filename in the documents directory as an NSString.

NSSearchPathForDirectoriesInDomains() returns a list of directories for a specific search path and a domain mask. In this case, you ask for the user’s Documents directory by using NSDocumentDirectory as the search path and NSUserDomainMask as the mask.

The return value of NSSearchPathForDirectoriesInDomains() is not just a single directory path but an array. You only care about the first result, so you simply select the first element and append the filename to get the full path to the file.

Now you can try out your file handler class and see where your own Documents directory lives.

Add the following code to init in CutTheVerletGameLayer.mm:

// Add to the top of the file
#import "FileHelper.h"
...

-(id) init
{
    if( (self=[super init])) {
        // Add the following lines
        NSString* filePath = [FileHelper fullFilenameInDocumentsDirectory:@"helloDirectory.xml"];
        NSLog(@"%@", filePath);
	...
    }
}

Build and run your project. You should see the file path in the console, like so:

Full file path to helloDirectory.xml in documents directory

Full file path to helloDirectory.xml in documents directory

If you run using the simulator, you can easily check the contents of the document directory. Just copy the path to the file, omitting the actual filename, right click on the Finder on your dock and select Go to folder…. Paste in the file path and press Enter.

Right now the Documents folder for your app is probably empty, but you’ll soon add some files to it.

On to the next method — checking if a file exists.

File Handler: Checking if a File Exists

Add the following method to FileHelper.m:

+(BOOL) fileExistsInDocumentsDirectory:(NSString*) filename {
    NSString* filePath = [FileHelper fullFilenameInDocumentsDirectory:filename];
    return [[NSFileManager defaultManager] fileExistsAtPath: filePath];
}

This one is rather simple. You take the full file path given to you by fullFilenameInDocumentsDirectory:, and ask the file manager whether a file with this name exists.

You can test this method by adding the following code to CutTheVerletGameLayer.mm:

-(id) init {
    if( (self=[super init])) {
        NSString* filename = @"helloDirectory.xml";
        BOOL fileExists = [FileHelper fileExistsInDocumentsDirectory:filename];
        if (fileExists) {
            NSLog(@"file %@ exists", filename);
        } else {
            NSLog(@"file %@ does not exist", filename);
        }
        ...
    }
}

Build and run your app. Right now, the console output should show that the file does not exist.

If you want to test that your code really does discover the file when it exists, create an empty file with the correct name in the Documents directory. (You can access the Document directory via Finder as described above.)

Build and run your app again, and the console should now tell you that the file exists.

So far you have only accessed the Documents directory, but the app should load files from the app bundle directory just in case there is no user-generated file.

Why would you do this?

This allows your app to have an initial version of the files. You can put them into the main app bundle, and load them into the editor on first run, where you can change the contents and then save them to the Documents directory.

This is where the third method of the FileHelper class comes in.

Barbara Reichart

Contributors

Barbara Reichart

Author

Over 300 content creators. Join our team.