1

I don't know if this is possible, but I would like to create one big texture atlas and use it on all classes of the application.

Can one CCSpriteBatchNode be used for multiple classes?

Suppose I create this on the main class

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"atlasGeral.plist"];
self.batchNodeGeneral = [CCSpriteBatchNode batchNodeWithFile:@"atlasGeral.png"];
[self addChild:self.batchNodeGeneral];

and I have another class creating CCLayers on the main class, that is initialized, before using CCSpriteBatchNode, like this:

-(id) init 
{

   if( (self=[super init])) {

        self.bg = [CCSprite spriteWithFile: @"cCircularBG.png"];
        [self addChild:self.bg];

        self.dr = [CCSprite spriteWithFile: @"cCircularDR.png"];
        [self addChild:self.dr];      
  }
  return self;  // self is a CCLayer
}

can this be optimized using the self.batchNodeGeneral from the main class? My idea is to replace these two sprites and others with something like [CCSprite spriteWithSpriteFrameName:...

thanks

Duck
  • 34,902
  • 47
  • 248
  • 470

1 Answers1

5

I'm not entirely sure I follow, but I'm pretty sure the answer is yes.

CCSpriteBatchNode doesn't have anything to do with classes, it has to do with assets. The important restriction on the use of batch nodes is that every sprite in the batch needs to reference the same texture atlas. So it is perfectly fine to have one batch node for your entire application and have every gameplay class add its own sprites to that batch. This can turn into a practical issue if your texture atlas becomes larger than the maximum texture size on your target hardware (see iOS device specs for details), but if you still want to have global batches and lots of assets it's not too hard to create a batch pool indexed by texture ID, create one batch node per atlas, and whenever you create a new sprite add it to the appropriate batch.

Honestly, I feel like the whole batch node thing is a terrible kludge on Cocos2D's part that could be made almost completely transparent to developers while still retaining its efficiency, but maybe this opinion is not entirely fair since I haven't dug around in the rendering code to understand their motivations. I guess it would mess with expectations of how depth sorting works, etc., but still I don't understand why batching objects for render is made the programmer's responsibility, it should be done by the engine.

Edit to add possible solution:

-(id) initWithMainClass:(MainClass*)mc
{

   if( (self=[super init])) {

        self.bg = [CCSprite spriteWithSpriteFrameName: @"cCircularBG.png"];
        [mc.batchNodeGeneral addChild:self.bg];

        self.dr = [CCSprite spriteWithSpriteFrameName: @"cCircularDR.png"];
        [mc.batchNodeGeneral addChild:self.dr];      
  }
  return self;  // self is a CCLayer
}
`

So when you initialize one of the other classes, you pass the main class instance as a parameter so you can access its fields. Or make the main/manager class a singleton or find another architecture suitable to your needs.

Suboptimus
  • 309
  • 1
  • 6
  • Thanks, but suppose your main class has a property called self.batchNodeGeneral and a method that will return that property, how would you rewrite the code I have posted on the init section to use that textures from that main class' self.batchNodeGeneral property? – Duck Jun 09 '12 at 20:14
  • Well that's more of an architectural decision for you. You can make your main object into something like a game manager responsible for the batch and make it a singleton, which seems to be a super-popular option for Cocos2D in particular and iOS development in general. Or you can have your other game classes take the main class as a parameter at initialization, so they have access to it. Depends a lot on how you think and what you're going for and architectural stuff like this can get very religious. – Suboptimus Jun 09 '12 at 20:17
  • ok, but my main point is this: on the main class I have this line [self addChild: self.batchNodeGeneral];... on the init part of a class how can I have another of these lines to add the same node again to that class? does not sound right and if I try it will crash. – Duck Jun 09 '12 at 20:20
  • Wow formatting in comments is so broken on this site, I added a hypothetical solution to my answer. Like I said you can also make the main/manager class a singleton or think of some celverer/eleganter solution according to your needs (this is a great programmer pastime). – Suboptimus Jun 09 '12 at 20:51
  • 3
    @Suboptimus: I agree, sprite batching can and should be automated when using texture atlases. The only downside of forcing sprite batching is that sprites from the same texture atlas can't easily be drawn between (z-order-wise) sprites from other batches. – CodeSmile Jun 09 '12 at 20:52
  • ahhhh, thanks. I thought I would have to add the node again in the class, but that makes things clear. Thanks. But this is something I don't understand. When I was adding the sprite on the class I was adding them as children to that class. Doing [mc.batchNodeGeneral addChild:self.bg]; as you mention, does not appear to be doing the same, I mean, the class is a CCLayer and that line does not appear to be adding the layers to the class... what I mean is this: I need the elements to appear on the CCLayer order being created and as I see these objects are not being added to CCLayer self. – Duck Jun 09 '12 at 22:03
  • 2
    Sorry, I didn't give proper consideration to the fact that you are creating CCLayers. A CCSprite can only have one parent, you can't add it to both the layer and a global sprite batch node, so you won't be able to do this with CCLayers. Unfortunately you can't even add CCLayers to a CCSpriteBatchNode with the correct texture because it only supports CCSprites as children. Definitely an annoyance especially since it limits your options to sensibly group your sprites while getting the best performance. Like I said, the batching in Cocos2D is a kludge and prevents you from doing sensible things. – Suboptimus Jun 10 '12 at 05:51