我们知道在Cocos2d-x 3.3中MoveTo和MoveBy可以使精灵移动,它们之间的区别在于MoveTo是移动到给定的坐标点;而MoveBy是从当前坐标点移动给定的坐标点这么多的距离。举例来说,假定精灵当前的坐标点是(x, y),分别给MoveTo和MoveBy指定一个坐标点(x1, y1),那么MoveTo和MoveBy最终的效果分别如下:

MoveTo:(x, y) → (x1, y1)

MoveBy:(x, y) → (x + x1, y + y1)

MoveTo和MoveBy各属一类,它们的继承关系如下:

1.jpg

接下来看每个类有什么接口,并结合实例说明。


MoveBy:

1、成员变量:

protected:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Vec2 _positionDelta;    // 偏移坐标,文章开头处说的(x1, y1)就是由它存储的。
 
    /* 起始坐标,文章开头处说的(x, y)就是由它存储的。
 
    * 不过这种说法只适用于为一个精灵设置了一个MoveBy动作,
 
    * 如果为同一个精灵设置了多个MoveBy动作,那么这个变量的值也是在不停的改变的,
 
    * 详见下面MoveBy::update()的源码分析。
 
    */
 
    Vec2 _startPosition;   
 
    /* 移动过程中的坐标,精灵的移动实际上是在不停的setPosition(),连在一起行程移动效果。
 
    * 这个变量就用于存储上一次setPosition()时的坐标。
 
    * 详见下面MoveBy::update()的源码分析。
 
    */
 
    Vec2 _previousPosition;

private:

1
2
3
4
5
6
7
8
9
/* 禁用拷贝构造函数和拷贝赋值操作符。
 
     * 这里用到了C++11标准的新特性“delete函数(= delete)”
 
 
     */
 
    CC_DISALLOW_COPY_AND_ASSIGN(MoveBy);

2、成员方法:

(1) static MoveBy* create(float duration, const Vec2& deltaPosition);

使用该函数创建一个MoveBy动作。

duration:动作持续时间。

deltaPosition:偏移坐标。这里会给出一对儿(x, y)坐标值,x轴是左负右正,y轴是下负上正。

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 用1秒的时间,向右移动100个像素的MoveBy。
 
    auto myMoveBy = MoveBy::create(1.0f, Vec2(100, 0));   
 
    // 用3秒的时间,向上移动500个像素的MoveBy
 
          auto myMoveBy = MoveBy::create(3.0f, Vec2(0, 500));   
 
          // 用1秒的时间,向右上移动的MoveBy,具体效果就是x和y轴移动效果的组合。
 
          auto myMoveBy = MoveBy::create(1.0f, Vec2(100, 100));   
 
// 用1秒的时间,向左移动100个像素的MoveBy。
 
 
 
auto myMoveBy = MoveBy::create(1.0f, Vec2(-100, 0));

auto是让编译器自动识别变量类型;create是MoveBy的静态成员方法,所以可以通过类名直接调用,无需类对象;Vec2是一个管理二维坐标的类。

当然,MoveBy只是创建了这么一个动作,要向让精灵真正的动起来,可参考如下代码:

1
2
3
4
5
6
7
8
9
auto mySprite = Sprite::create("mysprite.png");
 
mySprite->setPosition(Vec2(100, 100));
 
this->addChild(mySprite);
 
mySprite->runAction(MoveBy::create(1.0f, Vec2(100, 100)));
 
mysprite.png放在工程的Resources目录下。

实现源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
MoveBy* MoveBy::create(float duration, const Vec2& deltaPosition) 
       { 
           MoveBy *ret = new (std::nothrow) MoveBy();    // 创建MoveBy对象。 
           ret->initWithDuration(duration, deltaPosition);   // 调用内部函数,见下。 
           ret->autorelease();     // 让该对象在不使用时自动释放。
 
    return ret; 
       }
 
bool MoveBy::initWithDuration(float duration, const Vec2& deltaPosition) 
       { 
           if (ActionInterval::initWithDuration(duration))    // 动画的持续时间是由其父类负责的。 
           { 
               _positionDelta = deltaPosition;    // MoveBy的成员变量存储了偏移坐标。 
               return true; 
           }
 
    return false; 
       }

关键点总结:

  • MoveBy::create()可以创建一个MoveBy动作,创建过程中可以指定动作持续时间以及动作具体要向哪个方向(x轴是左负右正,y轴是下负上正)移动多少。

  • MoveBy并没有具体实现运动的过程,它只相当于一个配置。并且配置还进行了细化,其父类负责动画的持续时间,而MoveBy只负责偏移的坐标。

(2) virtual MoveBy* clone() const override;

使用该函数克隆一个MoveBy动作。

实例:

1
2
3
auto myMoveBy = MoveBy::create(1, Vec2(100, 100));
 
auto myMoveByClone = myMoveBy->clone();

实现源码:

1
2
3
4
5
6
7
8
MoveBy* MoveBy::clone() const 
       { 
           // no copy constructor 
           auto a = new (std::nothrow) MoveBy(); 
           a->initWithDuration(_duration, _positionDelta); 
           a->autorelease(); 
           return a; 
       }

实现又重新把create()中的内容写了一遍,为何不直接返回create()?

1
return MoveBy::create(_duration, _positionDelta);

关键点总结:

  • MoveBy::clone()就是克隆一个给定的动作,函数名字起得很形象。

  • 源码实现觉得应该更简洁写,调用MoveBy::create()即可。

(3) virtual MoveBy* reverse(void) const  override;

使用该函数创建一个与原先MoveBy相反的MoveBy动作。

实例:

1
2
3
auto myMoveBy = MoveBy::create(1, Vec2(100, 100));
 
0