cocos2d-x动作原理

首先CCAction是所有动作的基类,如下图继承关系:

那么来看看CCAction的定义:

class CC_DLL CCAction : public CCObject
{
public:
    CCAction(void);
    virtual ~CCAction(void);

    const char* description();
    virtual CCObject* copyWithZone(CCZone *pZone);
    //! return true if the action has finished
    virtual bool isDone(void);
    virtual void startWithTarget(CCNode *pTarget);

    virtual void stop(void);
    //! called every frame with it‘s delta time. DON‘T override unless you know what you are doing.
    virtual void step(float dt);
    virtual void update(float time);
    inline CCNode* getTarget(void) { return m_pTarget; }
    inline void setTarget(CCNode *pTarget) { m_pTarget = pTarget; }
    inline CCNode* getOriginalTarget(void) { return m_pOriginalTarget; }
    inline void setOriginalTarget(CCNode *pOriginalTarget) { m_pOriginalTarget = pOriginalTarget; }
    inline int getTag(void) { return m_nTag; }
    inline void setTag(int nTag) { m_nTag = nTag; }

public:
    static CCAction* create();
protected:
    CCNode    *m_pOriginalTarget;
    CCNode    *m_pTarget;
    int     m_nTag;
};

在类定义最后有三个成员变量,而继承自CCAction的CCFiniteTimeAction主要新增加了一个用于保存该动作总完成时间的成员变量float m_fDuration;

对于其两个子类CCActionInstant和CCActionInterval,前者没有新增任何函数和变量,而后者增加了两个成员变量:float m_elapsed(记录从动作开始起逝去的时间);和bool   m_bFirstTick(一个控制变量);

那么动作是如何执行的呢?

当一个节点调用runAction方法时,动作管理类CCActionManager(单例类)会将新的动作和节点添加到其管理的动作表中。

CCAction * CCNode::runAction(CCAction* action)
{
    CCAssert( action != NULL, "Argument must be non-nil");
    m_pActionManager->addAction(action, this, !m_bRunning);
    return action;
}

在addAction中,将动作添加到动作队列后,就会对该动作调用其成员函数startWithTarget(CCNode* pTarget)来绑定该动作的执行节点,和初始化动作类的成员变量。

这些工作都完成后,每一帧刷新屏幕时,系统就会在CCActionManager中遍历动作表中的每一个动作,并调用动作的step(float)方法。而step方法主要负责计算m_elapsed的值,并调用update(float)方法。

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

    this->update(MAX (0,                // needed for rewind. elapsed could be negative
                      MIN(1, m_elapsed / MAX(m_fDuration, FLT_EPSILON)   // division by 0
                          )
                      )
                 );
}

传入update方法的float型参数表示逝去的时间与动作完成需要的时间的比值,介于0-1之间,即动作完成的百分比。然后在update方法中,通过完成比例对节点的属性进行操作来达到动作的效果。
例如:对MoveBy调用update时,通过传入的比例调用setPosition直接修改节点的属性。

最后在每一帧结束后,CCActionManager的update会检查动作队列中每个动作的isDone函数是否返回true,如果返回true,则动作结束,将其从队列中删除。

——————————————————————————————————————————————————————————————————————————

从上面知道:动作都是由CCActionManager来管理。那我们再来看看CCActionManager的工作原理。

在CCDirector初始化时,执行了如下代码:

    // scheduler
    m_pScheduler = new CCScheduler();
    // action manager
    m_pActionManager = new CCActionManager();
    m_pScheduler->scheduleUpdateForTarget(m_pActionManager, kCCPrioritySystem, false);

可见动作管理类在创建时就注册了Update定时器,那么CCScheduler在游戏的每一帧mainLoop更新中都会触发CCActionManager注册的update(float )方法。调度器原理请参照此链接:http://www.cnblogs.com/songcf/p/3162414.html

// main loop
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)
                {
                    // The currentAction told the node to remove it. To prevent the action from
                    // accidentally deallocating itself before finishing its step, we retained
                    // it. Now that step is done, it‘s safe to release it.
                    m_pCurrentTarget->currentAction->release();
                } else
                if (m_pCurrentTarget->currentAction->isDone())
                {
                    m_pCurrentTarget->currentAction->stop();

                    CCAction *pAction = m_pCurrentTarget->currentAction;
                    // Make currentAction nil to prevent removeAction from salvaging it.
                    m_pCurrentTarget->currentAction = NULL;
                    removeAction(pAction);
                }

                m_pCurrentTarget->currentAction = NULL;
            }
        }

        // elt, at this moment, is still valid
        // so it is safe to ask this here (issue #490)
        elt = (tHashElement*)(elt->hh.next);

        // only delete currentTarget if no actions were scheduled during the cycle (issue #481)
        if (m_bCurrentTargetSalvaged && m_pCurrentTarget->actions->num == 0)
        {
            deleteHashElement(m_pCurrentTarget);
        }
    }

    // issue #635
    m_pCurrentTarget = NULL;
}
时间: 09-06

cocos2d-x动作原理的相关文章

