我看到某些文本似乎总是将CCSprite子类化。我在某个地方读到这样做并不好,最好从基本的东西开始。我想知道专业游戏开发者在游戏结构方面做了些什么。这是CCSprite的子类或在NSObject类ETC中添加CCSprite。
我希望我的问题有道理。
答案 0 :(得分:45)
我的偏好是几乎完全的CCNode子类。
如果我需要精灵,标签或任何与基本实现略有不同的行为,我只会继承CCSprite,CCLabel和其他内部Cocos2D类的子类。如果类别不足,子类化将是最后的手段。大多数Cocos2D开发人员显然不明白的是,CCSprite本身就是一个完整的类,不需要扩展(子类)来表示游戏对象。但是很容易陷入这种习惯,因为通过创建CCSprite子类,您可以获得视觉效果,并且您拥有一个用于游戏逻辑代码的容器。这样做不是很好。
如果您考虑一下,只要您向CCSprite添加某种游戏逻辑代码,它就不再仅仅是CCSprite,或者是它?考虑它的一个好方法是:如果你继承一个类(将其命名为MyClass)并向其添加自定义代码,那么将MyClass子类化为其他目的是否有意义?如果没有,那么你不应该是子类。
使用" Car"广泛使用的OOP类比。 class:你是子类" Car"制作更专业但仍然是通用的课程,如" SportsCar"," Truck"," Van"但是你不会将#34; Car"创造一辆保时捷911 V-Turbo Model 6"。为什么不?因为" SportsCar" class具有创建SportsCar的实例的所有方面,然后成为保时捷911 V-Turbo Model 6"。
你需要考虑的另一件事是保时捷911 V-Turbo Model 6"将是一个高度专业化的课程,除了定义非常具体的汽车是什么之外没有任何其他目的。将保时捷911""保时捷911"进行分类是没有任何意义的。 class因为它基本上丢失了它的泛型属性,并用非常具体的实现细节替换它们。如果你有一个你不能进一步合理地继承的类,那么你已经在类层次结构中创建了一个死胡同,并且本质上是编写功能代码,而不是面向对象的代码。尽管如此,对于简单的游戏来说还是可以的,但是如果你敢于做更多游戏,它会再次困扰你。
总结一下:只有当你的目的是制作一个更专业但仍然普遍可用的CCSprite类型时,你才会继承CCSprite。其中一个例子是CCLabelTTF,它是CCSprite的子类。它只增加了在运行时从字体和字符串创建CCSprite纹理的功能。子类化CCSprite的另一个例子是,如果您需要一个CCSprite,它将从谷歌地图更新其纹理,使其类似于基于经度和纬度坐标和缩放级别的地图图块。它仍然基本上是一个愚蠢的对象,其唯一目的是在某个位置显示矩形图像。这就是CCSprite的意义所在。一个在某个位置显示纹理的哑对象。
问题的确如此:是("是#34;)您的游戏对象是精灵,或拥有(&#34) ;有一个")一个用于视觉表现的精灵?答案应该始终是后者。子类化的通用规则是"是"关系,如果"有"这是composite pattern的时间。如果有疑问,并且两者似乎都适用,那么总是错误的"有一个"因为这总是有效的。
为什么我会说游戏对象不是精灵,而是有精灵?显然两者都适用。答案:游戏对象"是"精灵只要它可以由一个精灵表示而没有别的。但事实上,您的游戏对象可能必须由多个精灵,精灵,标签和一些粒子效果来表示。这意味着"是"随着应用程序的开发,关系更容易破裂,这意味着额外的重构工作。
通过使用CCNode作为游戏对象的基类,并将可视节点添加到该基本节点,您还可以使用基节点作为游戏对象视图的控制器对象。这意味着它更好地符合模型 - 视图 - 控制器(MVC)模式。
最后,我不会将NSObject子类化为cocos2d视图层次结构中的任何内容,或者保留对cocos2d视图层次结构中某些内容的引用。原因很简单,NSObject子类没有提供CCNode的任何标准功能(调度,添加子节点,子节点的相对定位),最重要的是,它很难与NSObject子类一起使用Cocos2D是节点类的自动内存管理。
没有详细说明,简单的规则是,如果一个子类具有一个Cocos2D节点的实例变量,它本身应该是一个Cocos2D节点,这样内存管理和所有其他方面都很容易和万无一失。就Cocos2D而言,CCNode类是视图层次结构的根类,因此它类似于UIResponder类,能够承担UIView和/或UIViewController类的角色(UIResponder的子类)顺便说一句。在场合。
简而言之:子类CCNode,然后使用组合/聚合模式来表示类的视觉方面。
答案 1 :(得分:12)
你的问题绝对有道理。
这基本上是一个架构问题。如果你的游戏主要基于“动画”,我会去CCSprite的子类化。如果您的游戏主要基于某些逻辑,可能是RPG或其他任何东西,那么屏幕表示实际上只是游戏状态的可能视图之一。因此,在我看来,它应该是表示游戏状态的对象树中的一个对象的一部分。
换句话说:如果你的游戏状态本质上是一个场景,那么子类CCSprite,因为Cocos2D在管理场景方面可能比你更好。如果你的游戏状态是“其他东西”,你可能应该考虑构建你自己的状态表示,并使你的精灵成为游戏对象的一部分。如果您决定更改渲染,这还允许您“切换”图形引擎。例如,您可能正在使用Cocos2D中的2D表示进行RPG。过了一会儿,你向Ubisoft展示你的演示,他们爱上它并给你2000万美元来完成它,但他们要求3D渲染。如果你去CCSprite的子类,你必须重做所有的游戏。如果你想在一个NSObject派生类中集成CCSprite / CCNode,你就可以了。
当然,这个例子有点夸大了......例如:D
答案 2 :(得分:6)
如果您在Cocos2D之旅中有这个问题,请将CCSprite子类化并完成。您现在不会创建任何需要微调类高级技术的东西。我说这不是对你的能力的侮辱,而是作为曾经有过这个问题的人。
当你开始怀疑是否需要重写CCNode的OpenGL方法调用时,那么你将需要仔细考虑你的子类化选项。子类化CCSprite可以为您提供更低级别的所有方法和属性,使您能够发现,学习和前进。
简而言之:子类CCSprite。
答案 3 :(得分:0)
在我看来,游戏中的对象不是精灵。 Sprite是对象的表示,它意味着你需要创建GameObject子类NSObject(也许是CCNode)..
总结:子类NSObject或CCSprite是类结构,您需要使用您的代码样式。