學習了CCAction
在每一幀中如何被更新之後,我們不妨回頭看看動作管理類CCActionManager
的工作原理。在對CCDirector
進行初始化時,也會對CCActionManager
進行初始化。下面的代碼是CCDirector::init()
方法中的一部分:
//動作管理器
m_pActionManager = new CCActionManager();
m_pScheduler->scheduleUpdateForTarget(m_pActionManager, kCCPrioritySystem, false);
可以看到,在CCActionManager
被初始化後,馬上就調用了定時調度器CCScheduler
的scheduleUpdateForTarget
方法。在scheduleUpdateForTarget
函數中,我們爲CCActionManager
註冊了一個定期更新的服務,這意味着動作的調度與定時器的調度都統一受到CCScheduler
的控制。具體地說,我們可以方便地同時暫停或恢復定時器與動作的運行,而不必考慮它們不同步的問題。
CCScheduler
在每一幀更新時,都會觸發CCActionManager
註冊的update
方法。從下面給出的CCActionManager::update
方法的代碼可以看到,CCActionManager
在這時對每一個動作都進行了更新。與調度器CCScheduler
類似的一點是,爲了防止動作調度過程中所遍歷的表被修改,Cocos2d-x對動作的刪除進行了仔細地處理,保證任何情況下都可以安全地刪除動作:
void CCActionManager::update(float dt)
{
//枚舉動作表中的每一個目標節點
for (tHashElement *elt = m_pTargets; elt != NULL; )
{
m_pCurrentTarget = elt;
m_bCurrentTargetSalvaged = false;
if (! m_pCurrentTarget->paused)
{
//枚舉目標節點對應的每一個動作
//actions數組可能會在循環中被修改,因此需要謹慎處理
for (m_pCurrentTarget->actionIndex = 0;
m_pCurrentTarget->actionIndex < m_pCurrentTarget->actions->num;
m_pCurrentTarget->actionIndex++)
{
m_pCurrentTarget->currentAction =
(CCAction*)m_pCurrentTarget->actions
->arr[m_pCurrentTarget->actionIndex];
if (m_pCurrentTarget->currentAction == NULL)
{
continue;
}
m_pCurrentTarget->currentActionSalvaged = false;
m_pCurrentTarget->currentAction->step(dt); //觸發動作更新
if (m_pCurrentTarget->currentActionSalvaged)
{
m_pCurrentTarget->currentAction->release();
}
else if (m_pCurrentTarget->currentAction->isDone())
{
m_pCurrentTarget->currentAction->stop();
CCAction *pAction = m_pCurrentTarget->currentAction;
m_pCurrentTarget->currentAction = NULL;
removeAction(pAction);
}
m_pCurrentTarget->currentAction = NULL;
}
}
elt = (tHashElement*)(elt->hh.next);
if (m_bCurrentTargetSalvaged && m_pCurrentTarget->actions->num == 0)
{
deleteHashElement(m_pCurrentTarget);
}
}
m_pCurrentTarget = NULL;
}