我正在读学习Cocos2d 2;并且偶然发现了这个问题:在游戏场景中,可能在场景层次结构下面有数千个实体,并且所有这些实体可能想要与最顶层的场景对象进行对话。 Learn Cocos2d 2的作者建议使用像这样的全局变量
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中一次只能有一个场景,所以这种方法大部分时间都可以正常工作而没有任何问题。但从设计的角度来看,我仍然觉得这种做法缺乏。
我考虑过两种选择:
使用适当的(旧)委托方法。在每个级别分配正确的委托/委托者关系。但是,这意味着数千行可能重复的代码,并且从我的角度看并不整洁
使用NSNotification(或KVO?)从子级别广播消息,并让父母做出相应的响应。但这是否意味着系统不必要的开销
此时我很遗憾,有人可以告诉我有经验的程序员可能会使用的一般习语吗?
答案 0 :(得分:1)
您可能需要阅读我的“Strategies for accessing other nodes in the hierarchy”指南。有很多选择,有利有弊。
答案 1 :(得分:0)
在大多数情况下,CCNode
s树的叶子,就像您提到的“玩家实体”一样,只有在{{1}上包含CCScene
时才会持续存在。场景堆栈。一旦弹出此场景,它将收到CCDirector
消息,从而dealloc
(其)removeAll
。这反过来将Children
这些孩子,包括你的“玩家权利”。您的“玩家实体”将收到的最后一条消息是dealloc
,在此期间所有父节点仍处于活动状态(尽管在被破坏的过程中),因此永远不会出现儿童请求无效dealloc
的情况。 1}}。但是,如果你想把任何孩子带到另一个场景,你必须在很多方面都非常小心,如果不是绝对必要,这几乎不值得鼓励。例如,您的特定代码块必须进行改进,以便sharedGameLayer
如果场景不再处于活动状态将返回sharedGameLayer
,并且您的“播放器实体”可能想要检查此返回值。 / p>
简短的回答是,只要您不在场景堆栈中移动节点,上面显示的代码就是安全的。各个节点有许多替代方法可以了解游戏的“图表”,包括每个nil
的{{1}}属性以及parent
的{{1}}属性