Search code examples
objective-ccocos2d-iphone

(cocos2d) Dynamically creating a menu and scene


After Python Objective-C syntax blows my mind!

I'm trying to create a menu that will 25 buttons. Clicking on that will start is appropriate level. The levels differ only by calling [CCTMXTiledMap tiledMapWithTMXFile: @ "lvl_1-25.tmx"];

To create the menu, I use:

    CCMenuItemSprite *lvl_1_button= [CCMenuItemSprite itemFromNormalSprite:[GameButton buttonWithText:@"lvl 1"] selectedSprite:NULL target:self selector:@selector(lvl1_start)];
    ...
    CCMenu *menu = [CCMenu menuWithItems: lvl_1_button, lvl_2_button, lvl_3_button,  nil];       

    [self addChild:menu];

The scene changes with:

-(void)lvl1_start

{
    [[CCDirector sharedDirector] replaceScene:[lvl1_start node]];

}

In this case the difference between levels is minimal. In one line at initialization.

-(id) init
{
    if( (self=[super init])) 
    {
        self.tileMap = [CCTMXTiledMap tiledMapWithTMXFile:@"lvl_1.tmx"];

The result is a ton of duplicate code. How can this be simplified?

After all, only need to change the scene and simply pass a single variable (the level number) in the initialization method.


Solution

  • I'll try to make it as simple as possible possible.

    To start add a new init method to your level scene which takes as argument the tilemap's name for example:

    // LevelScene.h
    - (id)initWithTilemapName:(NSString *)tilemap;
    
    // LevelScene.m
    - (id)initWithTilemapName:(NSString *)tilemap
    {
        if ((self = [super init]))
        {
            self.tileMap = [CCTMXTiledMap tiledMapWithTMXFile:tilemap];
            // ...
    

    Then to make the menu creation more dynamic, add your item in a run loop and associate them with a tag (to be able to differentiate them):

    CCMenu *menu = [CCMenu menuWithItems:nil];
    [self addChild:menu];
    
    for (int i = 1; i <= 25; i++)
    {
        CCMenuItemSprite *lvlItem = 
        [CCMenuItemSprite itemFromNormalSprite:[GameButton buttonWithText:[NSString stringWithFormat:@"lvl%d",i]] selectedSprite:NULL target:self selector:@selector(lvl_start:)];
        [lvlItem setTag:i];
    
        [menu addChild:lvlItem];
    }
    

    Add to finish in the selector, retrieve the menu item and create the scene with its corresponding tilemap.

    - (void)lvl_start:(CCMenuItemS *)item
    {
        LevelScene *yourScene = [[LevelScene alloc] initWithTilemapName:[NSString stringWithFormat:@"lvl%d.tmx",item.tag];
    
        [[CCDirector sharedDirector] replaceScene:yourScene];
    
        [yourScene release];
    }
    

    This is just an example to give you an idea, I have not tested it. But I hope it'll help you. ;)