1
\$\begingroup\$

I'm creating an attack boat game in c++ and I have an issue with my boat following the mouse around the screen. My plan is to have the boat follow the mouse more like a boat (slow rotations, instead of instantaneous whilst taking about 4 seconds to do a 360 turn) and for the most part it does what it should.

The bug happens when the mouse is on the left side of the screen (as soon as my mouse crosses the -x axis), as the boat follows the mouse, the boat turns in the wrong direction and does a 360, instead of following the mouse.

This is the code i'm using to do my boat turning.

        angle = atan2(delta_y, delta_x) * 180.0 / PI; 

        //Rotate the boat towards the mouse and
        //make the boat turn more realistically
        if (angle - rotate > 0) {
            rotate += 1.0f; // turns left
        } else if (angle - rotate < 0) {
            rotate -= 1.0f; // turns right
        }
        if (angle - rotate >= 360.0f) {
            rotate = 0.0f;
        }` 
\$\endgroup\$
1
\$\begingroup\$

It looks like you want to compute the signed difference between your two angles, taking into account that angles "wrap around," so the fastest way to get from +170 to -170 is to keep increasing, even though on a number line you'd have to go the other way and decrease.

Try this trick:

  float angleDifference = fmod(destination - current + 900f, 360f) - 180f;

This gives us the signed difference between two angles in the range [-360, 360], correctly handling the rotation direction across the wrap-around point.

  current += clamp(angleDifference, -1f * turnRate, 1f * turnRate);

  current = fmod(current, 360f); // Keep current from wandering too far afield.

How this works is the fmod or modulo operator (also represented by a % for integers or in other languages) "wraps" the number back to 0 when it goes above 360, or below -360. Adding 900 (2.5 * 360) keeps the intermediate math positive for our given input range, and we subtract the 0.5 * 360 at the end so that clockwise rotations come out negative.

\$\endgroup\$
  • \$\begingroup\$ % doesn't work with floats. Use fmod() instead. \$\endgroup\$ – HolyBlackCat Apr 4 '17 at 18:08
  • \$\begingroup\$ Right you are, @HolyBlackCat - I got used to C# where it's overloaded to work with both floating point and integer types. Fixed above. Feel free to make edits for simple corrections like this. :) \$\endgroup\$ – DMGregory Apr 4 '17 at 18:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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