Categories
Cocos2d

Cocos2d Tips: Transitioning between game screens

Let’s learn how to create menu for a cocos2d game and how to move between a menu, the game scene, a level complete scene etc.

Eventually your game will grow and you will have to create a clear structure to keep everything organized.

20120911-203055.jpg

As you can see, as with any app, the AppDelegate is the first object called. As such, it is the entry point to your game and will call the very first scene of your game. This means the first scene should probably the main menu which welcomes the user to the game and presents him with options.

As you can see from the Cocos2d tips “Creating a Menu”, menus can be quite complex:

http://quique123.wordpress.com/2012/09/12/cocos2d-tips-creating-a-menu/ ‎

When a cocos2d game is created, a Singleton instance of the GameDirector is instantiated and charged with managing scenes. After all, your Main Menu scene is just another scene/layer called by the game director. Thus it is quite common to create another Singleton class used to tell the director which scene to call.

Let’s call it the GameManager and his sole job is to tell the director which scene to call. Before we take a look at some code, keep in mind a game may grow to have quite a few scenes and while text is more human readable, it is easier to manage variables as numbers. The main reason is that switch statements use numbers, not text.

So it is common practice to use code such as this in a Constants.h file that you import into your GameManager.m Class:

typedef enum {

kNoSceneUninitialized=0,

kFirstScene=1,

kSecondScene=2,

kThirdScene=3,

} SceneTypes;

Now you can easily use a method such as this:

-(void)runSceneWithID:(SceneTypes)sceneID {

SceneTypes oldScene = currentScene;

currentScene = sceneID;

id sceneToRun = nil;

switch (sceneID) {

case kMainMenuScene:

sceneToRun = [MainMenuScene node];

break;

case kFirstScene:

sceneToRun = [Scene1 node];

break;

case kSecondScene:

sceneToRun = [PlaneScene node];//[Escena2 node];//

break;

case kThirdScene:

sceneToRun = [Scene3 node];

break;

default:

CCLOG(@”Unknown ID, cannot switch scenes”);

return;

break;

}

if (sceneToRun == nil) {

// Revert back, since no new scene was found

currentScene = oldScene;

return;

}

}

if ([[CCDirector sharedDirector] runningScene] == nil) {

NSLog(@”runningScene is nil…its ok because we are in process of setting the new scene???”);

[[CCDirector sharedDirector] runWithScene:sceneToRun];

} else {

[[CCDirector sharedDirector] replaceScene:[CCTransitionFlipAngular transitionWithDuration:0.5f scene:sceneToRun]];

}

currentScene = sceneID;

}

GAME START

Now this simple switch can be used to change scenes.  All you have to do at the end of the AppDelegate is call GameManager’s sceneToRun method and pass it the MainMenuScene.

MAIN MENU SELECTION

At the Main Menu scene, depending on the level selected from the menu you can pass a particular scene constant to GameManager in order to determine the level scene to call.

LEVEL END

From within your game level layer, after defining if your player won or lost, you can call GameManager to run a custom EndOfLevel scene/layer.  Then from that transitional scene you can call the MainMenuScene again.

Categories
Cocos2d Iphone Developer Technological

Cocos2d Tips: Creating a Menu

CCMenu by Santiapps - Marcio Valenzuela
CCMenu by Santiapps – Marcio Valenzuela

You can create a menu by creating label items or image items and passing them to a CCMenu object. A typical MainMenuScene.m file might look like this:

-(void)playScene:(CCMenuItemFont*)itemPassedIn {

if ([itemPassedIn tag] == 1) {

[[GameManager sharedGameManager] runSceneWithID:kIntroScene];

} else if ([itemPassedIn tag] == 2) {

[[GameManager sharedGameManager] runSceneWithID:kSecondScene];

} else if ([itemPassedIn tag] == 3) {

[[GameManager sharedGameManager] runSceneWithID:kThirdScene];

} else {

CCLOG(@”Unexpected item. Tag was: %d”, [itemPassedIn tag]);

}

}

