Windows下Cocos2d-x3.3中RotateTo和RotateBy的用法

2015年03月17日 09:31 0 点赞 0 评论 更新于 2025-11-21 17:24

在Cocos2d-x 3.3的Windows环境中,RotateToRotateBy这两个动作类都可用于实现精灵的旋转效果,但它们在功能上存在一些差异。

一、RotateTo和RotateBy的区别

RotateToRotateBy都能让精灵旋转,不过具体效果有所不同:

  • 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类中createinitWithDuration方法的实现源码:

// 平面旋转。
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;
}

三、关键点总结

  1. 旋转类型的实现:通过向RotateBy::create()传递不同种类的旋转坐标,可以实现2D旋转、带角度的3D旋转以及真正的3D旋转。该函数可以设置旋转动作的持续时间,旋转角度的正负控制旋转方向。
  2. 坐标轴的参考:让精灵围绕X、Y、Z轴旋转时,指的是精灵本身的坐标轴,而非世界或屏幕的坐标轴。
  3. 功能的分工RotateBy并没有具体实现运动的过程,它只相当于一个配置。并且配置还进行了细化,其父类负责动画的持续时间,而RotateBy只负责旋转的坐标。
  4. 代码优化建议:个人认为bool RotateBy::initWithDuration(float duration, float deltaAngle)bool RotateBy::initWithDuration(float duration, float deltaAngleX, float deltaAngleY)可以合并,均使用第二个。2D旋转调用initWithDuration()时传递的deltaAngleXdeltaAngleY相同即可,就像RotateBy::clone()中做的那样。

四、疑问

bool RotateBy::initWithDuration(float duration, float deltaAngleX, float deltaAngleY)方法中,存在一些疑问,但原文未完整给出相关内容。后续可进一步研究该方法在实际应用中的具体表现和潜在问题。

作者信息

boke

boke

共发布了 3994 篇文章