Android 根据运动来确定精灵的方向

Android 根据运动来确定精灵的方向,android,ios,mobile,cocos2d-x,marmalade,Android,Ios,Mobile,Cocos2d X,Marmalade,我正在开发一个使用Cocos2d-X和果酱SDK的游戏。在这个游戏中,我有几个物体在屏幕上使用漫游转向行为四处移动,但是我在确定这些物体朝向运动方向时遇到了很多问题 在我的GamObject类更新方法(精灵实际上是该对象的子对象)中,我有: 计算角度的方法为: float GameObject::calculateAngle(CCPoint nextPosition) { float offsetX, offsetY, targetRotation, currentRotation;

我正在开发一个使用Cocos2d-X和果酱SDK的游戏。在这个游戏中,我有几个物体在屏幕上使用漫游转向行为四处移动,但是我在确定这些物体朝向运动方向时遇到了很多问题

在我的GamObject类更新方法(精灵实际上是该对象的子对象)中,我有:

计算角度的方法为:

float GameObject::calculateAngle(CCPoint nextPosition)
{
    float offsetX, offsetY, targetRotation, currentRotation;
    int divRest;

    currentRotation = this->getRotation();

    // Calculates the angle of the next position.
    targetRotation = atan2f((-1) * nextPosition.y, nextPosition.x);
    targetRotation = CC_RADIANS_TO_DEGREES(targetRotation);

    targetRotation = targetRotation - currentRotation;

    // Make sue that the current rotation is not above 360 degrees.
    if (targetRotation > 0)
    targetRotation = fmodf(targetRotation, 360.0);
    else
        targetRotation = fmodf(targetRotation, -360.0);

    return targetRotation;
}
不幸的是,当我运行这段代码时,对象面向所有地方,而不是运动方向。我不知道我做错了什么

更新

您好,我已根据您的建议更新了代码:

void GameObject::update(float dt)
{
    float angle;
    CCPoint newVelocity;

    newVelocity = gameObjectMovement->calculateSteeringForce(dt);

    // Check if the velocity is greater than the limit.
    if (ccpLength(newVelocity) > MAX_WANDER_SPEED)
        newVelocity = ccpMult(ccpNormalize(newVelocity), MAX_WANDER_SPEED);

    nextPosition = ccpAdd(this->getPosition(), ccpMult(newVelocity, dt));

    angle = calculateAngle(newVelocity);

    this->setPosition(nextPosition);
    this->setRotation(angle);

    velocity = newVelocity;
}

float GameObject::calculateAngle(CCPoint velocity)
{
    float offsetX, offsetY, targetRotation, currentRotation;
    int divRest;

    // Calculate the angle based on the velocity.
    targetRotation = atan2f((-1) * velocity.y, velocity.x);
    targetRotation = CC_RADIANS_TO_DEGREES(targetRotation);

    // Make sure that the rotation stays within 360 degrees.
    if (targetRotation > 0)
        targetRotation = fmodf(targetRotation, 360.0);
    else
        targetRotation = fmodf(targetRotation, -360.0);


    return targetRotation;
}

它现在工作得好多了,但是我仍然看到一些奇怪的行为。实际移动方向/速度与我的对象的正面之间有90度的差异。

在我看来,你的方程式考虑了屏幕上下一点的绝对位置,这不会给你正确的旋转


要修复它,请使用速度向量的方向(我假设它有一个可用的X和Y值)来计算精灵旋转。如果使用此方法,则无需考虑之前的旋转。

您可能应该根据运动/速度矢量计算旋转,而不仅仅是最终位置。。。还有,currentRotation到底在做什么?嗨,我不小心删除了代码中的一行。当前旋转只是一个保存节点旋转的变量(这种方式更容易调试)。我将重新编写代码,根据速度向量计算旋转,并查看它是如何进行的。嗨,我更改了行:
angle=calculateAngle(nextPosition)至:
角度=计算角度(新速度)这样我就可以试着用这种方式计算角度,但结果仍然不是我所期望的,因为我的对象并不总是朝向运动方向。就像我提到的currentRotation是不需要的,你正在设置旋转,所以不需要减去currentRotation。嗨,事实上,下一个位置向量也是在局部坐标上,所以我猜我犯的错误之一是在计算目标旋转时考虑了当前旋转。是的,听起来像slazyk告诉过你同样的事情。是的,我完全按照你和@slazik告诉我的做了,然而,仍然有一些奇怪的地方:我的对象与运动方向/速度向量有90度的偏移。如果我给它们加上90度,那么它们的方向是正确的。也许我遗漏了什么。你确定你的斧头是直的吗?你知道0度相对于屏幕的位置吗?这可能只是因为你认为0度是90度。嗨,是的,你是对的,我是沿着Y轴定向我的物体,但是我是用X轴计算速度角,因此我是“90度偏离对齐”。我现在已经沿着X轴定向了我的对象,一切都在工作。非常感谢你的帮助!
void GameObject::update(float dt)
{
    float angle;
    CCPoint newVelocity;

    newVelocity = gameObjectMovement->calculateSteeringForce(dt);

    // Check if the velocity is greater than the limit.
    if (ccpLength(newVelocity) > MAX_WANDER_SPEED)
        newVelocity = ccpMult(ccpNormalize(newVelocity), MAX_WANDER_SPEED);

    nextPosition = ccpAdd(this->getPosition(), ccpMult(newVelocity, dt));

    angle = calculateAngle(newVelocity);

    this->setPosition(nextPosition);
    this->setRotation(angle);

    velocity = newVelocity;
}

float GameObject::calculateAngle(CCPoint velocity)
{
    float offsetX, offsetY, targetRotation, currentRotation;
    int divRest;

    // Calculate the angle based on the velocity.
    targetRotation = atan2f((-1) * velocity.y, velocity.x);
    targetRotation = CC_RADIANS_TO_DEGREES(targetRotation);

    // Make sure that the rotation stays within 360 degrees.
    if (targetRotation > 0)
        targetRotation = fmodf(targetRotation, 360.0);
    else
        targetRotation = fmodf(targetRotation, -360.0);


    return targetRotation;
}