我们知道RotateTo和RotateBy都可以让精灵旋转,但他们还是有一些不同,区别就在于RotateTo是旋转到指定的角度;而RotateBy是从当前角度旋转指定的角度。举例来说,假定精灵当前的角度是x,分别给RotateTo和RotateBy指定一个角度y,那么RotateTo和RotateBy最终的效果分别如下:
RotateTo:x → y
RotateBy:x → (x + y)
RotateTo和RotateBy各属一类,它们的继承关系如下:
接下来看每个类有什么接口,并结合实例说明。
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
|