Cocos2d-x 動作之動作原理——動作的更新

在瞭解了CCActionCCFiniteTimeActionCCActionInterval的類結構後,下面我們以它們爲例分析Cocos2d-x的動作機制。

當我們對CCNode調用runAction(CCAction* action)方法時,動作管理類CCActionManager(它是一個單例對象)會將新的CCAction和對應的目標節點添加到其管理的動作表中。

CCActionManageraddAction方法中,我們將動作添加到動作隊列之後,就會對該CCAction調用成員函數startWithTarget(CCNode* pTarget)來綁定該動作的執行者。而在CCAction的子類中(如CCActionInterval),還初始化了一些參數:

void CCActionInterval::startWithTarget(CCNode *pTarget)
{
    CCFiniteTimeAction::startWithTarget(pTarget);
    m_elapsed = 0.0f;
    m_bFirstTick = true;
}

當這些準備工作都完成後,每一幀刷新屏幕時,系統都會在CCActionManager中遍歷其動作表中的每一個動作,並調用該動作的step(ccTimedt)方法。step方法主要負責計算m_elapsed的值,並調用update(float time)方法,相關代碼如下:

void CCActionInterval::step(float dt)
{
    if (m_bFirstTick)
    {
        m_bFirstTick = false;
        m_elapsed = 0;
    }
    else
    {
        m_elapsed += dt;
    }

    this->update(MAX (0,
        MIN(1, m_elapsed / MAX(m_fDuration, FLT_EPSILON))
        )
    );
}

傳入update方法的time參數表示逝去的時間與動作完成需要的時間的比值,是介於0和1之間的一個數,即動作完成的百分比。

CCActionInterval並沒有進一步實現update方法。下面我們繼續以繼承自CCActionIntervalCCRotateTo動作的update方法爲例,分析update函數是如何實現的,其實現代碼如下:

void CCRotateTo::update(float time)
{
    if (m_pTarget)
    {
        m_pTarget->setRotation(m_fStartAngle + m_fDiffAngle * time);
    }
}

看到這裏,我們已經能看出Cocos2d-x的動作機制的整個工作流程了。在CCRotateTo中,最終完成的操作是修改目標節點的Rotation屬性值,更新該目標節點的旋轉屬性值。

最後,在每一幀刷新結束後,在CCActionManager類的update方法中都會檢查動作隊列中每一個動作的isDone函數是否返回true。如果返回true,則動作已完成,將其從隊列中刪除。isDone函數的代碼如下:

bool CCActionInterval::isDone(void)
{
    return m_elapsed >= m_fDuration;
}

對於不同的動作類,雖然整體流程大致都是先調用step方法,然後按照各個動作的具體定義來更新目標節點的屬性,但是不同動作的具體實現會有所不同。例如,CCRepeatForever動作的isDone函數始終返回false,因爲它是永遠在執行的動作;又如CCActionInstant及其子類的step函數中,向update傳遞的參數值始終是1,因爲瞬時動作會在下一幀刷新後完成,不需要多次執行update

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章