Windows下Cocos2d-x3.3中RotateTo和RotateBy的用法
在Cocos2d-x 3.3的Windows环境中,RotateTo和RotateBy这两个动作类都可用于实现精灵的旋转效果,但它们在功能上存在一些差异。
一、RotateTo和RotateBy的区别
RotateTo和RotateBy都能让精灵旋转,不过具体效果有所不同:
RotateTo:它会将精灵旋转到指定的角度。假设精灵当前的角度是x,给RotateTo指定一个角度y,那么最终精灵会从角度x旋转到角度y,即x → y。RotateBy:它是让精灵从当前角度开始,旋转指定的角度。同样假设精灵当前角度是x,给RotateBy指定一个角度y,最终精灵会从角度x旋转到角度x + y,即x → (x + y)。
二、RotateBy类的详细分析
1. 成员变量
RotateBy类有以下重要的成员变量:
protected:
bool _is3D; // false: 使用带角度的3D旋转方式;true: 使用真正的3D旋转方式。
Vec3 _dstAngle; // 目标角度。
Vec3 _startAngle; // 起始角度。
Vec3 _diffAngle; // 目标角度与起始角度之差。
private:
CC_DISALLOW_COPY_AND_ASSIGN(RotateTo); // 禁用拷贝构造函数和拷贝赋值操作符。
2. 成员方法
RotateBy类提供了以下几个静态的create方法来创建旋转动作:
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方法:实现平面旋转。其中,正的角度表示顺时针旋转,负的角度表示逆时针旋转。 - 第二个
create方法:实现带角度的3D旋转。 - 第三个
create方法:实现真正的3D旋转。
需要注意的是,第二个和第三个函数指定的围绕哪个轴旋转,指的是精灵本身的坐标轴,而非世界或者屏幕的坐标轴。
各参数的含义如下:
duration:旋转动作的持续时间。deltaAngle:需要旋转的平面角度。deltaAngleZ_X:X轴需要旋转的角度。deltaAngleZ_Y:Y轴需要旋转的角度。deltaAngle3D:需要旋转的3D角度,是一个Vec3类型的向量。
3. 实例代码
以下是使用RotateBy创建不同旋转动作的实例:
// 用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));
4. 让精灵执行旋转动作
要让精灵真正旋转起来,可参考以下代码:
auto mySprite = Sprite::create("mysprite.png");
mySprite->setPosition(Vec2(100, 100));
this->addChild(mySprite);
mySprite->runAction(RotateBy::create(10, 360));
注意,mysprite.png图片需要放在工程的Resources目录下。
5. 实现源码分析
以下是RotateBy类中create和initWithDuration方法的实现源码:
// 平面旋转。
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()中做的那样。
四、疑问
在bool RotateBy::initWithDuration(float duration, float deltaAngleX, float deltaAngleY)方法中,存在一些疑问,但原文未完整给出相关内容。后续可进一步研究该方法在实际应用中的具体表现和潜在问题。