Wow, it's very dark in there. And this tunnel is sooooo long. We could use some light. The good thing is, I know where the light is. Are you familiar with Flash or Photoshop ? If so, you can think of a cocos Scene as the canvas of the top-level document. A cocos Layer would be sort of a Photoshop layer directory. And then a cocos Sprite (or TextureNode) would be a layer containing a Bitmap. A cocos Label would be a layer containing a Textfield.
In general, you ask the Director to display one Scene at a time. Think of the runWithScene function as a convenience method for doing both :
[[Director sharedDirector] run]; // to run the Director at the very beginning of the program
[[Director sharedDirector] replaceScene: someScene]; // to replace the Director's current scene
// but since there's none, it won't replace the current scene but just set it
Therefore, any other time you need to replace the scene, you'll use replaceScene and never runWithScene.
If you want to avoid confusion, especially if you're not sure you understand how things work, it's a good idea to subclass Scene to create your own custom scenes. For instance, don't do this :
Scene *s2 = [Scene node];
[s2 addChild: [LayerGame node]];
Instead, create an CutScene, GameScene or OpeningScene class which subclasses Scene and add the LayerGame (or any other subclass of Layer of your own) in the init function. For example, with OpeningScene, something like :
// in .h
@interface OpeningScene : Scene {
}
- (void) displayNextScene; // we'll use that to load the next scene
@end
// in .m
@implementation OpeningScene
- (id) init {
self = [super init];
if (self != nil) {
[self addChild:[LayerGame node] z:1]; // <= you probably want LayerOpening here
}
return self;
}
- (void) onEnter {
[super onEnter];
// we wait 5 seconds and we call the displayNextScene function
[self runAction:[Sequence
actionOne: [DelayTime actionWithDuration:5.0f]
two: [CallFunc actionWithTarget:self selector:@selector(displayNextScene)]]];
}
- (void) displayNextScene {
// here we create the next scene and ask the Director to display it
NextScene *nScene = [NextScene node];
[[Director sharedDirector] replaceScene: [FadeTransition transitionWithDuration:2.0f scene:nScene]];
}
// and probably some other methods
@end
Of course, NextScene is your CutScene or GameScene or whatever, and is a subclass of Scene, exactly like the above code.
When you replace a scene with a transition, the following actions happen (let's say an occurrence of Scene1 is currently running in the Director) :
- an occurrence of the new Scene (say Scene2) is created in memory (Scene2 init is called)
- the Director is asked to replace the current scene with the new one (Director replaceScene is called)
- the transition starts (Scene2 onEnter is called)
- the transition ends (Scene1 onExit is called)
- the previous scene is removed by the Director (Scene1 dealloc is called, if not retained explicitly by you somewhere else)
Your piece of code [[Director sharedDirector] replaceScene: [FadeTransition transitionWithDuration:5.0f scene:s2 ]]; right in the onEnter method is not right because while the Director is already running a transition between two scenes, the new scene orders another transition with another scene to be run. And I don't know how the Director handles multiple replaceScene calls at the same time but I'm sure it's not intended to be used that way. That's also why I put a DelayTime action in the onEnter function, to make sure the previous transition is over. Another way of doing it is to call the replaceScene function in the onEnterTransitionDidFinish method which is called on the scene when the transition ends.
If you follow these instructions, you'll be able to see the light too ! Good luck.