Managing Game Scenes

My Wiki Page

One of the most common questions I have encountered on the forums is regarding scene and memory management. I had trouble with this at first myself so here is a tutorial to explain it all.


Tutorial Request from markjsb

First of all, there are a couple things to explain.

When I first started using Sparrow, I put my main menu into my Game class (i.e. SPStage subclass). This is not a good way to do it. The Game class should hold all of the different scenes that need to be displayed and swap them out.

The Life of a SPSprite

SPSprites go through a couple of stages. I will put retain counts in comments so that you can understand the memory management aspect.

Usually memory management is shown with these three rules:
1. When an object is retained or allocated, the retain count increases by 1.
2. When it is released the object's retain count is decreased by 1.
3. When you are finished with an object its retain count should be 0.

In this example, Scene1 is an SPSprite.

Scene1 *sprite = [[Scene1 alloc] init]; // Retain count: 1
[self addChild:sprite];                 // Retain count: 2
[sprite release];                       // Retain count: 1
[self removeChild:sprite];              // Retain count: 0
A Switching Function for Scenes

First, we need to add a variable and method to Game.h.

SPSprite *currentScene;
- (void)showScene:(SPSprite *)scene;

Now put create this method in Game.m.

- (void)showScene:(SPSprite *)scene {
    if ([self containsChild:currentScene]) {
        [self removeChild:currentScene];
    }
    [self addChild:scene];
    currentScene = scene;
}

Let me explain what this method does. First, you pass it a new scene sprite that has just been allocated and initialized. Then it checks to see if the currentScene is already being displayed. If it is, the scene is removed from the stage, decreasing its retain count by one and releasing it from memory. Then, the new scene is added to the stage. It is set as the currentScene so that it will be removed when a new scene is shown. Here is an example of passing a scene to this method on init.

- (id)initWithWidth:(float)width height:(float)height
{
    if ((self = [super initWithWidth:width height:height]))
    {
        Menu *menuScene = [[Menu alloc] init];
        [self showScene:menuScene];
        [menuScene release];
    }
    return self;
}
Changing Scenes from Other Classes

There are two ways to change scenes from other places in your game.
1. Creating methods in the Game class
Game.h

#import "Play.h"
- (void)showPlay;

Game.m

- (void)showPlay {
    Play *playScene = [[Play alloc] init];
    [self showScene:playScene];
    [playScene release];
}



2. Calling show scene from other classes
Menu.h

#import "Play.h"

Menu.m

#import "Game.h"
- (void)onPlayButtonTriggered:(SPEvent *)event {
    Play *playScene = [[Play alloc] init];
    [(Game *)[SPStage mainStage] showScene:playScene];
    [playScene release];
}
That's it!

If you have any questions please post them on the forum post linked to at the top. Here is a quick sample project I threw together to demonstrate this concept.


Sample Project

  tutorials/managing_game_scenes.txt · Last modified: 2013/03/05 10:19 (external edit)
 
Powered by DokuWiki