Games have many layers.

layers

The most common example is the main action layer (where the players and enemies are) having to communicate with the HUD layer (which presents score, health and other info) to the gamer. Let’s see how we can communicate between layers.

Typically you create a Scene and then a Layer in order to add that Layer as a child to the Scene.

Let’s say our Scene.h looks like this:

#import <Foundation/Foundation.h>

#import “cocos2d.h”

@interface Scene1 : CCScene {

}

@end

And our Scene.m looks like this:

-(id)init {

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

Scene1ActionLayer * actionLayer = [[[Scene1ActionLayer alloc] init] autorelease];

[self addChild:actionLayer z:0 tag:kActionLayer];

}

return self;

}

So we are adding the main action layer, actionLayer, to our scene at z=0 with a tag kActionLayer.  Simple enough.  Now let’s say we want to create a HUD layer to contain game information.  This can range from points, to level information, to instructions or simply health or powerup information.

Im not much of a designed so I created this simple rectangle as a bottom bar for my game.

HUDbar

The idea here is that those stars will actually represent the powerups a player must collect in order to complete a level.  Thus this will actually be a silhouette and each time the player picks up a power up, the HUD gets updated to place the powerup image in that space.  So we need the actionLayer to communicate with the HUD layer in order to say “Update the BIG GUNS power up!”.

We go ahead and create the actionLayer, possibly with a method called updateHUDWithPowerup:(Powerup*)power up; where Powerup is anything as simple as a typedef or as complex as a custom NSObject.

First, we need an instance of the HUD layer inside our actionLayer to call its method.  So inside our actionLayer, we forward declare it in our action layer :

@class “HUDLayer;

and then create an ivar for its instance:

HUDLayer *hudLayerInstance;

Second, we import the class in our action layer.m:

#import “HUDLayer.h”

Third, we simply allocate the instance in our actionLayer’s init method:

hudLayerInstance = [[HUDLayer alloc] initWithActionLayer:self];

[self addChild:backLayer z:0 tag:100];

Fourth, when the time comes to update the HUDLayer from the action layer’s update method (perhaps), we call:

[hudLayerInstance someMethodDefinedInHUDLayer:withThisValue];

Fifth, don’t forget to code the HUDLayer.  In its interface, forward declare your action layer class and add the custom initializer as well as your method like so:

@class ActionLayer;

@interface HUDLayer : CCLayer {

CCLabelTTF *_scoreLabel;

}

@property (nonatomic, assign) CCLabelTTF *scoreLabel;

-(id)initWithActionLayer:(ActionLayer*)layer;

@end

Finally implement your initializer and its “someMethodDefinedInHUDLayer” in order to pass it “withThisValue”.

Voila!  Another option is using Delegates/Protocols.

 

 

In this case we are adding all children to the Scene.  In order to get them to communicate, we would need to have methods inside the Scene itself to call actions between objects.  I prefer the former method.  I leave this kind of setup for adding layers that don’t really do much, such as timers, background, eye candy etc.  They are still important layers, they just dont interact with the actionLayer much or at all.

Leave a Reply