Cocos2d-x 动作之动作原理——CCActionManager的工作原理

学习了CCAction在每一帧中如何被更新之后,我们不妨回头看看动作管理类CCActionManager的工作原理。在对CCDirector进行初始化时,也会对CCActionManager进行初始化。下面的代码是CCDirector::init()方法中的一部分:

//动作管理器
m_pActionManager = new CCActionManager();
m_pScheduler->scheduleUpdateForTarget(m_pActionManager, kCCPrioritySystem, false);

可以看到,在CCActionManager被初始化后,马上就调用了定时调度器CCSchedulerscheduleUpdateForTarget方法。在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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章