学习了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;
}