TRIZ系列-创新原理-19-周期性动作原理

周期性动作原理表述如下:1)用周期性的动作(脉冲)代替连续的动作:2)如果动作已经是周期性的,则改变其频率:3)利用脉动之间的停顿来执行额外的动作: 尝试改变物体的运动规律--频率(将连续的动作试作频率为0),通过增大频率或降低频率来看看是否可以获得新的功能或者是强化某种功能,也可以尝试利用周期性动作的间歇来执行其它额外的动作,以充分利用系统的资源:案例如下:A)警笛和警灯:B) 冲击钻,蛤蟆夯:C)计算机指令;D)Windows操作系统的基本指令执行周期:E)汽车的雨刷器:.... 如果有些周

Cocos2D中Action的进阶使用技巧(一)

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 假设认为写的不好请多提意见,假设认为不错请多多支持点赞.谢谢! hopy ;) 大家对Cocos2d中动作的使用大概都非常清楚了,事实上本身action的概念也不复杂. 可是在某些情况下,一般的动作不能满足我们需求的时候,我们就必须使用更高级的Action方法来解决这个问题. 比方,串行化(不是序列化哦,这是两个全然不同的概念)不同Action的执行-有些童鞋可能会说非常easy,直接用CCActionSequence不就结了,可是等等我

cocos2D(三)---- 第一cocos2d的程序代码分析

在第一讲中已经新建了第一个cocos2d程序,执行效果例如以下: 在这讲中我们来分析下里面的代码,了解cocos2d的工作原理,看看屏幕上的这个"Hello World"是怎样显示出来的. 这是HelloWorld项目的代码结构: 以下,我们開始分析项目中的这些源文件: 从程序的入口点開始 这么多源文件在这里,到底先看哪个呢?有些人可能会先挑内容少的来看,认为这样就能够轻松解决掉一个源文件了.事实上这是不正确的,这样看起来更加是一头雾水,根本搞不清楚每一个源文件之间的联系.正确的做法应

18、Cocos2dx 3.0游戏开发找小三之cocos2d-x,请问你是怎么调度的咩

重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/30478251 Cocos2d 的一大特色就是提供了事件驱动的游戏框架, 引擎会在合适的时候调用事件处理函数,我们只需要在函数中添加对各种游戏事件的处理, 就可以完成一个完整的游戏了. 例如,为了实现游戏的动态变化,Cocos2d 提供了两种定时器事件: 为了响应用户输入,Cocos2d 提供了触摸事件和传感器事件: 此外,Cocos2d 还提供了一系列

自动化双臂机械手在自动化生产线领域中的发展

自动化双臂机械手在自动化生产线领域中的发展如何 中国的双臂机械手产业正在迎来高速发展期,从国内冲压机器人的应用来看,汽车.电子工业仍是主要的应用领域.机械手应用规模正在迅速扩大,中国冲压产业化正处于关键的转折点,在国家政策的推动下,国内冲压自动化将跨上一个新的台阶,进入快速发展阶段. 近年来自动冲压机械手是现在企业追求的方向,为了节约人力.降低产品单位成本,越来越多的企业通过改造现有生产方式为自动化生产,或者直接导入自动化生产.冲压自动化生产同样是企业急需导入的策略.本公司自主研发.制造的自动冲

ZT:关于自动档驾驶的文章

出处:https://zhidao.baidu.com/question/573044786.html 自动变速器的挡位 一般来说,自动变速器的挡位分为P.R.N.D.2.1或L等.P(Parking):用作停车之用,它是利用机械装置去锁紧汽车的 转动部分,使汽车不能移动.当汽车需要在一固定位置上停留一段较长时间,或在停靠之后离开车辆前,应该拉好手制动及将拨杆推进“P”的位置上.要注意的是:车辆一定要在完全停止时才可使用P挡,要不然自动变速器的机械部分会受到损坏.另外,自动变速轿车上装置空挡启动

JSP基本语法总结【1】(jsp工作原理,脚本元素,指令元素,动作元素)

时隔半年,回头对jsp复习整理一下,温故而知新. jsp工作原理: jsp服务器管理jsp页面分两个阶段:转换阶段(translation phase)和执行阶段(execution phase). 客户发送请求时,服务器检验jso语法是否正确,然后转换成servlet源文件,然后调用javac工具类便宜servlet源文件生成class文件,此阶段为转换阶段. 接下来,servlet容器加载转换后的servlet类,实例化一个对象来处理客户端的请求.请求处理后,响应对象被jsp服务器接收,服务

coco2dx-动作(Action)原理二 动作分类详解

http://blog.csdn.net/zh13544539220/article/details/45223863 上篇文章是关于Action的工作流程和ActionManager的执行原理,本文说说Action的分类和具体的设计 动作类型的分类: 一.限时动作:FiniteTimeAction 包括:即时动作(CCActionInstance)和持续时间动作(CCActionInterval) 1.即时动作:即时动作有几个其实是只改变的node的position,visible等属性而已,

cocos2d 动作回调函数

// on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !CCLayer::init() ) { return false; } CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); C