开发者

Cocos2d - using getChildByTag from child classes to get objects in a scene

I have a cocos2d scene that has several child objects that make up the screen display. Some of these child objects need to communicate with each other so that the display can be updated.

I decided that instead of passing around references to objects in the scene graph I would tag all the cocos2d nodes, pass the tag values around and then whenever I need a scene object I would just use the director to retrieve the object using the tag.

This means I don't have lots of references to objects flying around and my thinking was that it would be cleaner and less likely to cause memory problems with objects being retained when they shouldn't be.

I use the following code to retrieve a particular node:

CCNode* node = [[[[CCDirector sharedDirector] runningScene] getChildByTag:TAG_MY_LAYER] getChildByTag:TAG_MY_OBJECT];
if (node != nil ){
    NSAssert([node isKindOfClass:[myObject class]], @"node is not a myObject");
    myObject* mo = (myObject*)node;
    ...
    other stuff
    ....

Problem: When a scene is initialising with a transition then this method doesn't work. The call to running scene returns the transition and not the new scene. If you wait for the - 开发者_开发技巧onEnterTransitionDidFinish then it still doesn't work. It seems as if you have to wait for a little bit after this (presumably for the old scene to be destroyed) before the transition is removed and runningScene is your new scene.

Is it possible to get a reference to part of the scene graph that I can call getChildByTag from and it will get my tagged object, regardless of the state of scenes transitioning?


@erik - how is your answer relevant to the question asked ?

You can move your code to the onEnter() method which seems to be executed after transition to the new scene is completed ie :

-(void)onEnter {
   [super onEnter];

   CCNode* node = [[[[CCDirector sharedDirector] runningScene] getChildByTag:TAG_MY_LAYER] getChildByTag:TAG_MY_OBJECT];
   if (node != nil ){
     NSAssert([node isKindOfClass:[myObject class]], @"node is not a myObject");
     myObject* mo = (myObject*)node;
     ...
     other stuff
     ....
   }
}


Instead of using that approach I suggest you look into Singleton classes. In this case, the Singleton class GameSettings.h is used to keep track of the variable globalScore.

Anywhere in your code you may now reference the variable by calling [[GameSettings sharedGameSettings] globalScore];

When you need to tell another scene that some value has changed you can simply use the notification center.

GameSettings.h

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface GameSettings : NSObject {
  int globalScore;
}

@property (nonatomic, assign) int globalScore;

@end

GameSettings.m

#import "GameSettings.h"

@implementation GameSettings

@synthesize globalScore;

static GameSettings *sharedGameSettings = nil;

+(GameSettings *)sharedGameSettings
{
    @synchronized(self){
        if(sharedGameSettings == nil)
        {
            sharedGameSettings = [[self alloc] init];
        }
    }
    return sharedGameSettings;
}

+(id)allocWithZone:(NSZone *)zone{
    @synchronized(self)
    {
        if(sharedGameSettings == nil)
        {
            sharedGameSettings = [super allocWithZone:zone];
            return sharedGameSettings;
        }
    }
    return nil;
}


-(id)init{

    self = [super init];

    if(self){}
    return self;
}

Another idea (if you need to pass data between the scenes often) is to make one scene a delegate of the other scene.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