Pointing the turret/tankhead of a RTS Tank at a certain location

Started by
6 comments, last by pancomplex 15 years, 10 months ago
Hello out there, This problem has been giving me a really hard time for a couple of days now, so I hope some of the good people in here could help me out a little bit. I'm currently developing a 2d RTS game which has worked out pretty good so far. When it comes to the tanks I found out how to rotate the head and the turret as an independent unit, but know i need the turret and tank head to point at a given location (i.e. X = 200, Y = 300). I have found this really hard, since I'm using degrees to rotate the tank head, and X and Y cordinates for the position for it to look at. How is it possible to calculate the degree of turning around in order to look at the X and Y cordinate (180 being half the way and 360/0 being all the way). If somebody could help me out it would be awesome!
Advertisement
What do you mean by 'tank head'? Also, are you asking how to turn the tank as a whole towards the target (with the turret remaining in its default - that is, pointing straight ahead - orientation)? Or are you asking how to turn the turret towards the target regardless of which direction the body (which is what I'm guessing you mean by 'head') is pointing?
You have two coordinate pairs, the turret position and the target it is pointing at. Those two points describe the hypotenuse of a right-triangle:



The center of the red cross-hair is the position of the turret, while the other end of the diagonal bright green line is the target position. Drawing a vertical line downward (dashed, dark green line) yields a y-intercept, and the distance from the center of the cross-hair to the vertical line along the x-axis yields the x-intercept. The angle theta between the x-axis and the hypotenuse, theta is trivially computed as arcsin(dy / dx), where dx and dy refer to the relative intercepts.

Given your two coordinate pairs (x1, y1) and (x2, y2), the x- and y-intercepts are simply the differences between coordinate elements:
dx = x2 - x1;dy = y2 - y1;theta = arcsin(dy / dx);

Note that the C and C++ standard library implementations of arcsin yield values in radian measure, which you'll have to convert to degrees. I leave that as an exercise to you. [smile]
Thank you so much Oluseyi!! Man, I can't believe I didn't think about doing it that way! Awesome!

jyk -> Check out Oluseyi's post to see what I meant :) and thanks a lot for bothering!


Edit: I got it working but I used arctan instead (since we are working with the adjacent and opposite site) whereas the arcsin would be used to work with the hypotenuse and opposite site. Thanks again! :)

[Edited by - pancomplex on June 22, 2008 3:01:38 PM]
Quote:jyk -> Check out Oluseyi's post to see what I meant :) and thanks a lot for bothering!
I could be missing something, but I'm not sure that Oluseyi's solution is correct.

First of all, in general, asin() will return an angle in the range [-90, 90] (or the equivalent in radians), which means that additional computations will be required to determine the correct quadrant. Also, if I'm not mistaken, asin(dy/dx) will not yield the correct results in any case (for example, asin(1/1) will return 90 degrees, where the desired result given these values would be 45 degrees).

Perhaps Oluseyi meant to use atan(), but this also suffers from the 'which quadrant?' issue, as well as suffering from numerical issues when |x| is small.

Assuming you have such a function available, I would recommend that you instead use atan2():
vector2 diff = target - position;float angle = atan2(diff.y, diff.x);
The only special case you may need to consider when using this method is when the target is very near the turret's pivot point (i.e. right on top of it).

[Edit: It looks like you already figured out that you needed to use atan() rather than asin(). However, I'd still recommend using atan2() instead, if you have it available.]
Quote:Original post by jyk
Quote:jyk -> Check out Oluseyi's post to see what I meant :) and thanks a lot for bothering!
I could be missing something, but I'm not sure that Oluseyi's solution is correct.

First of all, in general, asin() will return an angle in the range [-90, 90] (or the equivalent in radians), which means that additional computations will be required to determine the correct quadrant. Also, if I'm not mistaken, asin(dy/dx) will not yield the correct results in any case (for example, asin(1/1) will return 90 degrees, where the desired result given these values would be 45 degrees).

Perhaps Oluseyi meant to use atan(), but this also suffers from the 'which quadrant?' issue, as well as suffering from numerical issues when |x| is small.

Assuming you have such a function available, I would recommend that you instead use atan2():
vector2 diff = target - position;float angle = atan2(diff.y, diff.x);
The only special case you may need to consider when using this method is when the target is very near the turret's pivot point (i.e. right on top of it).

[Edit: It looks like you already figured out that you needed to use atan() rather than asin(). However, I'd still recommend using atan2() instead, if you have it available.]


Wait a minute, does this mean that I don't have to worry about any of the quadrants if I use atan2 (sorry, I've never heard about it before :P). Thanks.
Quote:Wait a minute, does this mean that I don't have to worry about any of the quadrants if I use atan2...
Yes, that's right.
Quote:Original post by jyk
Quote:Wait a minute, does this mean that I don't have to worry about any of the quadrants if I use atan2...
Yes, that's right.


OMG I just used it and it works freaking awesome! :O! Thank you so much! You just saved me hours of work!

This topic is closed to new replies.

Advertisement