Header Ads

Cocos2d-x: Sprite Sheet Batch Rendering without PList

Time for blogging again. Today, I shall discuss about yet another very commonly use technique for animations i.e. batch rendering of a sprite sheet. Following are some prerequisites before you proceed any further in this tutorial. 

1) Knowledge about Cocos2d-x.  
2) Knowledge about Sprite Sheets.

The first step in this discussion is to create a sprite sheet. How to do this? the answer is very simple, you can download available software that do the work for you e.g. Texture Packer which is used specifically for cocos2d-x. Texture Packer tool is not free of cost due to which it can't be used for commercial purposes as it adds a water marker in your sprite sheet.

Here are some list of alternative tools for sprite sheet generation.  

1) Predator (my favorite) available with free version and licensed version.
2) Sprite Sheet Packer by MIT an Open Source project by MIT.
3) Dark Function Editor available with free & licensed version.

Predator is my favorite because it is specific to cocos2d-x, it generates plist along with sprite sheet and the freeware version does not add water marker to your generated sprite sheet. Why choose tool that generate sprite sheet specific to cocos2d-x? the answer is simple, if someone is interested in doing the batch render of the sprite sheet by using plist then the construction of plist holds utmost importance to follow the plist generation pattern that cocos2d-x specifically follows, otherwise you will end up in receiving weird issues in your code without a hint of any execution error. Preference is given to Texture Packer because the plist that texture packer generates never fails to load, however, plist generated by other tool even with Predator might not be compatible to cocos2d-x.

So, the entire theme of my today's discussion is to use an alternative approach which does not require sprite sheet batch rendering from plist instead we shall do the batch rendering by just using our beloved sprite sheet.

You can download the complete source code for this tutorial or you can follow step by step discussion below.

Download Link

Let us begin now. Create new project in cocos2d-x project and name it "BatchAnimation". Edit the "HelloWorldScene.h" file which should looks like below:

#ifndef __HELLOWORLD_SCENE_H__  

 #define __HELLOWORLD_SCENE_H__  

 #include "cocos2d.h"  
 #include "Box2D/Box2D.h"  
 #include "SimpleAudioEngine.h"  

 class HelloWorld : public cocos2d::CCLayerColor  

   // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone  
   virtual bool init();   

   // there's no 'id' in cpp, so we recommand to return the exactly class pointer  
   static cocos2d::CCScene* scene();  

   // Touch(or onClick) event.  
   void ccTouchesBegan(cocos2d::CCSet* touch, cocos2d::CCEvent* touchEvent);  

   // a selector callback  
   virtual void menuCloseCallback(CCObject* pSender);  

   // implement the "static node()" method manually  

   cocos2d::CCSprite *tankerObj;  

 #endif // __HELLOWORLD_SCENE_H__ 

We have added "ccTouchesBegan" method and "tankerObj" variable declaration. add following lines to "init" method in "HelloWorldScene.cpp" file i.e.

   // Create "Tanker" sprite object.  
   this->tankerObj = CCSprite::spriteWithFile("tanker_default.png",   
                                                    CCRectMake(0, 0, 106, 62));      
   // Set position of "Tanker" button on screen.  
   this->tankerObj->setPosition(ccp(50, CCDirector::sharedDirector()->getWinSize().height/2));  
   CC_BREAK_IF(! this->tankerObj);  

   // Add "Tanker" sprite object to "Defense Scene" as a child layer.  
   this->addChild(this->tankerObj, 1);  

   // Enable Keyboard Input.  

What we have done here is that we have added tanker sprite, then set its position and enable touch input to receive inputs to ccTouchesBegan method. Now, add "ccTouchesBegan" method as shown below:

void HelloWorld::ccTouchesBegan(CCSet* touch, CCEvent* touchEvent)  
    // Loading Tanker Sprite sheet.  
    CCSpriteBatchNode *tankerSpriteSheet = CCSpriteBatchNode::batchNodeWithFile("tanker.png");    

    // Setting sprite with sprite batch node.  
    CCSprite *spriteObj = CCSprite::spriteWithBatchNode(tankerSpriteSheet, 
                          CCRectMake(0, 0, 106, 62));    

    // setting positions.  
    spriteObj->setPosition(ccp(this->tankerObj->getPositionX() + 16,   
   // Adding spriteObj to tankerSpriteSheet.  
   tankerSpriteSheet->addChild(spriteObj, 1);  

   //Create an Animation    
   CCAnimation *_animation = CCAnimation::animation();   

   // Adding delay between batch sprties.  

   // Sprite Sheet grid.  
   int row = 3; // +1 add null to animation.  
   int col = 2;  

   for (int i = 0; i < row; i++)   
      for (int j = 0; j < col; j++)  
         //CCRectMake to define the width of each frame by moving into the "tanker.png" sprite sheet.   
         CCSpriteFrame *frame = CCSpriteFrame::frameWithTexture(tankerSpriteSheet->getTexture(), CCRectMake(j * 106, i * 62, 106, 62));   

        //Add frames to make animation.  

   //Running the animation   
   CCAnimate *animate = CCAnimate::actionWithAnimation(_animation, false);    
   CCRepeat *repeatAction = CCRepeat::actionWithAction(animate, 1);    

   // Adding tanker sprite sheet.  
   this->addChild(tankerSpriteSheet, 1);       

What we have done in the above code is that we have done the batch rendering by moving one by one to each frame like moving in a matrix and create animation for it. Try to change delay time between these frames and you shall see your sprite frames i.e. change "_animation->setDelay(0.02)" to "_animation->setDelay(1)".

That's about it. Execute the project and you will see your sprite sheet animation.

Enjoy!! Coding.

1 comment:

  1. hi asma i am sami i am also a game developer . i am currently working on cocos2d , cocos2d-x and unity3d .