iPhone Cocos2D游戏编程教材中的循环引用教材、游戏、iPhone、Cocos2D

2023-09-06 10:36:58 作者:青春为你更新

一个被滥用的话题,但我找不到答案.我正在关注学习 iPhone 和 iPad cocos2d 游戏开发"一书,无法真正理解 ShootEmUp 示例中的方法(可在 1) 是最好的.作者使用了一个 GameScene,其中添加了各种对象(例如 Ship、InputLayer 等)作为子对象.有争议的方面是,在这些对象中,通过使用静态方法调用 GameScene,该方法返回 GameScene 类的静态实例,该实例在 GameScene 的 init 方法中实例化.对我来说,这似乎是一个循环引用,并且根据许多 (例如,参见这篇文章) 是要避免的.我不确定在游戏编程中是否也是如此,因为这种方法可以在 1 这可能是有原因的.

an abused topic but I couldn't find an answer to this. I am following the "Learn iPhone and iPad cocos2d Game Development" book and cannot really understand if the approach in the ShootEmUp example (available at 1) is the best one. The author uses a GameScene to which adds as child various objects (e.g. Ship, InputLayer etc..). The controversial aspect is that within those object there are calls to the GameScene via using a static method that returns a static instance of the GameScene class that is instantiated in the init method of GameScene. This to me seems a circular reference and according to many (e.g. see this post) is something to avoid. I am not quiet sure if that's also true in Game Programming as this approach is found in 1 and there might be a reason for this.

谁能解释一下?我不确定是完全重构我的代码还是保留静态变量方法.

Would anyone be able to clarify? I am undecided whether to restructure my code completely or keep the static variable approach.

非常感谢:)!

源代码

推荐答案

这里看到的是半单例模式,它在整个 Cocos 中被广泛使用,实际上 Cocos 框架本身是完全建立在单例对象上的(如是很多Apple的UIKit).游戏经常使用单例,因为您通常在游戏中拥有大量中心数据,例如分数、健康、武器等,您的许多对象都需要了解这些数据.您通常还有一些对象,例如玩家、敌人等,它们需要通知您的应用程序的中央调度他们正在做什么,以便游戏中的其他对象可以做出相应的反应或调整.

What you see here is a semi-singleton pattern, and it is used extensively throughout Cocos, in fact the Cocos framework itself is built entirely on singleton objects (as is a lot of Apple's UIKit). Games frequently employ singletons because you typically have a lot of central data in a game, like scores, health, weapons, etc that many of your objects need some knowledge of. You also typically have objects, like players, enemies, etc that need to notify the central dispatch of your app what they are doing so other objects in the game can react or adjust accordingly.

这就是为什么许多 Cocos 游戏使用您在此处展示的技术的原因.如果您了解单例编程的风险,这不是一个坏习惯.基本上,请记住这一点:

This is why many Cocos games use the technique you've shown here. It is not bad practice if you understand the risks of singleton programming. Basically, keep this in mind:

无论您是使用单例式技术还是使用其他方法调用父级,您基本上都在做同样的事情.直接引用中央游戏引擎可能比依赖方法为您派生它更好.我不建议使用 [self parent] ,因为当您首先必须弄清楚谁是父母"时,这可能会变得难以阅读和调试,而单例访问可以让您立即知道自己是谁访问.孩子永远不应保留其父母.您可以引用父级,但不要保留.这里的单例方法的替代方法是在子节点中创建一个指向父节点的 iVar.但这本质上是相同的想法,因此为了最大限度地降低保留周期的风险,访问单例通常更安全.如果您的 iVar 设置不正确,您可能会有一个循环引用.您在此处显示的方法不是循环引用. Whether you use a singleton-style technique or instead call up the parent using another method, you are essentially doing the same thing either way. It's probably better to directly reference the central game engine directly than rely on methods to derive it for you. I would not recommend using [self parent] as that can get hard to read and debug later when you first have to figure "who is the parent," instead a singleton access lets you know immediately who you are accessing. A child should never retain its parent. You can reference the parent, but don't retain. An alternative to the singleton approach here is to make an iVar in the child that points to the parent. But this is essentially the same idea, so to minimize the risks of a retain cycle, accessing the singleton is typically safer. If your iVar is not set properly, you could have a circular reference. The method you've shown here is not a circular reference.

请注意,此特定代码会阻止您使用 +(GameScene*) sharedGameScene 方法,直到 GameScene 已初始化.这就是使它成为半单例的原因.通常情况下,单例中的这个方法会很聪明,如果它还没有初始化,那么它会自动初始化,这样使用这个类方法要么返回,要么先创建然后返回对象.

Note that this particular code prevents you from using +(GameScene*) sharedGameScene method until after the GameScene has been initialized. This is what makes it a semi-singleton. Typically, this method in a singleton will be smart enough to initialize itself if it is not already initialized so that using this class method either returns or first creates and then returns the object.

在 Cocos 中可能不是问题,因为您可能会在执行任何其他操作之前初始化游戏场景,因此它已经存在.

Probably not an issue in Cocos since you will likely initialize the Game Scene before you do anything else, so it will already exist.