我们知道RotateTo和RotateBy都可以让精灵旋转,但他们还是有一些不同,区别就在于RotateTo是旋转到指定的角度;而RotateBy是从当前角度旋转指定的角度。举例来说,假定精灵当前的角度是x,分别给RotateTo和RotateBy指定一个角度y,那么RotateTo和RotateBy最终的效果分别如下:

RotateTo:x → y

RotateBy:x → (x + y)

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

1.jpg

2.jpg

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


RotateBy:

1、成员变量:

protected: 

1
2
3
4
bool _is3D;    // false: 使用带角度的3D旋转方式;true: 使用真正的3D旋转方式。 
           Vec3 _dstAngle;    // 目标角度。 
           Vec3 _startAngle;    // 起始角度。 
           Vec3 _diffAngle;   // 目标角度与起始角度之差。

private: 

1
CC_DISALLOW_COPY_AND_ASSIGN(RotateTo);    // 禁用拷贝构造函数和拷贝赋值操作符。

2、成员方法:

(1) static RotateBy* create(float duration, float deltaAngle); 

   static RotateBy* create(float duration, float deltaAngleZ_X, float deltaAngleZ_Y); 

   static RotateBy* create(float duration, const Vec3& deltaAngle3D);

使用create()创建一个RotateBy动作。第一个函数实现平面旋转,正的角度顺时针旋转,负的角度逆时针旋转;第二个函数实现带角度的3D旋转;第三个函数实现真正的3D旋转。

关于第二个和第三个函数,正负旋转角度对应的旋转效果不太好描述,各位试一下就明了了。但要注意一点,这两个函数指定的围绕哪个轴旋转指的是精灵本身的坐标轴,而非世界或者说是屏幕的坐标轴。

例如,将精灵初始角度设为100°,此时调用第二个create()让精灵沿X轴旋转,看看效果。

duration:动作持续时间。

deltaAngle:需要旋转的角度。

deltaAngleZ_X:X轴需要旋转的角度。

deltaAngleZ_Y:Y轴需要旋转的角度。

deltaAngle3D:需要旋转的3D角度。

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 用10秒的时间,顺时针平面旋转360°。
 
auto myRotateBy = RotateBy::create(10, 360);
 
// 用10秒的时间,X轴带角度的旋转360°。
 
// 当X轴和Y轴均设置为360时,和上面的例子效果相同。
 
auto myRotateBy = RotateBy::create(10, 360, 0);
 
// 用10秒的时间,围绕X轴3D旋转360°。
 
auto myRotateBy = RotateBy::create(10, Vec3(360, 0, 0));

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

1
2
3
4
5
6
7
auto mySprite = Sprite::create("mysprite.png");
 
mySprite->setPosition(Vec2(100, 100));
 
this->addChild(mySprite);
 
mySprite->runAction(RotateBy::create(10, 360));

mysprite.png放在工程的Resources目录下。

实现源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 平面旋转。
 
RotateBy* RotateBy::create(float duration, float deltaAngle) 
       { 
           RotateBy *rotateBy = new (std::nothrow) RotateBy();    // 创建RotateBy对象。 
           rotateBy->initWithDuration(duration, deltaAngle);    // 调用内部函数,见下。 
           rotateBy->autorelease();      // 让该对象在不使用时自动释放。
 
    return rotateBy; 
       }
 
bool RotateBy::initWithDuration(float duration, float deltaAngle) 
       { 
           if (ActionInterval::initWithDuration(duration))    // 动画的持续时间是由其父类负责的。 
           { 
               _deltaAngle.x = _deltaAngle.y = deltaAngle;    // X轴和Y轴旋转相同的角度。 
               return true; 
           }
 
    return false; 
       }
 
// 带角度的3D旋转。
 
RotateBy* RotateBy::create(float duration, float deltaAngleX, float deltaAngleY) 
       { 
           RotateBy *rotateBy = new (std::nothrow) RotateBy(); 
           rotateBy->initWithDuration(duration, deltaAngleX, deltaAngleY); 
           rotateBy->autorelease(); 
           return rotateBy; 
       }
 
 
bool RotateBy::initWithDuration(float duration, float deltaAngleX, float deltaAngleY) 
       { 
           if (ActionInterval::initWithDuration(duration)) 
           {
 
        /* X轴和Y轴可以旋转不同的角度。
 
         ! 这里有一个疑问,见下面的疑问部分。
 
         */ 
               _deltaAngle.x = deltaAngleX; 
               _deltaAngle.y = deltaAngleY; 
               return true; 
           } 
           return false; 
       }
 
// 真正的3D旋转。
 
RotateBy* RotateBy::create(float duration, const Vec3& deltaAngle3D) 
       { 
           RotateBy *rotateBy = new (std::nothrow) RotateBy(); 
           rotateBy->initWithDuration(duration, deltaAngle3D); 
           rotateBy->autorelease();
 
    return rotateBy; 
       }
 
bool RotateBy::initWithDuration(float duration, const Vec3& deltaAngle3D) 
       { 
           if (ActionInterval::initWithDuration(duration)) 
           { 
               _deltaAngle = deltaAngle3D;    // 3D旋转角度,其中包括X,Y和Z轴需要旋转的角度。 
               _is3D = true;    // 设置RotateBy::_is3D,之后update()中根据该变量判断3D还是2D旋转。 
               return true; 
           }
 
    return false; 
       }

关键点总结:

  • 通过向RotateBy::create()传递不同种类的旋转坐标,可以实现2D旋转,带角度的3D旋转以及真正的3D旋转。函数可以设置旋转动作的持续时间,旋转角度的正负控制旋转方向。

  • 让精灵围绕X,Y,Z轴旋转,并不是指的世界或是屏幕的坐标轴,而是精灵本身的坐标轴。

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

  • 个人觉得

    bool RotateBy::initWithDuration(float duration, float deltaAngle)和

    bool RotateBy::initWithDuration(float duration, float deltaAngleX, float deltaAngleY)

    可以合并,均使用第二个。2D旋转调用initWithDuration()时传递的deltaAngleX和deltaAngleY相同即可,就像下面RotateBy::clone()中做的那样。

疑问:

1
0