2013-01-23 30 views
0

我正在阅读Learn Cocos2d 2;并偶然发现了这个问题:在游戏场景中,场景层次结构下可能有数千个实体,并且所有这些实体都可能想要与最上面的场景对象进行交谈。学习的Cocos2D 2笔者建议使用全局变量这样在cocos2d中安全地访问当前场景的最佳方式是什么?

static GameLayer* sharedGameLayer; 
+(GameLayer*) sharedGameLayer 
{ 
    NSAssert(sharedGameLayer != nil, @"GameScene instance not yet initialized!"); 
    return sharedGameLayer; 
} 

+(id) scene 
{ 
    CCScene *scene = [CCScene node]; 
    GameLayer *layer = [GameLayer node]; 
    [scene addChild: layer]; 
    InputLayer* inputLayer = [InputLayer node]; 
    [scene addChild:inputLayer z:1 tag:GameSceneLayerTagInput]; 
    return scene; 
} 

我个人认为这种方法不可靠:想象一个球员实体想知道从场景另一层触摸输入,所以它调用sharedGameLayer和假设它实际上就是它的父母,它只是从那里开始工作。但是,它怎么能如此确定?如果这个sharedGameLayer是别人分配的另一个实例呢?当然,在cocos2d中一次只能有一个场景,所以这种方法在大多数情况下可能没有任何问题。但从设计角度来看,我仍然觉得缺乏这种方法。

我想过两种选择:

  1. 使用正确的(旧)的委托方法。在每个级别分配正确的委托/委托关系。但是,这意味着数千行可能重复的代码,并且从我的角度来看并不整齐

  2. 使用NSNotification(或KVO?)从子级别广播消息,并让父级响应。但是,这是否意味着该系统

在这一点上,我完全迷失了,谁能告诉我有关经验的程序员可以使用一般的成语不必要的开销?

回答

0

在大多数情况下,只要包含CCScene位于CCDirector的场景堆栈中,您的树的叶子CCNode就像您提及的“玩家实体”一样。一旦该场景弹出,它将收到dealloc消息,因此removeAll(其)Children。这反过来会让这些孩子dealloc包括你的“玩家实体”。您的“玩家实体”将收到的最后一条消息是dealloc,在此期间,所有父节点仍处于活动状态(尽管处于被破坏的过程中),所以永远不会有儿童要求无效的sharedGameLayer的情况。但是,如果你想把任何孩子带到另一个场景,你将不得不在很多方面非常小心,如果不是绝对必要的话,这也不是什么可以鼓励的东西。例如,您的特定代码块将不得不进行改进,以便sharedGameLayer将返回nil,如果场景不再处于活动状态,并且您的“玩家实体”可能需要检查此返回值。

简短的回答是,只要不在场景堆栈中移动节点,上面显示的代码是安全的。单个节点有很多可供选择的方法来了解游戏的“图形”,其中包括的每个属性CCNode以及CCDirectorrunningScene属性。

+0

如果我采用这种方法,它必然意味着我的实体将与GameLayer紧密结合;除此之外,还有你提到的问题......有没有其他的方式来实现同样的事情,但有效和安全? – lynnard

+0

另一个问题是,启用ARC后,静态变量可能会阻止整个图层在正确的时间被释放,这似乎很烦人。 – lynnard

+1

这是我的观点。无论如何,如果您要放弃与该图层进行通信的场景中的任何孩子,最有可能的是,您必须设置场景的'sharedGameLayer = nil'' onExit'。如果你小心点,可以使用'removeFromParentAndCleanup',然后将节点添加到其他场景的图层。子节点应该确保检查'sharedGameLayer'是否返回'nil'。 –

相关问题