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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Create Your Own Level Editor: Part 1/3
55 mins
- Getting Started
- Choosing a File Format to Save Your Level Data
- Calculating the Position of Your Pineapples
- Setting ID and Damping Parameters for the Pineapples
- Setting up Your Rope Parameters
- Putting Your XML File Format Together
- Creating Your XML File Handler
- Create a Handler for File Access
- File Handler: Getting the Full Path to a File
- File Handler: Checking if a File Exists
- File Handler: Getting the Path for an Existing File
- Creating Model Classes for Game Objects
- Creating the Pineapple Model Class
- Creating the Pineapple Model Class
- Loading the Level Data File
- Loading Pineapple Information into Model Classes
- Loading Rope Information into Model Classes
- Displaying Your Pineapple Objects On-screen
- Displaying Your Rope Objects On-screen
- Where to Go From Here?
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:
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.