Jump to content
  • Advertisement
Sign in to follow this  
Toolmaker

Calculating the angle towards another object...

This topic is 4238 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a weird problem with my game, namely that units all the sudden bend towards a different angle when they're approaching said object/location. This is the idea: The game is a 2D tile-based RTS, and when units are moving, they calculate their angle towards to target(-area) and update their position accordingly. This happens every frame to make sure the unit arrives at the exact center of the tile. My code to calculate the angle is:
        protected float CalculateDesiredAngle(float opposite, float adjacent, out float hypotenuse)
        {
            // Calculate the desired angle to the unit
            hypotenuse = (float)Math.Sqrt(opposite * opposite + adjacent * adjacent);
            float desiredAngle = Math.Abs((float)Math.Atan(opposite / adjacent));

            // Correct the angle along the unit circle
            if (opposite < 0.0f)
            {
                if (adjacent == 0.0f)
                    desiredAngle += (float)Math.PI;
                else if (adjacent > 0)
                    desiredAngle += (float)Math.PI;
                else
                    desiredAngle += (float)Math.PI * 1.5f;
            }
            else if (opposite > 0.0f)
            {
                if (adjacent > 0)
                    desiredAngle += (float)Math.PI * 0.5f;
            }
            else
            {
                if (adjacent > 0.0)
                    desiredAngle += (float)Math.PI;
            }

            // Correct the desiredAngle so it's not negative or higher than 2 PI
            if (desiredAngle >= (float)Math.PI * 2)
                desiredAngle -= (float)Math.PI * 2;
            else if (desiredAngle < 0.0f)
                desiredAngle += (float)Math.PI * 2;

            return desiredAngle;
        }

It checked by not moving the unit, and it worked, except that 0.0 points eastwards. Not a problem, since I can change how the unit is position when drawing. During update, I do this:
Point next = path[0];
nextTile.X = next.X * Tile.Size + Tile.Size / 2;
nextTile.Y = next.Y * Tile.Size + Tile.Size / 2;
float hypotenuse;
float desiredAngle = CalculateDesiredAngle((next.X * Tile.Size + Tile.Size / 2) - Position.X, (next.Y * Tile.Size + Tile.Size / 2) - Position.Y, out hypotenuse);
if (angle != desiredAngle) // Make sure we don't rotate too much
{
    if (Rotate(desiredAngle, (float)Math.PI, deltaTime) != desiredAngle)
    {
        AdjustDirection();
        return false; // We haven't reached the correct angle yet
    }

    AdjustDirection();
}

// ... Code related to reserving tiles, checking if movement can occur, etc.

float x = ((float)Math.Cos(angle) * speed) * deltaTime;
float y = ((float)Math.Sin(angle) * speed) * deltaTime;
// Some code related to rounding down movement
position.X += x;
position.Y += y;

Now, it starts out perfectly, and moves up:
Angle = 270,7619
Angle = 270,7822
Angle = 270,7832
Angle = 270,7843
Angle = 270,7854
...
Angle = 276,9893
Angle = 277,5833
Angle = 278,2739
Angle = 279,061
Angle = 279,9727
Angle = 280,9644
Angle = 282,0956
Angle = 283,4937
As you can see, the further it moves towards the target tile, the more the angle bends off to the east. I have no idea what I am doing wrong here, so any help might be appreciated. Toolmaker

Share this post


Link to post
Share on other sites
Advertisement
I didn't look any further than this in your code, but using an inverse tangent to compute the angle can be problematic (mostly due to precision/stability problems, and handling of quadrants).

I can't say for sure if that's the cause of the problem, but if you have an 'atan2' function available you should use it instead.

Share this post


Link to post
Share on other sites
What does the code for your AdjustDirection() function look like? My hunch is that something odd may be going on in there.

Also, when you do the comparison "if (angle != desiredAngle)" you may be falling into that if-block unintentionally. Since you are comparing floats, which were calculated using sin/cos/tan, it's a bit unlikely that they will be exactly equal as you might be expecting.

Share this post


Link to post
Share on other sites
The AdjustDirection() function is used to change the visual angle of the unit. I'm using the tiles from Dune 2, and those units had 8 different directions. The AdjustDirection compares the various angles and based on the angle, it determines which part of the sprite it needs by moving the source rectangle around. It doesn't touch the angle to write too.

About the angle != desiredAngle, in the Rotate() function, I first calculate the radians that is turned, then check if the unit would overturn, and limit it if that is the case. It always results in the angle being exactly the desired one.

I'll try atan2.

Toolmaker

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!