Saturn
Saturn

Reputation: 18139

How to use CCSpriteBatchNode properly?

I add my sprite frames to CCSpriteFrameCache. Then I create a CCSpriteBatchNode with my desired image file.

This is what I don't quite understand:

When I make a CCSprite, if I want to take advantage of the CCSpriteBatchNode, I need to initialize the CCSprite with [CCSprite spriteWithBatchNode: rect:]? But if that's the case, I don't see how am I taking advantage of CCSpriteFrameCache to get the frames, since now I would be manually making the rect.

So I guess I use [CCSprite spriteWithSpriteFrameName:] and then I add this sprite to the batch node. But I am still unsure.

Upvotes: 1

Views: 2467

Answers (2)

S.H.
S.H.

Reputation: 2853

According to what I've learned of cocos2d. SpriteFrameCache and SpriteBatchNode have the same result but are used differently and can notice a slight performance difference if your game is very big...

CCSpriteFrameCache loads your frames according to when they are called by their named according to the plist file it was given. The atlas associated with the plist has to be added to the project as well or else the frames will be called but nothing will be found to be drawn. The Plist is like the address of where the image is located inside the image atlas. The good part of CCSpriteFrameCache is that the code is neater, and smaller than CCSpriteBatchNode method, at the cost that for every call of that frame, it goes to that specific atlas and draws it.

CCSpriteBatchNode, on the other hand, loads the atlas and loads it in one draw call. This is efficient because it reduces the amount of times the draw has to be done per need in the game. The only difficulty here is that you need to do math for the rectangles of each sprite in the atlas. This is because lets say your atlas is of 2 actions of a character, the atlas image file has a size of 1024x1024, and each sprite has a size of 128x128. so you would do the math to get each rectangle for the whole jump action for example.(This is where .plist come in handy to avoid doing such math)

The code gets complicated as you can see but it will only do one call, making it performance-wise your best call. Another way to use CCSpriteBatchNode is to have different static sprites and you would just do one draw call for those multiple static images or sprites.

If you need example code just ask, I would be more than happy to provide it.


Update: Adding Link for SpriteBatchNode and an Example of my own.

SpriteBatchNode:

Example using SpriteBatchNode with Ray Wenderlich I believe in this guy, and I have learned alot of Cocos2d from his tutorials. I would suggest you to read other of his tutorials.

In a nutshell, CCSpriteBatchNode is the exact same process we did below with the CCSpriteFrameCache the ONLY difference and its that you add the Sprite Child Node to the CCSpriteBatchNode and not the Layer, BUT you do Add the CCSpriteBatchNode to the Layer. This is the hard concept that new comers to Cocos2d get entangled at.


SpriteFrameCache:

The SpriteFrameCache I couldn't find a good example so here is one simple one.

//By doing this your sprites are now in the cache ready to be used 
//by their names declared in the .plist file.
-(void) loadingSprites:(NSString*) plistName {
     [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:plistName];

}

-(id)initGameLayer {
     //CCSprite accepts CCSpriteFrame and your img is now ready to be displayed.
     //However is still not drawn yet.
     CCSprite * mySprite = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:framename];


     //set a position if desired 
     //20 pixels to the right and 0 pixels to the top.
     mySprite.position = CGPointMake(20,0);

     //Now the Image has been drawn, making 1 draw call.
     [self addChild:mySprite];

 }

It is noteworthy to point out that CCSpriteBatchNode makes just 1 drawcall, HOWEVER all the sprites being added to the batchnode have to be part of the same SpriteAtlas.

And using SpriteFrameCache only its easier and simpler, but for every child added to the layer it means +1 draw call is being done.(This is the downside, performance)

So if you add 10 Sprites to the layer with SpriteFrameCache you will have 10 drawcalls.

However if you implement the SpriteBatchNode and add those 10 Sprites in the CCSpriteBatchNode instead and just add that CCSpriteBatchNode to the layer, you will have the same 10 sprites added but only ONE draw call will be done. Hence the Performance difference(for the best) will be significant in larger games.

Hope it helps, Cheers!

Upvotes: 4

Fernando
Fernando

Reputation: 7895

You should use:

CCSprite *sp = [CCSprite spriteWithSpriteFrameName:@"monster.png"];

The .plist that you specified in the SpriteFrameCache will take care of the frames for you. Then you create the sprite and add to the batch.

If you create the batchnode with a file called "myArt.png", you CAN ONLY add a sprite to it that is contained inside "myArt.png".

Hope it helps!

Upvotes: 4

Related Questions