稍微了解cocos2d-x的朋友應該都知道cocos2d-x裡面的動作都是通過CCAction的各種派生類來實現的。
比如我要將一個Sprite在1秒內從(0,0)移動到(400,400)
pSprite->setPosition(ccp(0,0));
CCMoveTo* moveTo = CCMoveTo::create(1.0f,,ccp(400,400));
pSprite->runAction(moveTo);
那麼,讓我們來看看Action在cocos2d-x到底是如何實現的。
首先必須要了解的幾個類
1.CCAction和CCActionInterval
CCAction是所有動作的基類,從代碼裡可以看出它本身並不執行動作
void CCAction::update(float time)
{
CC_UNUSED_PARAM(time);
CCLOG("[Action update]. override me");
}
他的作用只是提供一部分接口,如stop,update等等,其本身的實際作用並不是太大
CCActionInterval反而相對重要些,這個是大部分常用動作的基類,如常用的CCMoveTo,CCRotateBy等都是繼承自CCActionInterval,CCActionInterval還有很重要的一點就是他實現了step方法,這個方法是大部分其派生類更新動作的基礎(後文會有討論)
2.CCActionManager
從名字可以看出,這個類負責管理著所有的動作,
前面代碼裡的pSprite->runAction(moveTo);其實就是將moveTo這個Action和pSprite這個Node加入到了CCActionManager內部維護的m_pTargets的這個hash表中
看看代碼:
CCAction * CCNode::runAction(CCAction* action)
{
CCAssert( action != NULL, "Argument must be non-nil");
m_pActionManager->addAction(action, this, !m_bIsRunning);
return action;
}
看看,內部是否是調用CCActionManager的addAction
接著我們再看看addAction的實現
void CCActionManager::addAction(CCAction *pAction, CCNode *pTarget, bool paused)
{
CCAssert(pAction != NULL, "");
CCAssert(pTarget != NULL, "");
tHashElement *pElement = NULL;
// we should convert it to CCObject*, because we save it as CCObject*
CCObject *tmp = pTarget;
HASH_FIND_INT(m_pTargets, &tmp, pElement);
if (! pElement)
{
pElement = (tHashElement*)calloc(sizeof(*pElement), 1);
pElement->paused = paused;
pTarget->retain();
pElement->target = pTarget;
HASH_ADD_INT(m_pTargets, target, pElement);
}
actionAllocWithHashElement(pElement);
CCAssert(! ccArrayContainsObject(pElement->actions, pAction), "");
ccArrayAppendObject(pElement->actions, pAction);
pAction->startWithTarget(pTarget);
}