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 have an entity in 2D space moving around, lerping between waypoints. I would like to make the entity rotate around its own origin to face the current direction that it is going, I.E. towards the next waypoint in the list.

In case the waypoint movement code is needed, I'm using the following (this is contained inside of the entity that is following the waypoints) :

    private void GoToWaypoint() {
        if (waypointList.Count > 0) {
            Vector2 origin = helper.GetOrigin(position, width, height);
            int nodeWidth = 50;
            int nodeHeight = 50;

            if (moveToPosition != waypointList[0]) {
                moveToPosition = waypointList[0];
                moveToPositionOrigin = helper.GetOrigin(moveToPosition, nodeWidth, nodeHeight);
                distanceToPosition = moveToPositionOrigin - origin;
            }

            if ((Math.Ceiling(distanceToPosition.X) < 0)) {
                position.X -= moveSpeed;
                distanceToPosition.X = (int)Math.Round(distanceToPosition.X + moveSpeed);
            }
            else if ((Math.Floor(distanceToPosition.X) > 0)) {
                position.X += moveSpeed;
                distanceToPosition.X = (int)Math.Round(distanceToPosition.X - moveSpeed);
            }

            if (Math.Ceiling(distanceToPosition.Y) < 0) {
                // Check if the entity moves below the top boundary
                if (position.Y > 0) {
                    position.Y -= moveSpeed;
                    distanceToPosition.Y = (int)Math.Round(distanceToPosition.Y + moveSpeed);
                }
                else {
                    distanceToPosition.Y = 0;
                }
            }
            else if (Math.Floor(distanceToPosition.Y) > 0) {
                // Check if the entity moves below the bottom boundary
                if (position.Y < 550) {
                    position.Y += moveSpeed;
                    distanceToPosition.Y = (int)Math.Round(distanceToPosition.Y - moveSpeed);
                }
                else {
                    distanceToPosition.Y = 0;
                }
            }

            // If the entity gets in the waypoint, or the distance to the waypoint is 0 on both axis (which can occur due to screen boundaries)
            if ((helper.InNode(position, moveToPosition, width, height, nodeWidth, nodeHeight)) || ((distanceToPosition.X == 0) && (distanceToPosition.Y == 0))) {
                waypointList.RemoveAt(0);
            }
        }
    }

I know this may have been asked elsewhere, and the bit of searching that I did on this type of problem, didn't really help me. I'm slightly math retarded, so I don't understand the explanations that don't really explain what the math is exactly achieving. So any help that breaks down the math and functions needed to achieve this would be greatly appreciated.

Thanks.

share|improve this question
    
How are you currently expressing rotation of your entities? –  Tetrad Oct 30 '11 at 0:00
    
They are currently static. So they stay the same rotation that the sprite gets loaded as. –  Nicholas Oct 30 '11 at 1:58
add comment

1 Answer 1

up vote 3 down vote accepted

Step 1: Ensure that your sprites have a consistent default orientation. That is, all your sprites need to point in the same direction. This will make everything else vastly easier.

Step 2: Given two waypoints, you can compute the vector direction between them. Normalize this vector. This is the direction that you want your ship to face.

Step 3: The C-standard library function atan2 computes an angle (in radians) from a normalized vector. The vector (1, 0) will produce an angle of 0.

Therefore, you can compute the angle to rotate the sprite by calling atan2(dir.y, dir.x) (note that Y comes first. That's not a typo).

Step 4: In Step 1, we ensured that all sprites have a default orientation. atan2 has a default orientation of (1, 0). Therefore, we need to adjust the angle we got, so that providing a vector in the direction of the default produces a 0 angle. This adjustment is done by applying an offset to the value from atan2, depending on what the default orientation is (note: the following assumes that +Y is up and +X is right). The offset for each default orientation is:

  • right: 0
  • up: -pi/2
  • left: -pi
  • down: -3pi/2

Step 5: When you draw this sprite, use the appropriate XNA function to rotate the sprite at draw time. I'm sure XNA has a way to do that. You may have to convert the angle to degrees though.

Note that this computation also assumes that the XNA rotation function rotates counter-clockwise, such that positive angle values rotate it counter-clockwise.


Advice: You should not have a "moveSpeed" that is added to both X and Y. You should have a moveSpeed which is multiplied by the normalized direction to the destination waypoint. That vector (which is the velocity vector) is then added to the current position to get the new position.

share|improve this answer
    
Thanks for your response and advice. Will be sure to implement that movement tip for sure. Can you tell me if I'm going about this right though? The next waypoint in the path is "moveToPosition" rotationAngle = moveToPosition - position; rotationAngle.Normalize(); lookAt = (float)(Math.Atan2(rotationAngle.Y, rotationAngle.X)); lookAt -= (float)((3 * Math.PI) / 2); In my draw method I use "lookAt" to rotate the sprite to face the waypoint. This is working somewhat, but there are some rotation bugs. So just curious if that's because I'm doing it wrong. Thanks again. –  Nicholas Oct 30 '11 at 8:56
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.