I'm currently starting with cocos2d-x to build games for blackberry/android/iOS.
I have the png and plist for the animations of a character created with texturepacker. I load them with CCSpriteBatchNode
and CCSpriteFrameCache
then I use a function created by me that loads all frames into an array of frames, then create a CCAnimation
object and store the CCAnimate
object created with the animation (code is more clear) the thing is that I have a function that detect touches and it is supposed to cycle through all animations, but it always crashes.
here is some code (this goes in the init()
):
_batchNode = CCSpriteBatchNode::create("Character/girl.png");
_cache = CCSpriteFrameCache::sharedSpriteFrameCache();
_cache->addSpriteFramesWithFile("Personajes/girl.plist");
_character = CCSprite::createWithSpriteFrameName("girlneutral1.png");
_character->setPosition(ccp(winSize.width * 0.1, winSize.height * 0.5));
_batchNode->addChild(_character, 1);
this->addChild(_batchNode);
createAnimation(0, "girlpush", 8, 0.15f);
createAnimation(1, "girlneutral", 4, 0.3f);
createAnimation(2, "girlcrash", 12, 0.3f);
createAnimation(3, "girljump", 12, 0.2f);
createAnimation(4, "girltrick", 12, 0.3f);
_character->runAction(CCRepeatForever::create( _charanimation[3]));
this->setTouchEnabled(true);
the function that loads the animations (_charanimation[] is just an array of CCAnimate):
void HelloWorld::createAnimation(int a, CCString animation_name, int frames, float delay)
{
CCArray* animframes = CCArray::createWithCapacity(frames);
char str[100] = {0};
for(int i = 1; i <= frames; i++)
{
sprintf(str, "%s%d.png", animation_name.getCString(), i);
CCSpriteFrame* frame = _cache->spriteFrameByName( str );
animframes->addObject(frame);
}
_charanimation[a] = CCAnimate::create(CCAnimation::createWithSpriteFrames(animframes, delay));
//_charanimation[a]->getAnimation()->setLoops(-1);
}
and I get the animation to work (the one I set with runAction()
) but if I try to change the animation, for example, when I touch the screen:
void HelloWorld::ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event)
{
action++;
action%=5;
_character->stopAllActions();
_character->runAction( CCRepeatForever::create(_charanimation[action]));
char str[100];
sprintf(str, "Animation: %d", action);
pLabel->setString(str);
}
it crashes... I don't know if I am doing it wrong, if anyone could help, I will appreciate.
If I change the animation in runAction()
it shows the animation correctly, but I can't change ingame with touches.
by the way, this is the error I get in console:
cocos2d-x debug info Assert failed: reference count should greater than 0
In function retain -- ..\..\cocoa\CCObject.cpp:92 m_uReference > 0 -- assertion failed
Its because the CCAnimate
object you have created is autorelease object and you are not retaining the object. Autorelease objects will be deleted automatically if they are not retained, either explicitly or by some other object.
While adding to array You can do
CCAnimate *animate = CCAnimate::create(CCAnimation::createWithSpriteFrames(animframes, delay));
animate->retain();
_charanimation[a] = animate;
do not forget to release all the objects in the array when everything is over
_charanimation[index]->release();
Note:
Instead of using the simple C or C++ array you can use Cocos2d's CCArray
which retains the object once it is added to the array.
For Example: (The memory handling is similar to Objective-C)
_charanimation = new CCArray();
//To add object to array
_charanimation->addObject(object); //This will retain the object
//To get an object
_charanimation->objectAtIndex(index);
_charanimation->lastObject();
_charanimation->randomObject();
//To remove object
_charanimation->removeObjectAtIndex(index); //This will release object
_charanimation->removeObject(object); //This will release object
//Dont forget delete array later
delete (_charanimation);