具有合成和 CCSpriteBatchNode 的游戏对象 [英] Game object with composition and CCSpriteBatchNode

查看:14
本文介绍了具有合成和 CCSpriteBatchNode 的游戏对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在 iPhone 上使用 cocos2d 和 box2d 开发游戏.
我阅读了很多关于游戏代码组织、游戏对象结构等的文章.我首先通过继承自 CCSprite 的基类本身来开发我的游戏对象.我有一个 CCSpriteBatchNode 来在一次绘制调用中绘制所有玩家可以与之交互的游戏项目.这很简单,因为我的 Item 类间接继承自 CCSprite,因此我可以轻松地将我的项目添加到 CCSpriteBatchNode.最重要的是,我可以依靠 cocos2d 来保留我的对象.

I'm currently developing a game with cocos2d and box2d on iPhone.
I read a lot of articles concerning game code organization, game objects structure etc. I first started developing my game objects by inheriting from a base class itself inheriting from CCSprite. I had a CCSpriteBatchNode to draw all the game items, which the player can interact with, in one draw call. This was easy because my Item class indirectly inherit from CCSprite so I could easily add my items to the CCSpriteBatchNode. And on top of that I could rely on cocos2d to retain my objects.

阅读文章后,我明白需要用更面向组合的风格而不是继承风格来重构我的代码.所以我选择了一个继承自 NSObject 并具有一个或多个 CCSprite、一个 b2Body 等属性的 GameObject 基类.

After I read the articles, I understood the need to refactor my code with a more composition oriented style rather than the inheritance style. So I went with a GameObject base class inherited from NSObject and having properties such as one or more CCSprite, one b2Body etc.

我现在面临的问题是我不能再直接将我的游戏对象添加到 CCSpriteBatchNode 中.我首先认为我可以通过将 GameObject 的 sprite 属性添加到 CCSpriteBatchNode 来轻松解决问题.没关系,但谁保留拥有 CCSprite 的对象?如何从 CCSprite 轻松访问原始对象(userData/Object 是否正常)?

The problem I'm facing now is that I can't directly add my GameObject to the CCSpriteBatchNode anymore. I first thought I could easily fix the problem by adding the sprite property of the GameObject to the CCSpriteBatchNode. It's ok but who retains the object owning the CCSprite ? How can I easily access the original object from the CCSprite (are userData/Object ok) ?

我应该创建一个数组来保留我的物品吗?我想知道您将如何使用具有这种游戏对象结构的 CCSpriteBatchNode ?

Should I create an array retaining my items ? I'd like to know how you would use a CCSpriteBatchNode with such a game object structure ?

已经有一个线程关于未回答的问题,我真的喜欢听这个话题.不是一个直截了当的答案,但有一些要更进一步的元素.

There is already a thread about that which is unanswered and I'd really like to hear about the subject. Not a straight answer but some elements to go further.

谢谢.

推荐答案

我个人不推荐使用 NSObject 作为 cocos2d 类的基类了.仅仅因为你失去了一些 cocos2d 的便利功能,比如调度,你可以很容易地在内存管理方面自责.

Personally I don't recommend using NSObject as the base class for cocos2d classes anymore. Simply because you lose some cocos2d convenience features such as scheduling and you can easily shoot yourself in the foot, memory-management wise.

您想要的是场景具有一个或多个精灵批处理节点的设置.您可以将它们视为您的精灵的图层.从 CCNode 派生的实际游戏对象(将它们视为 MVC 控制器)可以添加到任何地方,通常直接添加到场景中.

What you want is a setup where the scene has one or more sprite batch nodes. You can consider them layers for your sprites. Your actual game objects (consider them to be MVC controllers) deriving from CCNode can be added anywhere, typically directly to the scene.

scene
 + batch node 1
   + sprite 1
   + sprite 2
   + sprite n
 + batch node 2
   + sprite 1
   + sprite 2
   + sprite n
 + game node 1
 + game node 2
 + game node 3
 + game node n

要记住的是,每个游戏节点都有一个或多个精灵作为实例变量,但它们不是节点的子节点.例如,游戏节点 1 类可能如下所示:

The thing to keep in mind is that each game node has one or more sprites as instance variables, but they're not childs of the node. So for example the game node 1 class might look like this:

game node 1 class
  CCSprite* sprite1;  // instance variable
  CCSprite* sprite2;  // instance variable

现在,当您初始化游戏节点 1 及其精灵时,您将精灵添加到适当的精灵批处理节点.通常,您会希望像单例一样访问场景以访问其 sprite 批处理属性.

Now when you init game node 1 and its sprites, you add the sprites to the appropriate sprite batch node. Typically you will want to access your scene like a singleton to get access to its sprite batch properties.

sprite1 = [CCSprite spriteWithSpriteFrameName:@"doodle.png"];
[[scene sharedScene].batchNode1 addChild:sprite1];
sprite2 = [CCSprite spriteWithSpriteFrameName:@"splash.png"];
[[scene sharedScene].batchNode2 addChild:sprite2];

请注意,您不需要保留精灵,只要它们是精灵批处理节点的子节点.addChild 方法为您保留它.实际上,它只是将其添加到执行保留的数组中.另外,如果您仍在考虑保留",请务必 开始使用 ARC.

Note that you do not need to retain the sprites as long as they are children of the sprite batch node. The addChild method retains it for you. Actually, it just adds it into an array which does the retaining. Also, if you're still thinking about "retain", by all means start using ARC.

您不需要弄清楚如何访问 sprite 批处理中的 sprite.它可作为游戏节点类的实例变量使用,如果您愿意,也可以将其作为属性公开提供给其他类.

You do not need to figure out how to access the sprite in the sprite batch. It's available as an instance variable of your game node class, and if you wish, you can also make it publicly available to other classes as a property.

游戏节点类显然运行所有对象的游戏逻辑,包括定位和修改精灵的属性.在游戏节点类中唯一需要注意的是从批处理节点中删除精灵,否则可能会泄漏.为此,请覆盖清理方法:

The game node class obviously runs all the object's game logic, including positioning and otherwise modifying the sprite's properties. The only thing you need to take care of in the game node class is that you remove the sprites from the batch node, otherwise it may be leaking. To do so, override the cleanup method:

-(void) cleanup
{
    [sprite1 removeFromParentAndCleanup:YES];
    sprite1 = nil;
    [sprite2 removeFromParentAndCleanup:YES];
    sprite2 = nil;

    [super cleanup];
}

将变量设置为 nil 很重要,因为清理后可能会有代码运行,包括 dealloc 方法中的代码.您也可以删除 dealloc 中的精灵,但根据您的设置,由于对游戏节点类仍持有的精灵的引用,甚至可能不会调用 dealloc.因此,如果精灵不是游戏节点类本身的子(或孙),则使用清理方法通常更安全.

It's important to set the variables to nil because there may be code running after cleanup, including the code in the dealloc method. You could also remove the sprites in dealloc but depending on your setup, dealloc may not even get called because of the references to the sprite the game node class is still holding. Therefore it is generally safer to use the cleanup method if the sprites are not children (or grandchildren) of the game node class itself.

这篇关于具有合成和 CCSpriteBatchNode 的游戏对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