In this post I will use an Image Atlas to create sprites.
An Sprite Sheet (or Image Atlas) is an image with multiple images packed into one and a meta data file that goes along with it to specify where every image is placed in the sheet.
Creating a Sprite Sheet
It is much faster and more efficient to pack all the images that you want to use in your project as an sprite sheet. That is because Cocos2dx will draw all the sprites that are part of one sprite sheet in one OpenGL call and that will speed things up.
There are a couple of tools that you can use to create sprite sheets with.
- TexturePacker is another one that I am using now. It is also the one that is recommended by Cocos2d-x documentation.
- Zwoptex is the one I used for my first game Breakanator. I think it used to be free at the time!
There are other ones out there to use too. But these are the ones I have used so far and are pretty good.
So, from the previous sprite post, we had 5 images that we used to create our sprites from. Lets pack them as one and see how it goes…
I am going to use TexturePacker for this post because that is the one that I have a license for, but the other one is quite similar and even simpler to use.
- In TexturePacker, press the “Add sprites” button from the top shelf and choose the images that you want to import and press “Open”.
- In the setting bar at the right side of the screen, for “Data Format” choose “cocos2d-x”
- Turn on: “Force Square”
- Turn off: “Allow rotation”
- Set “Texture Format” to PVR and “Pixel Format” to PVRTCI 4bpp RGBA
- PVR is usually faster to load on devices. Also, be careful that apparently the compressed PVR format doesn’t work on Android devices.
- If you don’t get the same quality using PVR, then just use the PNG format! Although, you could probably bring down the size by using 4 bit pixels and dithered images.
- I usually set the “Size constraints” to be a power of two. For the PVR format we chose, it automatically forces that option.
- Everything else can be left as default.
- Press “Publish sprite sheet” button from the upper shelf.
- Select the Resources folder of your cocos project, give it a name (“spritesheet” in my case) and press “Save”.
Now you should have a .pvr and a .plist added to the Resources folder.
Adding Sprite Sheet to Xcode
- I create a new cocos project for this post in my project folder and call it spritesheet
cocos new spritesheet -p com.rezagn.games -l cpp -d ~/Projects/tests/cocos
- Add both the image file spritesheet.pvr (or png) and the spritesheet.plist to your resources in Xcode by right-clicking on the Resources folder in Xcode and choosing “Add files to…” from the menu.
Creating Sprites Using the Sprite Sheet
Creating sprites from a sprite sheet is very similar to creating sprites from images, with a couple of differences:
- First you need to add your sprite sheet meta data file to a pre-defined cache called SpriteFrameCache.
- When making sprites you should use Sprite::createWithSpriteFrameName() instead of Sprite::create().
Here is how the code inside the init method will look like now:
bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Scene::init() ) { return false; } auto visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto spriteCache = SpriteFrameCache::getInstance(); spriteCache->addSpriteFramesWithFile("spritesheet.plist"); auto ball = Sprite::createWithSpriteFrameName("ball.png"); ball->setPosition(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2 - 100); this->addChild(ball); auto pad = Sprite::createWithSpriteFrameName("pad.png"); pad->setPosition(origin.x + visibleSize.width / 2, 10); this->addChild(pad); auto block = Sprite::createWithSpriteFrameName("block.png"); block->setPosition(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2); this->addChild(block); auto brick_red = Sprite::createWithSpriteFrameName("brick_red.png"); brick_red->setPosition(origin.x + visibleSize.width / 2 - 72, origin.y + visibleSize.height / 2); this->addChild(brick_red); auto brick_blue = Sprite::createWithSpriteFrameName("brick_blue.png"); brick_blue->setPosition(origin.x + visibleSize.width / 2 + 72, origin.y + visibleSize.height / 2); this->addChild(brick_blue); return true; }
Notice how first we loaded the sprite sheet to memory and added it to the cache:
auto spriteCache = SpriteFrameCache::getInstance(); spriteCache->addSpriteFramesWithFile("spritesheet.plist");
Set the design resolution to 1024×768 to run on the Mac.
Compile and Run
It should compile and run without any errors and the result should be similar to the previous post.
You should notice that the GL calls are now only 1 as opposed to 5 from when we didn’t have the sprite sheet. This is because Cocos2d-x automatically will draw all the sprites that use the same sprite sheet, in one call!
This will increase the speed of your game dramatically!