5 min read

Adding more layers to scenes

As we have discussed before, a scene can contain any number of layers you want. Well, as long as performance is not an issue. As CCLayer inherits from CCNode, it can be added as the child of CCScenes or other CCLayers, allowing you to organize your content in a nice fashion.

There are three types of CCLayers that you can use and combine in your games. They are as follows:

  • CCLayer: We have been using them forever. Besides all the features inherited from CCNodes, they can receive touches and accelerometer input.
  • CCColorLayer: They inherit from CCLayer so besides being able to receive touches and accelerometer input, their opacity and RGB colors can be changed.
  • CCMultiplexLayer: It inherits from CCLayer and can have many children, but only one will be active at any given time. You can switch between those children.

In the following examples, we will be creating some CCLayers in different ways to achieve different results.

Time for action – creating a HUD to display lives and the score

We will begin by building a simple Heads Up Display (HUD) for our game. Its purpose is to show some useful data about the current state of the game to the player. The idea behind making the HUD into a new layer is to simplify the logic of the GameLayer. This way, the GameLayer will only handle stuff of the game itself while leaving the HUD logic to the HUDLayer.

In our game, the HUD will display the remaining lives, score, remaining bombs, and anything you want to display later. Once it is done, all we need to do in the GameLayer is send a message so the HUDLayer gets updated.

  1. The first step in creating the HUD is to add a new file to the project. In the Xcode project, select File | New file and add a new Objective-C class. Rename it as HUDLayer.
  2. Replace the contents of the HudLayer.h with the following lines:

    #import <Foundation/Foundation.h>
    #import “cocos2d.h”
    #import “GameScene.h”

    @interface HudLayer : CCLayer
    {

    CCBitmapFontAtlas * level;
    CCBitmapFontAtlas * score;
    CCBitmapFontAtlas * bombs;
    NSMutableArray * lives;
    }

    @property (nonatomic,retain) CCBitmapFontAtlas * level;
    @property (nonatomic,retain) CCBitmapFontAtlas * score;
    @property (nonatomic,retain) CCBitmapFontAtlas * bombs;
    @property (nonatomic,retain) NSMutableArray * lives;

    @end

    
    
  3. Do the same with the contents of the HudLayer.m file:

    #import “HudLayer.h”

    @implementation HudLayer

    @synthesize lives,bombs,score,level;

    – (id) init
    {
    if ((self = [super init])) {

    CCSprite * background = [CCSprite spriteWithFile:@”hud_background.png”];
    [background setPosition:ccp(160,455)];
    [self addChild:background];

    lives = [[NSMutableArray arrayWithCapacity:3]retain];
    for(int i=0;i<3;i++)
    {
    CCSprite * life = [CCSprite spriteWithFile:@”hud_life.png”];
    [life setPosition:ccp(18+ 28*i,465)];
    [self addChild:life];
    [lives addObject:life];
    }

    CCSprite * bomb = [CCSprite spriteWithFile:@”hud_bomb.png”];
    [bomb setPosition:ccp(18,445)];
    [self addChild:bomb];

    GameLayer * gl = (GameLayer *)[self.parent getChildByTag:KGameLayer];

    level = [CCBitmapFontAtlas bitmapFontAtlasWithString:@”Level 1″
    fntFile:@”hud_font.fnt”];
    [level setAnchorPoint:ccp(1,0.5)];
    [level setPosition:ccp(310,465)];
    [level setColor:ccBLACK];
    [self addChild:level];

    score = [CCBitmapFontAtlas bitmapFontAtlasWithString:@”Score 0″
    fntFile:@”hud_font.fnt”];
    [score setAnchorPoint:ccp(1,0.5)];
    [score setPosition:ccp(310,445)];
    [score setColor:ccBLACK];
    [self addChild:score];

    bombs = [CCBitmapFontAtlas bitmapFontAtlasWithString:@”X3″
    fntFile:@”hud_font.fnt”];
    [bombs setAnchorPoint:ccp(1,0.5)];
    [bombs setPosition:ccp(47,440)];
    [bombs setColor:ccBLACK];
    [self addChild:bombs];

    }
    return self;
    }

    – (void) dealloc
    {
    [super dealloc];
    [lives release];
    }
    @end

    
    

    You can find the images and the font used above in the companion files at Support.

  4. What we have to do now is load this new layer and add it as a child of the GameScene. Change the init method of the GameScene class to look like the following:

    – (id) init
    {
    self = [super init];
    if (self != nil)
    {

    [self addChild:[GameLayer node] z:0 tag:KGameLayer];
    //kGameLayer defined in the GameScene.h file.
    #define kGameLayer 1
    [self addChild:[HudLayer node] z:1 tag:KHudLayer];
    //kHudLayer defined in the GameScene.h file. #define
    kHudLayer 2

    }
    return self;
    }

    
    

    The only thing missing now is to make some changes here and there to be able to update the HUDLayer with the actual state of the game. Let’s update the score and remaining lives, for now.

  5. Change the loseLife method of the GameLayer class:

    -(void)loseLife
    {
    self.lives–;

    HudLayer * hl = (HudLayer *)[self.parent getChildByTag:KHudLayer];
    CCSprite * live = [hl.lives objectAtIndex:self.lives];
    [live setVisible:NO];

    if(self.lives ==0)
    {
    [self resetGame];

    //LOSE THE GAME
    //GO TO GAME OVER LAYER
    }
    }

    
    
  6. Add the resetGame method:

    -(void)resetGame
    {
    HudLayer * hl = (HudLayer *)[self.parent getChildByTag:KHudLayer];
    for(CCSprite * c in hl.lives)
    {
    [c setVisible:YES];
    }
    self.level=1;
    [hl.level setString:@”Level 1″];
    self.score=0;
    [hl.score setString:@”Score 0″];
    self.bombs =3;
    [hl.bombs setString:@”X3″];
    lives = STARTING_LIVES;
    }

    
    

    These methods will handle the displaying of the remaining lives.

  7. Finally, modify the Enemy class’s destroy method, so it updates the score label instead of logging the score to the console:

    -(void)destroy
    {
    [self reset];
    [theGame setScore:theGame.score+100];
    HudLayer * hl = (HudLayer *)[theGame.parent getChildByTag:KHudLayer];
    [hl.score setString:[NSString stringWithFormat:@”Score
    %d”,theGame.score]];
    }

    
    
  8. Run the game. You should see a HUD at the top of the screen (as shown in the following screenshot) with all the actual information about the state of the game. Destroy some enemies to see the score updated and lose some lives to see the “lives” icons disappear.

What just happened?

We just went through the steps needed to create a new layer, adding it to the scene and updating its contents.

Our new layer just holds some information of the game state and displays it to the player. In order to achieve that we just added a few CCSprites and CCBitmapFontAtlases which get updated when needed.

Once the HudLayer class was created we added it to the GameScene over the GameLayer, so its contents are always shown on top of the GameLayer’s ones. We also provided a tag for both layers, as we will need to access them from other places. We could also have added a reference to the other layer inside them.

That is all what we need to do in order to add more layers to a scene. The rest of the code just handles the updating of the contents of the HudLayer. When the player hits an enemy, a score is awarded. Then the label placed in the HUD is updated.

When the hero is hit and a life is lost, we just turn the corresponding icon’s visibility off, then when the game is reset we turn all of them on.

LEAVE A REPLY

Please enter your comment!
Please enter your name here