I expect a very simple answer, but beyond me. I've done some searching but can't find anything.

I want to rotate a sprite at a constant rate a tick so it will try to face another sprite.

I can calculate the angle between them, it's dealing with the rotation increment/decrement when the angle crosses the 360 degrees mark to 0 degrees, messes up my code and I just can't think through it.

I'm still confused on how to get this fully working though. Merely using playerAngle won't account for the entities current rotation, it'll only give the angle between two points. The entity will just spin infinitely as playerAngle will never change so long as it is static, despite it rotating. How do I factor in it's rotation?

Actually it is important that you use the right inverse function to get the right sign. Intuitively, you want to put yourself in the position of your character and facing the same direction. You turn clockwise if it is to your left, counter clockwise if it is on your right, or face the target directly if is right about in front of you. Atan will give you an absolute angle. The dot product will tell you if something is in front or behind you. To make the sign tell whether you are on the left or right, rotate the direction you are facing 90 degrees and use that with your dot product. In 2D, that is like taking the Z-component of the cross product.

I was thinking cross product because swapping the order for two vectors changes the outcome while dot product does not. That gives you the correct sign and I think the right angle if you use sin-1. I was thinking my answer was applicable in 2D or 3D, but I will have to look at the math to figure out what my train of thought really was. In 2D, you could subtract two absolute angles from each other and adjust the answer to get the right sign.

If all the numbers work out, you could do the same thing I wrote in one line.

Actually it is important that you use the right inverse function to get the right sign. Intuitively, you want to put yourself in the position of your character and facing the same direction. You turn clockwise if it is to your left, counter clockwise if it is on your right, or face the target directly if is right about in front of you. Atan will give you an absolute angle. The dot product will tell you if something is in front or behind you. To make the sign tell whether you are on the left or right, rotate the direction you are facing 90 degrees and use that with your dot product. In 2D, that is like taking the Z-component of the cross product.

I was thinking cross product because swapping the order for two vectors changes the outcome while dot product does not. That gives you the correct sign and I think the right angle if you use sin-1. I was thinking my answer was applicable in 2D or 3D, but I will have to look at the math to figure out what my train of thought really was. In 2D, you could subtract two absolute angles from each other and adjust the answer to get the right sign.

If all the numbers work out, you could do the same thing I wrote in one line.

thing.rotate(Math.max(-maxTurn, Math.min(maxTurn, angle)));

You can use a cross product to do the rotation as well, just do:

thing.forward x (target.pos - thing.pos)

where thing.forward is the forward vector of the sprite to be rotated (which doesn't need to be normalised).

Then as you show on your diagram, -ve or +ve Z indicate which way to rotate. Then keep rotating until the abs of the cross-product is below a threshold.

Remember if you use the dot or cross product, you should be doing it with vectors and not the positions as you are using here. So as I said above, you want to use the entity forward (direction) vector and entity->player vector.

Edit: Actually one other thing you need to check with the cross product is that the entity is not facing directly away from the player (i.e. 180 degrees), as the cross will also be zero then. You can do that with a dot product.

That will return an angle between -180 and 180 with the angle starting on the II quadrant along the X-axis. You just have to add 180 to it and everything will be resolved to an angle resulting in a positive number. I just did it right now.

Using a complex number/vectors instead you have: the sign of the cross product (orthogonal direction) tells you which direction is the minimal angular path. A constant angular velocity (for fixed simulation timesteps) is a fixed complex number. Multiple the current rotation (identical to unit direction vector) performs the rotation. Re cross product and if the sign has changed you have overshot the target direction..set to target. No trig, inverse trig or any explicit angles.

If you do that, you will continuously overshoot the target when the angle between them is less than the angular velocity. I tried to solve the problem of all three cases of the if, else if, else block without using only multiplications. You could avoid trig if you stored cos(maxTurn) (because it is constant.) I could not do away with both square roots and inverse trig functions.

Make sure you check your code carefully. There were some bugs there (y/x being swapped in atan2, decreasing rotation when the angle was > 0) which you can spot yourself if you take the time to look through.

I've finally reached a perfect solution, although I can't say this code is as efficient as can be. The real problem ended up the different way rotations were being stored. For the entities rotation, it run counterclockwise 0-360. The result of atan2 gave me something running clockwise and -180-180. The key turned out to be converting to counterclockwise 0-360, after which it was a trivial solution, although code posted earlier on here helped out, particulary in ensuring there isn't jerky movement when the entity is pointing towards the ship out by only a fraction of a degree.

I'm not sure if this solution would apply to anyone else's code, but hopefully it could be of help to somebody. Either way, there is plenty of reading material on this post, and I'd like to thank everybody who contributed and helped solve my issue!

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org