Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to implement a type of movement where the object gradually faces the target. The problem I've run into is figuring out which turning direction is faster. The following code works until the object's orientation crosses the -PI or PI threshold, at which point it will start turning into the opposite direction

void moveToPoint(sf::Vector2f destination) {
    if (destination == position) return;

    auto distance = distanceBetweenPoints(position, destination);
    auto direction = angleBetweenPoints(position, destination);

    /// Decides whether incrementing or decrementing orientation is faster
    /// the next line is the problem
    if (atan2(sin(direction - rotation), cos(direction - rotation)) > 0 ) {
        /// Increment rotation
        rotation += rotation_speed;
    } else {
        /// Decrement rotation
        rotation -= rotation_speed;
    }

    if (distance < movement_speed) {
        position = destination;
    } else {
        position.x = position.x + movement_speed*cos(rotation);
        position.y = position.y + movement_speed*sin(rotation);
    }
    updateGraphics();
}

'rotation' and 'rotation_speed' are implemented as custom data type for radians which cannot have values lower than -PI and greater than PI. Any excess or deficit "wraps around". For example, -3.2 becomes ~3.08.

share|improve this question
    
Just off-topic: You are telling that rotation should wrap around if it exceeds. For example -3.2 becomes 0.06. Shouldn't it be 3.08 (= PI - 0.06)? –  zacharmarz Jun 28 '13 at 20:22
    
add comment

2 Answers

up vote 3 down vote accepted

Assuming direction is the desired rotation angle to turn toward, just subtract direction - rotation and wrap the result into the [-pi, pi] range. Then its sign should indicate the correct direction to turn. There's no need to munge it through any trigonometric functions.

share|improve this answer
    
Yes, direction is the desired rotation. What you're suggesting doesn't work any better than what I had before though. –  A.B. Jun 28 '13 at 20:00
    
I think what he is saying is that you do not need atan2 there since you already have the desired direction. From there I usually check to see if the difference is greater than pi or less than -pi and subtract or add 2pi to ensure that it turns to the shortest distance. –  UnderscoreZero Jun 28 '13 at 20:43
    
I have to correct myself. It works - there was a problem with the [-PI, PI] that wasn't apparent. –  A.B. Jun 28 '13 at 20:57
add comment

This is faster because it does not have to calculate the atan. It just determines if your angle is greater or lesser than Path.PI.

/**
* Gets the angle that is in the range [-2*PI, 2*PI] and returns the equivalent angle
* that is in the (-PI, PI] range.
*/
void function normalizeAngle(a:Number):Number {
    if (a > Math.PI) {
        return a - 2 * Math.PI;
    } else if (a <= -Math.PI) {
        return a + 2 * Math.PI;
    }
    return a;
}

// usage example:
var rotationDifference:Number = normalizeAngle(targetRotation - originalRotation);

On each update you rotate a portion of the rotationDifference.

share|improve this answer
1  
Just change the if in while to make it work for all angles. Of course, get rid of the else :) –  Martijn Courteaux Jun 28 '13 at 22:35
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.