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

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