cocos2d-x v3.9 关于RotateTo和SkewTo的疑问

原创 2015年11月19日 11:01:32

最近在研究cocos2d-x v3.9的RotateTo时遇到了个问题,不知道是否算是Bug。

首先说一下我理解的RotateTo。RotateTo不关心精灵当前的角度,将精灵旋转至指定的角度。无论指定的角度是多少,最终旋转的角度一定在-360°~360°之间。进一步,我认为如果指定的角度为正角度则应按照顺时针方向将精灵旋转至指定角度;如果指定的角度为负角度,则应按照逆时针方向。

例如精灵的初始角度为0°,指定旋转角度为1090°,则实际应按照顺时针旋转10°(1090 % 360);又或者精灵的初始角度为0°,指定旋转角度为-591°,则实际应按照逆时针旋转231°(591 % 360)。

实际情况:比如精灵的初始角度均为0°。
1、

auto myRotateTo = RotateTo::create(3, 270);
mySprite->runaction(myRotateTo);

效果:以逆时针旋转90°。

2、

auto myRotateTo = RotateTo::create(3, -181);
mySprite->runaction(myRotateTo);

效果:以顺时针旋转179°。
看起来是遵循了就近原则,从当前角度到指定角度走了个最近路程。看一下源码:

void RotateTo::calculateAngles(float &startAngle, float &diffAngle, float dstAngle)
{
    // 将startAngle更新为对360.0°求余的角度。
    // 比如startAngle传进来是721.7°,更新后为1.7°。
    if (startAngle > 0)
    {
        startAngle = fmodf(startAngle, 360.0f);
    }
    else
    {
        startAngle = fmodf(startAngle, -360.0f);
    } 

    diffAngle = dstAngle - startAngle;    // 得到目标角度与起始角度之间的差值。
    if (diffAngle > 180)
    {
        diffAngle -= 360;
    }
    if (diffAngle < -180)
    {
        diffAngle += 360;
    }
}

初步证实了,是就近原则那么个意思。如果顺时针的旋转角度大于180°了,那从逆时针方向转更近,逆时针方向的同理。
可真的是这样吗?继续测试。

3、

auto myRotateTo = RotateTo::create(3, 640);
mySprite->runaction(myRotateTo);

效果:以顺时针旋转280°。如果遵循就近原则,应该按照逆时针旋转80°。

4、

auto myRotateTo = RotateTo::create(3, -541);
mySprite->runaction(myRotateTo);

效果:以逆时针旋转181°。如果遵循就近原则,应该按照顺时针旋转179°。

5、

auto myRotateTo = RotateTo::create(3, 899);
mySprite->runaction(myRotateTo);

效果:以顺时针旋转539°。这更没什么就近原则之说了,起码效果上是多转了一圈。

6、

auto myRotateTo = RotateTo::create(3, -731);
mySprite->runaction(myRotateTo);

效果:以逆时针旋转371°。同上,没有就近原则之说,起码效果上多转了一圈。

**至此做个总结:
精灵的初始角度为0°,
当 -540° <= 指定的角度 <= 540°时,旋转遵循就近原则,旋转的角度在360°之内。
当 541° < 指定的角度 < 720° 或者 -720° < 指定的角度 < -541° 时,旋转不遵循就近原则,旋转的角度在360°之内。
当 指定的角度 >= 720° 或者 指定的角度 <= -720° 时,旋转的角度在360°之外,即起码多旋转了一圈,也就无法谈及是否遵循就近原则了。**

如果按照我理解的RotateTo,RotateTo::calculateAngles()应该是如下形式:

void RotateTo::calculateAngles(float &startAngle, float &diffAngle, float dstAngle)
{
    diffAngle = fmodf(dstAngle, 360) - fmodf(startAngle, 360);
    diffAngle = fmodf(diffAngle, 360);

    if(((diffAngle < 0) && (dstAngle >= 0)) || ((diffAngle > 0) && (dstAngle < 0)))
    {
        if(diffAngle > 0)
            diffAngle -= 360;
        else
            diffAngle += 360;
    }

    return ;
}

SkewTo在计算变化角度的时候也有同样的问题。此外,SkewTo在对X轴的变化角度取余的时候为何对180°求余?

if (_startSkewX > 0)
{
    _startSkewX = fmodf(_startSkewX, 180.f);    // 180°?
}
else
{
    _startSkewX = fmodf(_startSkewX, -180.f);    // 180°?
}

这样会导致问题。举个简单的例子,比如我让X轴从181°变换到191°,

sprite->setSkewX(181);
auto skewto = SkewTo::create(3, 191, 0);
sprite->runAction(skewto);

本意只是想让X轴沿顺时针方向变化10°,单实际的效果是X轴沿逆时针方向变化了170°。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

cocos2d-x实例学习(7)之同时使用rotate,skew,scale

本实例演示了同时使用CCRotateTo,CCSkewTo,CCScaleTo来实现动态效果,代码如下 CCSize boxSize = CCSizeMake(100.0f, 100.0...

cocos2d-x实例学习(5)之SkewTo&SkewBy

SkewTo&SkewBy概念 SkewTo:把某一CCSprite歪斜到某一值 SkewBy:把某一CCSprite歪斜多少值,它有一个方法reverse,它让对象按原路径返回 S...

cocos2dx的可以实现的效果总结

动作(Actions) move移动:moveto/moveby 从一个位置移动到另外一个位置 从一个位置移动多少数量级 rotate旋转:rotateto/rotateby 从一个角度旋...

Cocos2d-x能够实现的效果总结

Cocos2d-x能够实现的效果总结

cocos2dx之CCRotateTo、CCRotateBy

我学习的这个版本是2.0版的,后面版本都已经更新了,所以在使用改变CCRotateTO、CCRotateBy改变运动需要借助其他的成员方法,下面的例子是在2.0编写的: void MyActionR...

Cocos2dx中RotateTo对旋转方向的处理

今天在写个demo的时候意外发现了一个跟rotate相关的有趣的事情。 如果我们想要将一个物体旋转朝向另外一个物体的时候,一般都会采用如下的方法: // 通过tan值求arctan来得到旋转角...

cocos2d-x v3.9 与ActionInterval的孩子们之间的对话(3)

我:今天咱们继续聊,还~有~谁~? TargetedAction:这儿呢,这儿呢。我能让一个精灵待执行的动作在另一个精灵的动作执行完成之后执行。这可不同于Sequence,Sequence是让同一个精...

cocos2d-x v3.9 与ActionInterval的孩子们之间的对话(1)

我(对MoveBy):你的爹地ActionInterval除了你还有其他的孩子吗? MoveBy:有,而且还有很多。他们也几乎都是一对儿一对儿的,不是父子就是兄弟,当然也有独生子。 我(窃窃私语)...

cocos2d-x v3.9 与ActionInterval的孩子们之间的对话(2)

我:我看在ActionInterval的孩子中你们好像有些与众不同。 Sequence、ExtraAction、Repeat、RepeatForever、DelayTime以及ReverseTime...

Cocos2d-x 3.9教程:4.精灵的创建和基本操作

1. 精灵的创建和基本操作 1.1. 精灵的创建 ①正常创建 Sprite *sprite = Sprite::create("man.png");//通过图片创建精灵 sprite->setPos...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)