-(void)displayMainMenu {

CGSize screenSize = [CCDirector sharedDirector].winSize;

if (sceneSelectMenu != nil) {

[sceneSelectMenu removeFromParentAndCleanup:YES];

}

// Main Menu

CCMenuItemImage *playGameButton = [CCMenuItemImage

itemWithNormalImage:@”TapMeToPlay.png”

selectedImage:@”TapMeToPlay.png”

disabledImage:nil

target:self

selector:@selector(displaySceneSelection)];

CCMenuItemImage *optionsButton = [CCMenuItemImage

itemFromNormalImage:@”someImage.png”

selectedImage:@”someImage.png”

disabledImage:nil

target:self

selector:@selector(showOptions)];

mainMenu = [CCMenu menuWithItems:playGameButton,optionsButton,nil];

[mainMenu alignItemsVerticallyWithPadding:screenSize.height * 0.059f];

[mainMenu setPosition:ccp(screenSize.width * 2,screenSize.height / 2)];

id moveAction =

[CCMoveTo actionWithDuration:1.2f

position:ccp(screenSize.width * 0.75f,

screenSize.height * 0.70f)];

id moveEffect = [CCEaseIn actionWithAction:moveAction rate:1.0f];

[mainMenu runAction:moveEffect];

[self addChild:mainMenu z:0 tag:kMainMenuTagValue];

}

-(void)displaySceneSelection {

CGSize screenSize = [CCDirector sharedDirector].winSize;

if (mainMenu != nil) {

[mainMenu removeFromParentAndCleanup:YES];

}

CCLabelTTF *playScene1Label = [CCLabelTTF labelWithString:@”Level 1″ fontName:@”Motter Tektura” fontSize:45];

playScene1Label.color=ccc3(000, 000, 000);

CCMenuItemLabel *playScene1 = [CCMenuItemLabel itemWithLabel:playScene1Label target:self selector:@selector(playScene:)];

[playScene1 setTag:1];

[playScene1 addChild:stroke z:-1];

CCLabelTTF *playScene2Label = [CCLabelTTF labelWithString:@”Level 2″ fontName:@”Motter Tektura” fontSize:45];

playScene2Label.color=ccc3(000, 000, 000);

CCMenuItemLabel *playScene2 = [CCMenuItemLabel itemWithLabel:playScene2Label target:self selector:@selector(playScene:)];

[playScene2 setTag:2];

[playScene2 addChild:stroke2 z:-1];

CCLabelTTF *playScene3Label = [CCLabelTTF labelWithString:@”Level 3″ fontName:@”Motter Tektura” fontSize:45];

playScene3Label.color=ccc3(000, 000, 000);

CCMenuItemLabel *playScene3 = [CCMenuItemLabel itemWithLabel:playScene3Label target:self selector:@selector(playScene:)];

[playScene3 setTag:3];

[playScene3 addChild:stroke3 z:-1];

CCLabelBMFont *backButtonLabel =

[CCLabelBMFont labelWithString:@”Back”

fntFile:@”MyFontFile.fnt”];

CCMenuItemLabel *backButton =

[CCMenuItemLabel itemWithLabel:backButtonLabel target:self

selector:@selector(displayMainMenu)];

sceneSelectMenu = [CCMenu menuWithItems:playScene1,

playScene2,playScene3,backButton,nil];

[sceneSelectMenu alignItemsVerticallyWithPadding:screenSize.height * 0.059f];

[sceneSelectMenu setPosition:ccp(screenSize.width * 2,screenSize.height / 2)];

id moveAction = [CCMoveTo actionWithDuration:0.5f position:ccp(screenSize.width * 0.5f,screenSize.height/2)];

id moveEffect = [CCEaseIn actionWithAction:moveAction rate:1.0f];

[sceneSelectMenu runAction:moveEffect];

[self addChild:sceneSelectMenu z:1 tag:kSceneMenuTagValue];

}

There are three methods here that are important:

1) playScene which basically receives an item and based on the received item it calls CCDirector to play a scene.

2) displayMainMenu which uses images as buttons to call a second level menu item.  It basically creates menu items and then uses them to populate CCMenu menuWithItems.

3) displaySceneSelection which is called from the displayMainMenu which then takes the user selection and passes it to playScene.