cocos2d-x v3.3 ActionInterval

来源:互联网 发布:斑马旅游 知乎 编辑:程序博客网 时间:2024/05/01 02:00

ActionInterval主要负责记录持续动作已执行了多长时间。它对应于ActionInstant(瞬时动作),ActionInterval的继承关系如下:

image

其下还继承了很多的持续动作类,这里只截取了一部分。

1、成员变量:

protected:
           float _elapsed;    // 动作已执行了多长时间。

    /* 这个是为了防jerk而设定的,不过jerk是什么我还不是特别清楚,图像抖动吗?

     * 下面说到step()成员方法的源码实现时还会说到。

     */
           bool _firstTick;

2、成员方法:

(1) inline float getElapsed(void) { return _elapsed; } 

该方法用于获得从动作开始执行后过去了多少秒。

(2) void setAmplitudeRate(float amp);
             float getAmplitudeRate(void);

这两个方法用于设置格子动画的振幅,不过好像还没有实现。

(3) virtual bool isDone(void) const override;

该方法用于判断动作是否执行完毕。

实现源码:

bool ActionInterval::isDone() const
       {
           return _elapsed >= _duration;
       }

很简单,当发现动作的执行时间大于等于指定的时间,则说明动作已经执行完成。

(4) bool initWithDuration(float d);

该函数用于初始化动作的持续时间(_duration)以及动作已执行的时间(_elapsed)。

d:动作持续时间。

实例:

该函数不需要应用程序中主动调用,一般由ActionInterval的派生类调用create()时内部调用,例如MoveBy::create()。

实现源码:

bool ActionInterval::initWithDuration(float d)
       {
           _duration = d;    // 初始化动作的持续时间,_duration属于ActionInterval的父类。

    // prevent division by 0
           // This comparison could be in step:, but it might decrease the performance
           // by 3% in heavy based action games.
           if (_duration == 0)
           {

        /* 这里是为了防止_duration作为除数时其被设置为0。

         * FLT_EPSILON是一个计算机所能识别的最小正数。

         * _duration我看到的只在ActionInterval::step()中作为除数,

         * 但那里有个MAX(_duration, FLT_EPSILON)作为保障机制,

         * 所以我理解这里不用特别将_duration = FLT_EPSILON亦可。

         * 对上面注释的理解,是否是说由于影响游戏的性能,

         * step()中可以不用MAX()对_duration的值进行保障,而放在这里?

         */
               _duration = FLT_EPSILON;
           }

    _elapsed = 0;    // 初始化动作已持续时间。
           _firstTick = true;    // 为了防止jerk而设置的变量。

    return true;
       }

关键点总结:

♂ 该函数要结合ActionInterval派生类的create()来看,比如MoveBy::create()。

♂ 对于_duration作为除数需要非零的保障,在ActionInterval::step()中使用MAX()或者在ActionInterval::initWithDuration()中直接赋值均可。考虑到在游戏运行过程中step()会被经常调用,在step()中总去MAX()会影响游戏的性能,所以可在initWithDuration()将_duration赋值好,step()中直接使用即可。

(5) virtual void startWithTarget(Node *target) override;

该函数用于将动作与精灵进行绑定。

target:待执行动作的精灵。

实例:

该函数不需要应用程序中主动调用,一般由精灵调用runAction()关联动作时内部调用,例如mySprite->runAction(myRotateBy);。

实现源码:

void ActionInterval::startWithTarget(Node *target)
       {
           FiniteTimeAction::startWithTarget(target);    // 其父类将精灵与动作进行绑定。
           _elapsed = 0.0f;    // 初始化动作已持续时间。
           _firstTick = true;    // 防止jerk而设置的变量。
       }

关键点总结:

♂ 该函数要结合精灵的runAction()来看,比如mySprite->runAction(myRotateBy)。

(6) virtual void step(float dt) override;

该函数根据流逝的时间计算出动作的进度(百分比形式),然后将这个进度传递给动作的update()进行更新。

dt:从上一帧到这一帧所流逝的时间。

实例:

无。

实现源码:

void ActionInterval::step(float dt)
       {
           if (_firstTick)    // 防止jerk,step()第一次被调用时会进入这里。
           {
               _firstTick = false;
               _elapsed = 0;
           }
           else
           {
               _elapsed += dt;    // _elapsed存储动作已执行的时间。
           }

    /* 首先使用MAX()保障_duration非0;之后用动作已执行时间除以动作总的持续时间

     * 得到动作已完成的进度(理解为百分比)。当动作的进度为1的时候相当于100%,

     * 这里使用MIN()保障动作的执行进度不会超过100%。

     * 最后一个MAX()不是很理解,难道进度会有负值的情况?

     */

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

关键点总结:

♂ 该函数由引擎内部调用,当动作执行起来后不停的被调用。函数中首先累计动作已执行时间,之后根据这个时间以及动作的总持续时间,算出当前动作的执行进度,最后将进度交给update()更新精灵的状态。

♂ 函数中最后update()参数中的最后一个MAX()不太理解,难道进度会有负数的情况?

(7) virtual ActionInterval* reverse() const override

      virtual ActionInterval *clone() const override

这两个函数在ActionInterval中不能被调用,需要其派生来实现。

 

 

0 0
原创粉丝点击