In today’s post I would like to share with you a handy piece of code to manage sprite sheets. I have called it TSSpriteSheetManager.
TSSpriteSheetManager is a singleton cocos2d class that allows for easily manage sprite sheets. You just add sprite sheets to the manager and then request a sprite or frame automatically batched for you. The manager will search for the sprite in all the added sprite sheets and if it is not in any of them, it will search for individual files on your project.
You have the entire source code for this project at the end of this article.
Motivation: batching and easy switching from individual files to sprite sheets
I usually start my game projects by prototyping without using sprite sheets from the very beginning of the development process (Muster my Monsters was not an exception). This allows me to make quick changes by just swapping files. Ok, maybe I’m also a bit lazy :p
However, sooner or later you will need to start using sprite sheets on your game (you know, performance). The process to switch to individual images to sprite sheets could be a pain in some circumstances.
On the other hand, it is usually recommended to use sprite sheets with cocos2d batching mechanism. This way, you can take advantage of the fact that all the frames of your game assets are in the same texture (or a few of them). This way, you can reduce considerably the draw calls and, therefore, the overall performance of your game.
So, to solve both problems in one shoot I coded this little singleton class called TSSpriteSheetManager.
TSSpriteSheetManager offers the following features:
- One single method to create CCSprites from a sprite sheet or a single image. This is very useful to switch from individual image files to sprite sheets. You tipically start your protoypes with individual files to test rapidly. TSSpriteSheetManager makes switching to sprite sheets a painless process.
- Automatic batching. TSSpriteSheetManager creates automatically CCSpriteBatchNodes when necessary. This allows for reducing the draw calls automatically.
- Supports iPhone, iPhone Retina, iPad and iPad Retina sprite sheets
First, you need to add some sprite sheets. You typically put this code in the “Loading…” section of your scene.
[[TSSpriteSheetManager sharedInstance] addSpriteSheetWithFile:@"all_head_spritesheet.plist" andTextureFormat:@"png"];
Then, to add a sprite to a node use this snippet:
CCSprite *head1 = [[TSSpriteSheetManager sharedInstance] addSpriteWithFileOrFrame:@"chuck_head__1.png" toNode:self autoBatching:YES]; head1.position = screenCenter;
As you can see, the addSpriteWithFileOrFrame:toNode:autoBatching: method adds the sprite automatically to the provided node. This is slightly different from the usual cocos2d work-flow. However, this is needed to perform the automatic batching of the sprite.
TSSpriteSheetManager offers an additional method:
You may use this method if you prefer to ignore all the automatic batching stuff, but still benefit from transparent loading of CCSprites from individual files or sprite sheets (see Limitations section below).
As usual, very easy to use 😉
Adding TSSpriteSheetManager into your Xcode 4 project
To add the TSSpriteSheetManager component to your project you simply need to drag & drop the entire “TSSpriteSheetManager” folder. There are only two files.
- CCMenu. Due to the particular nature of CCMenu you are not allowed to add CCSpriteBatchNodes to it. You can only add CCSprites to a CCMenu. So you can’t use the addSpriteWithFileOrFrame:toNode:autoBatching: method. However, you are still allowed to use spriteWithFileOrFrame: to just get the CCSprite and then add it to your CCMenu in the usual way.
- TSSpriteSheetManager uses cocos2d tags to manage the needed nodes for automatic batching. By default, the first CCSpriteBatchNode is created with the tag 9999. Take it into account to avoid collisions with your own nodes. You can change this default value by modifying the value of the constant kBatchNodesFirstTag at the top of the TSSpriteSheetManager.m file.
You have the source code of this project on GitHub.
I’m not completely conformable with this piece of code yet. I have been using it during the lasts days on the development of Muster my Monsters. However, I guess that it still needs some testing. Any kind of feedback is welcome! So, consider it a beta :p