我应该inheritanceCCSprite,CCNode还是NSObject?

我看到某些文本似乎总是将CCSprite子类化。 我在某个地方读到这样做并不好,最好从基本的东西开始。 我想知道专业游戏开发者在游戏结构方面做了些什么。 这是CCSprite的子类或在NSObject类ETC中添加CCSprite。

我希望我的问题有道理。

你的问题肯定是有道理的。

这基本上是一个架构问题。 如果你的游戏主要基于“动画”,我会去CCSprite的子类。 如果您的游戏主要基于某些逻辑,可能是RPG或其他任何东西,那么屏幕表示实际上只是游戏状态的可能视图之一。 因此,在我看来,它应该是表示游戏状态的对象树中的一个对象的一部分。

换句话说:如果你的游戏状态本质上是一个场景,那么子类CCSprite,因为Cocos2D在管理场景方面可能比你更好。 如果你的游戏状态是“其他东西”,你可能应该考虑建立你自己的状态表示,并使你的精灵成为游戏对象的一部分。 如果您决定更改渲染,这还允许您“切换”图形引擎。 例如,您可能正在使用Cocos2D中的2D表示进行RPG。 过了一会儿,你向Ubisoft展示你的演示,他们爱上它并给你2000万美元来完成它,但他们要求3D渲染。 如果你去CCSprite的子类,你必须重做所有的游戏。 如果你想在一个NSObject派生的类中集成CCSprite / CCNode,你就可以了。

当然,这个例子有点夸大了……例如:D

我的偏好是几乎完全CCNode的子类

如果我需要精灵,标签或任何与基本实现略有不同的行为,我只会inheritanceCCSprite,CCLabel和其他内部Cocos2D类的子类。 如果类别不足,子类化将是最后的手段。 大多数Cocos2D开发人员显然不明白的是,CCSprite本身就是一个完整的类,不需要扩展(子类)来表示游戏对象。 但是很容易陷入这种习惯,因为通过创建CCSprite子类,您可以获得视觉效果,并且您拥有游戏逻辑代码的容器。 这样做不是很好。

如果你考虑一下,只要你向CCSprite添加某种游戏逻辑代码,它就不再只是一个CCSprite,或者是它? 考虑它的一个好方法是:如果你inheritance一个类(将其命名为MyClass)并向其添加自定义代码,那么将MyClass子类化为其他目的是否有意义呢? 如果没有,那么你不应该是子类。

要使用广泛使用的“Car”类的OOP类比:你将“Car”子类化为更专业但仍然是通用的类,如“SportsCar”,“Truck”,“Van”,但你不会将“Car”子类化为打造“保时捷911 V-Turbo Model 6”。 为什么不? 因为“SportsCar”类具有创建SportsCar 实例的所有方面,然后成为“保时捷911 V-Turbo Model 6”。

你需要考虑的另一件事是“保时捷911 V-Turbo Model 6”将是一个高度专业化的类别,除了定义那辆非常具体的汽车之外没有任何其他目的。 将“Porsche 911”类子类化是没有任何意义的,因为它基本上已经丢失了它的通用属性,并用非常具体的实现细节替换它们。 如果你有一个你无法合理地inheritance的类,那么你已经在类层次结构中创建了一个死胡同,并且本质上是编写function代码,而不是面向对象的代码。 尽管如此,它对于简单的游戏来说还是可以的,但是如果你敢于做更多的事情,它会回来困扰你。

总结一下:只有当你的目的是制作一个更专业但仍然普遍可用的CCSprite时,你才会inheritanceCCSprite。 其中一个例子是CCLabelTTF,它是CCSprite的子类。 它只增加了在运行时从字体和字符串创建CCSprite纹理的function。 子类化CCSprite的另一个例子是,如果您需要一个CCSprite,它将从谷歌地图更新其纹理,使其类似于基于经度和纬度坐标和缩放级别的地图图块。 它仍然基本上是一个愚蠢的对象,其唯一目的是在某个位置显示矩形图像。 这就是CCSprite。 一个在某个位置显示纹理的哑对象。

问题实际上是这样的:你的游戏对象 (“是一个”)一个精灵,或者它的视觉表现是否 (“有一个”)一个精灵? 答案应该始终是后者。 子类化的通用规则是“是一种”关系,如果“有一个”它是复合模式的时间。 如果有疑问,两者似乎都适用,总是在“有一个”方面犯错,因为这总是有效的。

为什么我会说游戏对象不是精灵,而是有精灵? 显然两者都适用。 答案:游戏对象“只是一个”精灵,只要它可以由一个精灵表示而不是别的。 但事实上,您的游戏对象可能必须由多个精灵,精灵,标签和一些粒子效果来表示。 这意味着随着应用程序的开发,“是一种”关系更容易破裂,这意味着额外的重构工作。

通过使用CCNode作为游戏对象的基类,并将可视节点添加到该基本节点,您还可以使用基节点作为游戏对象视图的控制器对象。 这意味着它将更好地符合模型 – 视图 – 控制器(MVC)模式。

最后,我不会将NSObject子类化为应该位于cocos2d视图层次结构中的任何内容,或者保留对cocos2d视图层次结构中某些内容的引用。 原因很简单,NSObject子类不提供CCNode的任何标准function(调度,添加子节点,子节点的相对定位),最重要的是,很难将NSObject子类与Cocos2D的自动内存管理结合使用。节点类。

没有详细说明,简单的规则是,如果一个子类具有一个Cocos2D节点的实例变量,它本身应该是一个Cocos2D节点,这样内存管理和所有其他方面都很容易和万无一失。 就Cocos2D而言,CCNode类是视图层次结构的根类,因此它类似于UIResponder类,能够承担UIView和/或UIViewController类的角色(顺便说一下,这两个类都来自UIResponder)在场合。

简而言之:子类CCNode,然后使用组合/聚合模式来表示类的视觉方面。

如果您在Cocos2D之旅中有这个问题,请inheritanceCCSprite的子类并完成它。 您现在不会创建任何需要微调类高级技术的东西。 我说这不是对你的能力的侮辱,而是一个曾经有过这个问题的人。

当您开始怀疑是否需要重写CCNode的OpenGL方法调用时,那么您将需要仔细考虑子类化选项。 子类化CCSprite可以为您提供更低级的所有方法和属性,使您能够发现,学习和前进。

简而言之:子类CCSprite。

在我看来,游戏中的对象不是精灵。 Sprite是对象的表示,它意味着你需要创建GameObject子类NSObject(也许是CCNode)..

总结一下:子类NSObject或CCSprite是类结构,您需要使用您的代码样式。