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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章