Level changing problem

Forums Programming cocos2d support (graphics engine) Level changing problem

This topic contains 9 replies, has 2 voices, and was last updated by  Dragyn 2 years, 9 months ago.

Viewing 10 posts - 1 through 10 (of 10 total)
Author Posts
Author Posts
July 1, 2011 at 2:45 pm #232773

mrcointreau
@mrcointreau

Hello everybody, I’d need a little help with the my game’s level changing strategy.

I have the following GameScene class:

@interface GameScene : CCScene {
HUDLayer *hudLayer;
InputLayer *inputLayer;
Level *levelLayer;
PoorStudent *poorStudent;
}

@property (nonatomic, readwrite, assign) Level *levelLayer;

+ (GameScene *)sceneWithLevel:(int)levelNumber;
+ (GameScene *)sharedScene;

- (id)initWithLevelNumber:(int)levelNumber

@end

@implementation GameScene

@synthesize levelLayer;

static GameScene *instanceOfGameScene;

+ (id)sceneWithLevel:(int)levelNumber {
GameScene *scene = [[[GameScene alloc] initWithLevelNumber:levelNumber] autorelease];

return scene;
}

+ (GameScene *)sharedScene {
return instanceOfGameScene;
}

- (id)initWithLevelNumber:(int)levelNumber {
if ((self = [super init])) {
if (instanceOfGameScene == nil) {

instanceOfGameScene = self;

// Load all of the game's artwork
CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"game-art.plist"];

poorStudent = [PoorStudent poorStudent];

hudLayer = [HUDLayer HUDLayerWithHealth:poorStudent.health andScore:0];
[self addChild:hudLayer z:1];

inputLayer = [InputLayer node];
[self addChild:inputLayer z:2];

levelLayer = [Level levelWithLevelNumber:levelNumber];
[levelLayer addChild:poorStudent z:0];
[self addChild:levelLayer z:0];

CGSize screenSize = [[CCDirector sharedDirector] winSize];
[poorStudent setPosition:ccp(poorStudent.contentSize.width, screenSize.height / 2)];
[levelLayer runAction:[CCFollow actionWithTarget:poorStudent worldBoundary:CGRectMake(0, 0, levelLayer.contentSize.width, levelLayer.contentSize.height)]];

[self scheduleUpdate];
}
}
return instanceOfGameScene;
};

which is a singleton class.

I use the sceneWithLevel method for the first call to the GameScene instance.

I’m trying to change the level by using the following method:

- (void)loadLevel:(int)levelNumber {
[self removeChild:levelLayer cleanup:YES];
levelLayer = [Level levelWithLevelNumber:levelNumber];
[levelLayer addChild:poorStudent];
}

but when I call it I’ve got the following error:

Assertion failure in -[Level addChild:z:tag:]

NSAssert( child.parent == nil, @”child already added. It can’t be added again”);

Could somebody help me with this, please?

July 1, 2011 at 6:49 pm #336278

Dragyn
Moderator
@dragyn

From that error, my best guess is that something else in your code is keeping the levelLayer alive. Check for anything else that might be retaining a reference to the levelLayer, because the “cleanup” will only take care of children of the CCLayer, not outside references. If this is the case, it’s somewhere other than the code snippet you posted.

I’m curious why your main game is apparently in a Singleton. For what it’s worth, I’ve found this type of uber-singleton to be more problematic because it’s not as “clean” if you want to reset your level. I generally take the approach of using a Singleton to hold persisted values (and any load/save methods), but let the actual main game scene be a separate, non-singleton. This lets you persist values in the Singleton, but if you have a need to completely reset the game scene (restart or going to a new level), you can do it with a simple replaceScene, and replace it with a new instance of itself. Just my 2 cents worth.

July 1, 2011 at 8:46 pm #336279

mrcointreau
@mrcointreau

First of all, thanks for your reply.

I use a singleton for my GameScene because i only need one GameScene at time and I don’t want more than one to be allocated. Is it wrong?

July 2, 2011 at 2:28 am #336280

Dragyn
Moderator
@dragyn

No, not wrong. There are many ways to accomplish your goals, and if your way works for you (and you can keep everything straightforward when you change levels), then go for it.

To debug your layer problem, I was just thinking it might be an interesting test to set up a test method that you can trigger in your scene that only performs the “removeChild” portion of the loadLevel method. Run this through Instruments, and see if that layer actually goes away. If not, then start walking the code to see what you’ve retained or alloc’d, and make sure it all gets put away when you’re done. The most common things I’ve seen are related to arrays or touch delegates. If you’re explicitly registered for touch handling, make sure you get rid of it in the onExit (or before).

Good luck!

July 2, 2011 at 9:57 am #336281

mrcointreau
@mrcointreau

Maybe the problem is that in my GameScene class I have set the HUDLayer, the LevelLayer, the InputLayer and my PlayerSprite as instance variable and retained them. I did it because I have many methods where I access to them and I want to call getChild every time to retrieve a node.

So my GameScene interface is:

@interface GameScene : CCScene {
HUDLayer *hudLayer;
InputLayer *inputLayer;
Level *levelLayer;
PoorStudent *poorStudent;
}

and in my GameScene init method I retain all of them and add them as child.

Could this be the problem? I’m getting mad!

July 2, 2011 at 9:40 pm #336282

Dragyn
Moderator
@dragyn

I think I see what might be the problem. I completely missed that you had declared the levelLayer as a property. You should use self.levelLayer, so it uses the getter/setter for the property. When you bypass the setter, it doesn’t call a release before it assigns the new value. You should change this everywhere you are giving a new value to levelLayer (both in the initWithLevelNumber and the loadLevel method).

Let me know if that helps.

July 3, 2011 at 12:00 am #336283

mrcointreau
@mrcointreau

Does levelLayer become a property even without the @property declaration and the @syntesize commmand???

July 3, 2011 at 3:54 am #336284

Dragyn
Moderator
@dragyn

No, it doesn’t. However, from the code you posted in the first post, both of those declarations are in your code.

July 4, 2011 at 12:04 am #336285

mrcointreau
@mrcointreau

You’re right, my back Dragyn, now I got it, thank you very much!

It was more than a month that I didn’t touch the game so I made some mess with the memory management, thanks :)

July 4, 2011 at 3:20 am #336286

Dragyn
Moderator
@dragyn

Glad to help.

Good luck!

Viewing 10 posts - 1 through 10 (of 10 total)

You must be logged in to reply to this topic.