I'm trying to animate a sprite while it's moving. As per the examples: I create an array of frames, create a CCAnimation with them (and a delay), and then create the CCAnimate from that. When I do the following (in the constructor where animate is made):
this->addChild(sprite);
sprite->runAction(animate);
It works fine.
When I try to run a certain animation while it moves in a different method (animate is a global pointer to the animation) I get the following error:
In function retain -- ..\..\cocoa\CCObject.cpp:92 m_uReference > 0 -- assertion failed
Or more specifically: CCAssert(m_uReference > 0, "reference count should greater than 0");
I looked to this post (http://www.cocos2d-x.org/boards/6/topics/7553) and added a CC_SAFE_RETAIN(animate) and CC_SAFE_RETAIN(display) in the init method.
Now I see the first image of the animation but it crashes right after saying:
In function addAction -- ..\..\actions\CCActionManager.cpp:191 ! ccArrayContainsObject(pElement->actions, pAction) -- assertion failed
I figured out the problem.
Essentially follow the example here: http://www.cocos2d-x.org/boards/6/topics/7553)
The second part was that the action was being run twice, which is why that error was thrown.
It was a logic error on my part (I'm using a custom CCNode child class)
I overrode the 'numberOfRunningActions' to take into account both the custom class and the sprite
class GameObject { public: GameObject(); virtual ~GameObject(); bool initWithParent(cocos2d::CCNode* pParent); void changeAction(int index); cocos2d::CCSprite* m_pSprite; cocos2d::CCMutableArray<cocos2d::CCAction*>* m_pActions; cocos2d::CCNode* m_pParent; };
GameObject::GameObject() : m_pSprite(NULL) , m_pActions(NULL) , m_pParent(NULL) { } GameObject::~GameObject() { CC_SAFE_RELEASE(m_pSprite); CC_SAFE_RELEASE(m_pActions); } bool GameObject::initWithParent(CCNode* pParent) { bool bRet = false; do { CCSize winSize = CCDirector::sharedDirector()->getWinSize(); CCAssert(pParent != NULL, ""); m_pParent = pParent; m_pSprite = CCSprite::spriteWithFile("grossini.png"); m_pSprite->setPosition(ccp(winSize.width/2, winSize.height/2)); m_pParent->addChild(m_pSprite); CC_SAFE_RETAIN(m_pSprite); CCMoveBy* move = CCMoveBy::actionWithDuration(0.5f, ccp(100, 0)); CCActionInterval* moveReverse = move->reverse(); CCRepeatForever* moveForever = CCRepeatForever::actionWithAction((CCActionInterval*)CCSequence::actions(move, moveReverse, NULL)); CCFadeIn* fadeIn = CCFadeIn::actionWithDuration(0.5f); CCActionInterval* fadeOut = fadeIn->reverse(); CCRepeatForever* fadeForever = CCRepeatForever::actionWithAction((CCActionInterval*)CCSequence::actions(fadeIn, fadeOut, NULL)); CCRotateBy* rotate = CCRotateBy::actionWithDuration(0.5f, 90.0f); CCActionInterval* rotateReverse = rotate->reverse(); CCRepeatForever* rotateForever = CCRepeatForever::actionWithAction((CCActionInterval*)CCSequence::actions(rotate, rotateReverse, NULL)); m_pActions = CCMutableArray<CCAction*>::arrayWithObjects(moveForever, fadeForever, rotateForever, NULL); CC_SAFE_RETAIN(m_pActions); changeAction(0); bRet = true; } while (false); return bRet; } void GameObject::changeAction(int index) { int count = m_pActions->count(); CCAssert(index >= 0 && index < count, ""); if (m_pSprite->numberOfRunningActions() > 0) { m_pSprite->stopAllActions(); } m_pSprite->setOpacity(255); m_pSprite->runAction(m_pActions->getObjectAtIndex(index)); }
void HelloWorld::step(cocos2d::ccTime dt) { static int animationIndex = 0; m_pGameObj->changeAction(animationIndex); animationIndex = ++animationIndex > 2 ? 0 : animationIndex; }