Cocos2d iphone 具有合成和CCSpriteBatchNode的游戏对象

Cocos2d iphone 具有合成和CCSpriteBatchNode的游戏对象,cocos2d-iphone,code-organization,Cocos2d Iphone,Code Organization,我目前正在用iPhone上的cocos2d和box2d开发一款游戏。 我读了很多关于游戏代码组织、游戏对象结构等的文章。 我第一次开始开发游戏对象是从一个基类继承而来,基类本身继承自CCSprite。 我有一个CCSpriteBatchNode来绘制所有游戏项目,玩家可以在一次绘制调用中与之交互。这很容易,因为我的Item类间接继承自CCSprite,因此我可以轻松地将我的项添加到CCSpriteBatchNode。除此之外,我还可以依靠cocos2d来保存我的对象 在阅读了这些文章之后,我理解

我目前正在用iPhone上的cocos2d和box2d开发一款游戏。
我读了很多关于游戏代码组织、游戏对象结构等的文章。 我第一次开始开发游戏对象是从一个基类继承而来,基类本身继承自CCSprite。 我有一个CCSpriteBatchNode来绘制所有游戏项目,玩家可以在一次绘制调用中与之交互。这很容易,因为我的Item类间接继承自CCSprite,因此我可以轻松地将我的项添加到CCSpriteBatchNode。除此之外,我还可以依靠cocos2d来保存我的对象

在阅读了这些文章之后,我理解了用更面向组合的风格而不是继承风格重构代码的必要性。 所以我使用了一个从NSObject继承的GameObject基类,它具有一个或多个CCSprite、一个b2Body等属性

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

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

关于这个问题已经有很多问题没有答案,我真的很想听听这个问题。这不是一个直截了当的答案,但有一些因素需要进一步研究


谢谢。

就我个人而言,我不建议再将NSObject用作cocos2d类的基类。仅仅因为你失去了一些cocos2d的便利功能,比如日程安排,你就可以很容易地攻击自己,内存管理也很明智

您需要的是一个设置,其中场景具有一个或多个精灵批处理节点。你可以把它们当作你的精灵。从CCNode派生的实际游戏对象(将其视为MVC控制器)可以添加到任何位置,通常直接添加到场景中

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
需要记住的是,每个游戏节点都有一个或多个精灵作为实例变量,但它们不是节点的子节点。例如,game node 1类可能如下所示:

game node 1 class
  CCSprite* sprite1;  // instance variable
  CCSprite* sprite2;  // instance variable
现在,当您初始化游戏节点1及其精灵时,将精灵添加到相应的精灵批处理节点。通常,您会希望像单个对象一样访问场景,以访问其“精灵批处理”属性

sprite1 = [CCSprite spriteWithSpriteFrameName:@"doodle.png"];
[[scene sharedScene].batchNode1 addChild:sprite1];
sprite2 = [CCSprite spriteWithSpriteFrameName:@"splash.png"];
[[scene sharedScene].batchNode2 addChild:sprite2];
请注意,只要精灵是“精灵批处理”节点的子级,就不需要保留精灵。addChild方法为您保留它。实际上,它只是将其添加到一个数组中,该数组执行保留操作。另外,如果你还在考虑“保留”,那就千方百计

您不需要了解如何在精灵批处理中访问精灵。它可以作为游戏节点类的实例变量使用,如果您愿意,还可以将其作为属性公开给其他类

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

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

    [super cleanup];
}

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

谢谢你的回答。如果我理解你的意思,添加游戏对象有两个步骤:将游戏对象添加为场景的节点(无视觉表示),然后添加游戏对象需要显示的任何视觉表示(在精灵批处理节点或仅在层中)。我之所以想在“精灵批处理”节点中访问CCSprite,是因为我沿x轴移动了它们(或者更确切地说,移动了它们“连接”到的主体)。也许这不是我应该做的。。。