09-动作流程-1-MoveBy分析

来源:互联网 发布:linux下挂载iscsi存储 编辑:程序博客网 时间:2024/06/07 05:26

代码例子

m_pActionSprite = Sprite::create("CloseSelected.png");

m_pActionSprite->setPosition(100.0f,100.0f);

addChild(m_pActionSprite);

m_pActionSprite->runAction(MoveBy::create(10.0f, Vec2(500.0f,500.0f)));

效果

Image

分析

分为两个过程

1.构建Action

2.在渲染循环中(Director::mianLoop -> Director::drawScene)中执行每一帧

构建Action过程

Image(1)

runAction主要做了两件事情

1.在Direction Scheduler 中的 ActionManager中addAction

ActionManager维护了一个数组(c语言),每一个Element的结构如下

Image(2)

也就是说一个Node对象,会维持一个Action的Array

2.另外create出的Action进行了保存。在ActionManager中首先找到target,然后找到target下的Action,然后调用Action去执行具体的动画。

Action本身是一个完整的动作描述,包括了target对象,在update中具体实现帧动画

对于MoveBy初始化有两个方面比较重要:

1.在create的时候

Image(3)

记录了duration和增量值

2.在调用target的runAction时候,ActionManager中add了Action后,会调用startWithTarget

Image(4)

Image(5)

Image(6)

关键是Action保存了要执行的Node对象,另外初始化了

1.position-通过target获取

2.duration 0

3.elapsed 0

4.firstTick true

Action渲染过程

Image(7)

1.在Director::drawScen中

Image(8)

_deltaTime  如何来的?

在drawScene中首先调用了

calculateDeltaTime();

Image(9)

最后*_lastUpdate = now;

排除意外情况后,真正的计算时间是:

_deltaTime = (now.tv_sec - _lastUpdate->tv_sec) + (now.tv_usec - _lastUpdate->tv_usec) / 1000000.0f;

tv_sec 是秒单位

tv_used是微秒单位

1秒=100万微秒

tv_sec: 1s

tv_used: 500 000 us

两者相加是 1.5秒

2.在scheduler::update中,遍历了添加到scheduler中的element,并调用其对应的回调

Image(10)

其中ActionManager回调的添加是在Director::init中发生的

Image(11)

我们看看scheduleUpdate

Image(12)

target此处代表了ActionManager对象,priority,此处要注意,ActionManager设定的是最小的值(也就是在schedule::update中首先执行的是ActionManager的update回调方法)

3.在ActionManager::update中遍历每一个Element,然后遍历该target的每一个Action,然后调用了Action::step

Image(13)

针对MoveBy来说,调用的是ActionInterval::step

Image(14)

4.最终调用了MoveBy的update

Image(15)

上图代码的原理主要参考了:http://www.cocoachina.com/bbs/3g/read.php?tid=288130

当只有一个动作作用于精灵时,currentPos与_previousPosition一直都是相同的(因为没有其他动作移动该精灵),所以diff总是为0,继而精灵的起始坐标(_startPosition)保持不变,精灵只是_positionDelta * t计算出当前精灵应该移动的偏移量。针对以上的描述举一个简单的例子,比如一个MoveBy动作是1s向右移动100个像素,现在调用了update(),时间过去了0.1秒,那么此时应该将精灵放在距离起始坐标向右10个像素的位置(_startPosition + (100, 0) * 0.1);之后过了段时间又掉用了update(),此时过去了0.7秒,那么此时应该将精灵放在距离起始坐标向右70个像素的位置。

当有多个动作作用于精灵时情况稍微复杂了些。比如有两个MoveBy动作都是1s向右移动100个像素,精灵的起始位置是(0, 0),0.1s的时候MoveBy1的update()被调用,将精灵向右移动了10个像素,此时精灵位于(10, 0);0.11s时MoveBy2的update()被调用,发现精灵的当前位置与自己之前记录的起始坐标(_previousPosition,startWithTarget()中初始化了)不一样了,故而_startPosition被更新为(10, 0),之后将精灵向右移动11个像素,此时精灵位于(21, 0);之后比如0.15s时MoveBy1的update()被调用,也发现精灵的当前位置与自己之前记录的起始坐标不一样了,故而_startPosition被更新为(11, 0),之后将精灵向右移动15个像素,此时精灵位于(26, 0);之后就是以此类推,当1s过后精灵位于(200, 0)。

当不开启CC_ENABLE_STACKABLE_ACTIONS时,update()中只有一个setPosition(),所以谁最后setPosition()就体现谁的效果,即最后一个MoveBy有效果。

0 0
原创粉丝点击