0

我在读Learn 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 中一次只能有一个场景,所以这种方法可能在大部分时间都可以正常工作,没有任何问题。但从设计的角度来看,我仍然觉得缺乏这种方法。

我想过两种选择:

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

  2. 使用 NSNotification(或 KVO?)从子级广播消息,并让父级做出相应的响应。但这是否意味着系统不必要的开销

在这一点上我很迷茫,有人可以告诉我有经验的程序员可能会使用的一般习语吗?

4

2 回答 2

1

You may want to read my "Strategies for accessing other nodes in the hierarchy" guide. Plenty of options to choose from with pros and cons.

于 2013-01-23T12:12:36.327 回答
0

在大多数情况下,您的 s 树的叶子CCNode,例如您提到的“玩家实体”,只要包含CCSceneCCDirectors 的场景堆栈中,就会持续存在。一旦这个场景被弹出,它将收到一条dealloc消息,因此removeAll(its) Children。这反过来将dealloc这些孩子,包括你的“玩家实体”。您的“玩家实体”将收到的最后一条消息是,dealloc在此期间所有父节点仍处于活动状态(尽管正在被破坏),因此永远不会出现子节点请求无效的情况sharedGameLayer. 但是,如果您想将任何孩子带到另一个场景中,则必须在很多方面都非常小心,如果不是绝对必要的话,这几乎没有什么值得鼓励的。例如,必须改进您的特定代码块,以便在场景不再处于活动状态sharedGameLayer时返回,并且您的“玩家实体”可能想要检查此返回值。nil

简短的回答是,只要您不在场景堆栈中移动节点,上面显示的代码就是安全的。单个节点有许多替代方法可以了解游戏的“图形”,包括each的parent属性CCNode和.runningSceneCCDirector

于 2013-01-23T01:13:34.830 回答