Iphone Game Programming – Tutorial 12 – Saving State
I’ve managed to squeeze in one last small tutorial for 2009. I had a request on the blog for a tutorial on saving game state. This is only a quicky and I’ve built it on the code from Tutorial 11. It covers how I’ve used NSCoding to store game state which is really easy to do.
Tutorial 12 Project
I hope you enjoy it and have a great Christmas :o)
Upate 23/12/09: Kurt commented on the tutorial and pointed out that I am over retaining myObject when it is loaded from the decoder. As I am using self.myObject and the property is defined as retain, doing a further retain when reading it in would in fact leak myObject. I have changed the source code and removed the unnecessary retain. I don’t use self in the SLQ code and hence need the retain. More haste less speed they say :o)
Mike
47 Comments
Kurt on December 23rd, 2009
I think you are over-retaining myObject. In the header file, myObject is tagged with the “retain” attribute. When you load your object from the archived data, you use self.myObject assignment which will do the retain for you. You do not need the extra retain, and this can cause a leak.
In your Sir Lamorack’s Quest code, you do not use “self-dot” syntax, you just assign directly to variables, so you do need the explicit retain there. I’ll bet you just got in the habit of adding the retain here, and carried it over to your other example.
mike on December 23rd, 2009
Hi Kurt and thanks for the heads up. Your absolutely right that I’m over retaining it. I did just carry it over without thinking from my SLQ code, DOH!!!
I’ll make a note in the post :o)
Mike
RoberRM on December 24th, 2009
Thank you very much, Mike, for this early Xmas present. :)
Merry Christmas and a happy New Year to you too.
Kurt on December 25th, 2009
Hi Mike,
In my haste to point out a leak I forgot to say:
Thank you so much for your tutorials. Examples like these are a wonderful resource for new programmers. I would never have been able to write an iPhone app without people like you who post these examples. I hope you have a Merry Christmas and best wishes for a great 2010!
mike on December 25th, 2009
Cheers Kurt
People sharing their knowledge is how I have learnt SOO much over the years, so this is just a way for me to repay the community.
I hope you have a great Christmas too and a successful app filled new year.
Mike
PaulC on December 28th, 2009
Was it my request that this was a response to? Because it was exactly what I was looking for. Thankyou so much!
I hope you had a great Christmas, have an even better New Year.
Paul.
mike on December 28th, 2009
Hi Paul, yes, this was based on your request :o)
I’m glad it gave you what you needed. I did have a great Christmas and looking forward to an exciting new year. I hope you also had a great Christmas and wish you all the best with your projects in the new year :o)
Mike
Martin on December 29th, 2009
Hi Mike,
This is very useful for beginners like me. I am developing an Opengl based iPhone app. I have a question, i want to keep the home view background image as under the sea(i.e. live water image as background image), how can i do that? Do i need to have a sea water image in .gif format and add it as background because it should be live water flowing here and there, same like under sea?
mike on December 30th, 2009
Hi Martin
I’m not completely sure I understand your question, but it sounds like you want an animated background to your game?
If you are rendering in OpenGL there is no built in way to render an animated GIF. You would need to create your own animation using a sprite sheet.
If your background image is the full size of the screen then I would create one image that filled the entire screen, and then render smaller animated images on top where you want the water to be flowing etc.
There is a tutorial I’ve done on sprite sheets if you want to take a look through.
Hope that helps.
Mike
Martin on December 30th, 2009
Hi Mike,
Thanks a lot. Yes, i want an animated background with full screen. There is no specific place where should the water flow etc. instead it can simply look like under water.
mike on December 30th, 2009
Great, glad to gave you some ideas. To get started you could simply create a sprite sheet from the seperate images you have in your gif image and then just run that animation in the background.
When you start to get more advanced you can start to perform all sorts fancy effects using OpenGL e.g. render a simple underwater background and then use OpenGL to render a wobbly refractive effect over the top using that base image. This can all get very complex but some cool effects can be achieved.
Check out Pearl Diver in the Readers Game section to see the kind of underwater effects you can create. Not sure how they did them but they look good.
Mike
Martin on December 30th, 2009
Thanks Mike. As i can’t use a single animated image directly, i should have images separated out that water flow gif image as i) First static image can have only water. ii) Next image can have moving water kind of static image etc., atlast i should animate these images one by one using animation API’s? Are there any samples source to go through?
Starra on December 31st, 2009
Hi MIke,
Great tutorials. Me and a couple friends want to develope iphone games and your tutorials have been very helpful in getting the ground running.
One question, since I am still a beginner in Objective-C. When I run your code straight from the downloaded file, it runs fine. However, when I copied the files over to a new project, I get this warning.
“/Users/Starra/Documents/Project/2DShooter/MenuScene.m:31:0 /Users/Starra/Documents/Project/2DShooter/MenuScene.m:31: warning: incompatible Objective-C types ‘struct NSString *’, expected ‘struct UIImage *’ when passing argument 1 of ‘initWithImage:’ from distinct Objective-C type”
Shouldn’t the initwithImage function be expecting a NSString instead of UIImage like the warning suggest? I am confused.
Also, when I run the new project, somehow, I just get a white screen after the loading screen. The menu screen did not show up. I probably did something wrong when I moved the files or something, but just in case you have any idea what is going on.
Starra on December 31st, 2009
I found the problem to the warning. All I needed is to cast the initwithImage with a (Image*) in front.
Now I am stuck with the white screen problem. As I play with it more, I notice that the menu scene might have rendered, but somehow it is not shown because when I click the iphone button, as the app quit, there is a fade out sequence of the menu scene with all the menu item. Any ideas??
Thank for the help and Happy New year!!
mike on December 31st, 2009
Hi Starra
Do you have any code you can send me or an example project with the issue you are seeing and I can take a look.
Mike
Starra on December 31st, 2009
I did some googling around and found out that if I comment this line out…
“window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];”
in applicationDidFinishLaunching(), the app runs fine with the menu scene and everything. Not sure why that is though, since I was about to run your project straight from the downloaded files. Thanks Mike!
dilbertian on January 1st, 2010
Mike,
Trying to implement this into my program today and am making progress but don’t have it working quite yet. I have a question. If I were going to integrate this with something similar to your Tutorial 10 with which already has a call to [window addSubview:glView]; in the applicationDidFinishLaunching() routine, would I just add another line under that for MyObject to add another subview for that too? Here is an excerpt of that section of code:
[window addSubview:glView];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
Having some compilation issues with the viewController’s .view member at the moment so I can’t tell if it will work or not yet.
I just wanted to make sure I’m on the right path.
Thanks for putting this and all of the other tutorials together as well, it’s all VERY helpful and enlightening
Thanks!
-Dil
Anonymous on January 3rd, 2010
Any link to download the video directly instead of watching online?
Thank you.
benoitr007 on January 4th, 2010
Hi Mike,
Thanks again for the wonderful tutorials.
I would like to ask, will your book cover audio sessions in more depth, as I am having problems with the background music of my game, more specifically when I lock the phone. It just stops playing and doesn’t come back, and I also have lag issues.
Thank you
Benoit
mike on January 4th, 2010
Hi benoitr007, yes, the book is going to have a chapter on the SoundManager class as well as information on how I have implemented it in SLQ. SLQ uses OpenAL for location based sound e.g. when doors open and close the sound can be heard based on where the player is standing in relation to the door :o)
Locking and unlocking the phone and keeping music playing was a problem I was having as well. I made changes to the sound engine to better handle this. I’ll post up a zip later of my latest sound engine with these changes. Just dropping the class in should cause it to work nicely when phone calls, alarms or phone lock stops the sound :o)
Mike
benoitr007 on January 4th, 2010
Hi Mike, that’s great news! Did you experience lag problems caused by the music? I’m having some when I run the tutorial 10 project on my iPhone and add music to it. There seems to be 2-3 skipped frames every second or so. I found a way to fix this by setting the audio session category to SoloAmbientSound, which apparently keeps the decoding on the audio hardware instead of the CPU. But whenever I play the sound again after locking and unlocking the phone, the lag is back.
dilbertian on January 9th, 2010
Mike,
I am having some issues with the sound engine – (maybe the same problem you have fixed) – looks like when the background music pauses or stops, all sounds stop as well. If I resume or restart another music track, it sounds as if all previous sounds had been queued and try to play all at once.
In doing some debug with playSoundWithKey(), I don’t see any smoking guns but noticed that the sourcestate was always AL_STOPPED but wasn’t sure if this was causing the problem or not. I tried a few work-arounds but most of them were either inefective or crash and burn.
Thanks,
-Dil
mike on January 9th, 2010
Hi Dil
That is an odd issue. The AVAudioPlayer is different from the OpenAL side of things so should not interfere with it. I’ll do some testing and see if I can get the same effect and get back to you.
Mike
mike on January 9th, 2010
I’ve just one a quick test. I paused music playing but could still hear OpenAL sounds being played. When I then played the music again it continued from where I had paused it and the OpenAL still worked ok.
What I’ve done is zip up my latest SoundManager files. This has all the bug fixes in it for handling sound interruptions etc. It also makes use of the Apple C class for loading sound files of different types correctly.
Give it a try and let me know if you have the same issues. You should just be able to drop this straight into your project.
Let me know how it goes.
Mike
mike on January 9th, 2010
A link would be useful :o)
http://www.71squared.com/iPhon.....lasses.zip
Mike
dilbertian on January 10th, 2010
Mike,
Thanks bunches for the ultra quick reply and source dump!!!!
I expect that this will work but will check back to let you know either way.
-Dil
Juion on January 15th, 2010
Hi,
first of all I want to thank you very much for the incredibly helpful tutorials you’ve put up here. It’s been a great support for me so far.
Unfortunately I’m having an issue running Tutorial 12 on my machine.
While executing line 41:
_soundManager = [SoundManager sharedSoundManager];
in the OGLGameController method init, XCode always throws an “EXC_BAD_ACCESS” error. I tried to incorporate the new sound manager version you’ve recently uploaded, but still no success.
I’ve come to a dead end. Can you please help me?
mike on January 16th, 2010
Hi Juion
I’m not sure what your problem is. It certainly telling you that your trying to access something that has either not been allocated or has been released too early and its still trying to be used.
What happens if you comment out that line. Tutorial 12 did not use the sound manager class or the game controller class so I’m assuming you are adding these yourself. Check to make sure you are allocating your objects at the right time and not releasing them too soon.
Without seeing more code that is all I can suggest at the moment.
Mike
Peter on January 19th, 2010
Wanted to thank you Mike for all the hard work you’ve done to get this together for everyone.
I started following your tutorials back when you first started and I wanted to share with you and anyone else that’s interested what we’ve been able to achieve so far using your blog as a starting point.
Here’s the game we are developing, thanks to your tutorials. Let us know what you think!
hugo on February 1st, 2010
Hi Mike,
Could you tell me please how to deal with arrays of objects?
Let say i have an object A that contains an array of objects B (object B has encodeWithCoder and initWithCoder methods) and i want to encode object A…
encoding every single one separately with different key (using stringWithFormat for example) seems stupid.
Is there an easier way?
btw. Do you encode all particle emitters while saving game sate?
mike on February 1st, 2010
Hi hugo
Based on your example, you would just need to encode object A which could be an NSMutableArray or dictionary. For example, I have an array in SLQ that contains all my baddies. Each baddie is an object which supports NSCoding. When I want to encode the array I simply do
[encoder encodeObject:entities forKey:@"entities"];
This will encode the entire contents of that array and store it with the key entities. I can then decode in the same way populating an NSMutableArray.
There is nothing stopping you from doing the same with particles, although more work would be required so that the particle details that are stored in a structure are converted to a wrapping object or class of their own.
I personally don’t bother with that. I simply create any particle emitters that are held within an object during the init, which is still done when you create objects that have been encoded. It saves a lot of effort :o)
Hope that helps
Mike
hugo on February 2nd, 2010
hey, thanks for reply,
good to know that it’s so easy with nsarrays, unluckily form me i’ve used staright C arrays and i had to do it all by myself… everythig is workin fine except for particle emitters – but im working on it. i will share the code only if i manage to get it work
mike on February 3rd, 2010
@Peter, I checked out your website and the its looking very cool. Trying to cover a project like this and being so far apart cannot be easy, but it looks like your making great progress.
I can’t wait to see the next video and how the game is coming along :o)
Mike
9livesoftware on February 8th, 2010
Hello,
Im trying to make it so when my character jumps and when it lands on a block it doesnt go through it.
PS I dont know how to code for the jump or the collision.
glen on February 12th, 2010
Hi Mike
Great tutorials!
Could you, or anyone else help with the following.
In the game i’m trying to develope i’ve been using a 2d array to store bullet information. The array holds a bullet start position x and y offset for x and y to control direction and a counter which reduces to 0, giving the bullets a lifespan. the other dimension to the array is for the number of bullets if you see what i mean. So when the screen is touched the array is checked for the first instance of a 0 lifespan then the x,y,and lifespan are set. The update scene then loops the array changing the position by using the offset for each bullet with a lifespan > 0 and decreases the lifespan. The render scene then loops and displays a bullet each time the lifespan is > 0. I have altered this code loads of times even to the point of makeing multiple 1d arrays which prevents me from looping as i would like but i come up with the same problem everytime? When you create a new bullet the previous one disappears???? Thanks to all in advance for any help.
Anonymous on March 5th, 2010
Hey Mike,
I would like to thank you for this great tutorial, it is the best.
I am starting to build my game project based on the tutorial, and started to worry about the Max PNG size the Image/2DTexture could handle.
I would really apreciate any help on this.
Cheers.
mike on March 5th, 2010
The largest texture that can be handled in OpenGL ES 1.1 on the iPhone is 1024×1024 pixels. On the iPhone 3GS using OpenGL ES 2.0 it is 2048×2048.
Unless you really need the features of OpenGL ES 2.0 I would stick with 1.1 which also gives you currently the largest user base, so 1024×1024 is the max.
Hope that helps.
Mike
jjack on March 6th, 2010
is it possible to use NSUserDefaults to save the state or is that to memory constraining
Thanks
Ron on March 11th, 2010
Hi Mike,
Excellent tutorials! I’m finding them extremely helpful and informative. Keep up the great work!
Cheers!
glen on March 17th, 2010
Hi All
I’ve been working with tutorial9 to do my little project and its going good. But ive just started to try and implement some saving when the app quits using tutorial 12. I cant seem to get it working and i wondered if anyone could tell me anything to help or even post an example. All i want to be able to do is save a handfull of ints when the program quits???
Thanks in advance
mike on March 17th, 2010
Hi glen, where are your ints being stored? Are they within objects you have created, or just held in your main game.
If they are inside objects then the NSCoder stuff should be implemented in those objects to encode the ints. If they are just in the core game code then you could use an NSDictionary and write its contents out. This is how I am saving my settings in SLQ e.g. volume
NSNumber *mv = [NSNumber numberWithFloat:sharedSoundManager.musicVolume]; NSNumber *fv = [NSNumber numberWithFloat:sharedSoundManager.fxVolume]; NSNumber *lh = [NSNumber numberWithInt:joypadPosition]; NSNumber *fd = [NSNumber numberWithInt:fireDirection]; [settings setObject:mv forKey:@"musicVolume"]; [settings setObject:fv forKey:@"fxVolume"]; [settings setObject:lh forKey:@"joypadPosition"]; [settings setObject:fd forKey:@"fireDirection"]; [settings writeToFile:settingsFilePath atomically:YES];
Loading them back in would use
if([[NSFileManager defaultManager] fileExistsAtPath:settingsFilePath]) {
SLQLOG(@"INFO - GameController: Found settings file");
settings = [[NSMutableDictionary alloc] initWithContentsOfFile:settingsFilePath];
} else {
SLQLOG(@"INFO - GameController: No settings file, creating defaults");
settings = [[NSMutableDictionary alloc] init];
[settings setObject:[NSString stringWithFormat:@"%f", 0.7f] forKey:@"musicVolume"];
[settings setObject:[NSString stringWithFormat:@"%f", 0.5f] forKey:@"fxVolume"];
[settings setObject:[NSNumber numberWithInt:0] forKey:@"joypadPosition"];
[settings setObject:[NSNumber numberWithInt:0] forKey:@"fireDirection"];
}
// Get the prefs from the pref file and update the sound manager
[sharedSoundManager setMusicVolume:[(NSString *)[settings valueForKey:@"musicVolume"] floatValue]];
[sharedSoundManager setFxVolume:[(NSString *)[settings valueForKey:@"fxVolume"] floatValue]];
self.joypadPosition = [[settings valueForKey:@"joypadPosition"] intValue];
self.fireDirection = [[settings valueForKey:@"fireDirection"] intValue];
Hope that helps.
Mike
glen on March 18th, 2010
Hi Mike
Thanks for the response i have decided that if somethings worth doing its worth doing right. So i have bought the book and im going to start all over again with a better understanding of how to do everything. Only read to chapter 3 so far but im already glad i bought it.
Cheers
dave on April 2nd, 2010
Hi Mike,
Thanks for all the great tutorials. I just wanted to ask a question about saving game state. Given an earlier tutorial on a singleton shared game state, why not just centralise all game state and encode/decode/save the singleton object? Is there a benefit to having each game object know how to encode/decode its own game state data?
David
Greg on April 28th, 2010
Hi Mike, thanks for all the tutorials. Had a follow-up question similar to the one above me (dave). Is there a way to restore a singleton (with state) or is it better practice to just save the data individually from the singleton, initialize and rebuild the singleton manually from my “Load Game” methods?
Kaizoku on July 26th, 2010
Thx mike, the project file seems to be only the joypad, not the actual tutorial 12 folder.




Tweets that mention Iphone Game Programming – Tutorial 12 – Saving State | 71² - The ramblings of two 30-something developers -- Topsy.com on December 23rd, 2009
[...] This post was mentioned on Twitter by 71Squared, Carlos Chavez. Carlos Chavez said: RT @71squared: Tutorial 12 – Saving Game State has been posted – http://tinyurl.com/ye9ma4e [...]