Tuesday, June 26, 2018

xna - Rotate entity to match current velocity


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.



Answer



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.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...