Converting 2 Axis Input to an Angle

In summary, a video game programmer is seeking help with converting input from a controller's right stick into a degree measurement to turn the player towards. After discussing various solutions and potential bugs, the programmer is able to successfully implement a code that takes into account the different quadrants and angles to accurately rotate the player's sprite.
  • #1
Drakkith
Mentor
22,975
7,335
I'm dabbling in video game creation and I'm making a very basic top-down twin stick shooter. The problem is that I don't know how to get the player to turn to an angle that matches the controller's right stick. I'm trying to figure out an equation or something to convert the -100 to +100 input from each axis of the stick into a degree measurement to turn the player towards.

For example, if the stick is at a coordinate of (50,50), up and right, then the player would turn to 315 degrees (0 degrees is at the 3 O-clock position in the program I'm using and moves clockwise from there).

Any ideas?
 
Mathematics news on Phys.org
  • #2
Usually, 0o is on the x-axis (3 o'clock position as yours) but the angle moves anticlockwise. In this setting, to find the angle given some coordinate (x,y), where x>0, all we need to do is to compute

[tex]\theta = \tan^{-1}\left({\frac{y}{x}}\right)[/tex]

And the result will be in radians. But now since your system is a clockwise rotation, just take the negative of that value.
Notice that I said for x>0. We run into problems when trying to distinguish, say, (50,50) with (-50,-50) because y/x = 1 in both of these cases while they obviously differ by 180o. We also have another problem. The arctan function we're using returns values between -90o and 90o. Basically, the coordinate (50,50) will return -45o as opposed to 315o which is a whole revolution more.

So let's consider consider the 4 points A,B,C,D where each point is in its respective quadrant starting with A in the lower right, so if we consider their angles to be
$$A=70^o$$
$$B=110^o=180^o-70^o$$
$$C=250^o=180^o+70^o$$
$$D=290^o=360^o-70^o$$

Then we know that the inverse tan function would return A = 70o, B = -70o, C = 70o, D = -70o so you'll need to account for these discrepancies accordingly.
 
  • #3
Thanks, Mentallic. I should be able to make two different events to control the players angle, one for when X > 0 and one for when X < 0. How would that change our math?
 
  • #4
So if X > 0 and Y < 0 (bottom right) then the angle is simply the value returned by the arctan calculation. If X < 0 then we add 180 to the calculation. Finally, if X > 0 and Y > 0 then we add 360.

The code to return the angle could be...

edit: I decided not to post any code in case you want to make the discovery for yourself.
 
  • #6
Thanks, guys. I'll try to implement this as soon as possible and get back to you.
 
  • #7
Got it. Had to figure out a few things regarding which axis was which and in what direction the values increased or decreased, but I worked it out. In my program I have to enter the following events:

System: Every tick
----Gamepad: Gamepad 0 Right Analog X axis > 0
--------Gamepad: Gamepad 0 Right Analog Y Axis < 0 : Player: Set Angle to 360+atan((Gamepad.Axis(0,3))/(Gamepad.Axis(0,2)))
--------System: Else : Player: Set angle to atan((Gamepad.Axis(0,3))/(Gamepad.Axis(0,2)))
----Gamepad: Gamepad 0 Right Analog X Axis < 0
--------Gamepad: Gamepad 0 Right Analog Y Axis not equal to 0 : Player: 180-atan((Gamepad.Axis(0,3))/(Gamepad.Axis(0,2)))

Thanks you two. I couldn't have done it without you.
 
Last edited:
  • #8
Drakkith said:
System: Every tick
----Gamepad: Gamepad 0 Right Analog X axis > 0
--------Gamepad: Gamepad 0 Right Analog Y Axis < 0 : Player: Set Angle to 360+atan((Gamepad.Axis(0,3))/(Gamepad.Axis(0,2)))
--------System: Else : Player: Set angle to atan((Gamepad.Axis(0,3))/(Gamepad.Axis(0,2)))
----Gamepad: Gamepad 0 Right Analog X Axis < 0
--------Gamepad: Gamepad 0 Right Analog Y Axis < 0 : Player: 180-atan((Gamepad.Axis(0,3))/(Gamepad.Axis(0,2)))
--------System: Else : Player: Set Angle to 180+atan((Gamepad.Axis(0,3))/(Gamepad.Axis(0,2)))

A few possible bugs I've noticed.

Have you considered when X=0? The atan calculation will cause problems because you're dividing by zero, but the angle will simply be 90 and 270 deg respectively depending on Y (also assuming X!=0 && Y!=0).
Also I see you're calculating 360+angle for the lower right axis (X>0, Y<0) as opposed to upper right, is this intended?
For X<0, the calculation -atan(Y/X) is 180 degrees short for both Y<0 and Y>0, so you should be calculating 180-atan(Y/X) in both of these.
Finally, the atan(Y/X) result is in radians, and you're adding degrees to it. You need to convert it to degrees first by multiplying -atan(Y/X) by 180/pi, and then do your degree addition.

Here is a sample code in C:
float angle;
assert(X!=0 && Y!=0);

if (X=0 && Y<0)
- - - angle = 90;
else if (X=0 && Y>0)
- - - angle = 270;
else {
- - - float gradient = ((float)Y)/X;
- - - angle = -atan(gradient)*180/pi;
- - - if (X<0)
- - - - - - angle += 180;
- - - else if (Y>0)
- - - - - - angle += 360;
}

return angle;
 
  • #9
Mentallic said:
Have you considered when X=0?


The code only runs the event when X is greater than or less than zero. When X = 0 the event doesn't run, so it is never calculated. I've done some a small amount of testing, so I can't tell if it works perfectly yet, but it appears to work very well overall.


Also I see you're calculating 360+angle for the lower right axis (X>0, Y<0) as opposed to upper right, is this intended?

Yes. My controller's right analog stick goes from 0 to -100 when pressed upwards and 0 to +100 when pressed downwards. It threw me off for a while until I figured that out.

For X<0, the calculation -atan(Y/X) is 180 degrees short for both Y<0 and Y>0, so you should be calculating 180-atan(Y/X) in both of these.

Why's that? If X = -90 and Y = 2, then atan(2/-90) equals -1.273. Adding 180+atan(2/-90) gives me 178, which is the degree I need.

Finally, the atan(Y/X) result is in radians, and you're adding degrees to it. You need to convert it to degrees first by multiplying -atan(Y/X) by 180/pi, and then do your degree addition.

The program I use calculates everything in degrees, no radians. It works. I've tested it and my player's sprite turns to match the angle of the stick very well.
 
  • #10
Drakkith said:
Why's that? If X = -90 and Y = 2, then atan(2/-90) equals -1.273. Adding 180+atan(2/-90) gives me 178, which is the degree I need.


If X = -90 and Y = 2 then that's the top-left quadrant which is 180 and a bit, so you don't want 178 degrees but rather 182 degrees.

But of course, you're the one that's familiar with the system you're using and if you claim it works then why would we try and fix something that isn't broken? ;)
 
  • #11
Mentallic said:

If X = -90 and Y = 2 then that's the top-left quadrant which is 180 and a bit, so you don't want 178 degrees but rather 182 degrees.

This would be true if my controller returned a positive Y-value when the stick is pressed upwards, but it doesn't. When the stick is pressed up it returns a negative value. So pressing it halfway up returns a value of -50.

This took me about one or two infuriating hours to figure out. The math was telling me my code should work, but when I first implemented it, the player's sprite turned everywhere but the right direction!
 
  • #12
Ack! I did make a mistake. I had one of one of my conditions set up to check for the Left analog Y-axis, instead of the Right analog stick Y-axis. Turns out that when X<0 I can simply have one condition for when Y is not equal to zero that will then set the player angle to 180+atan(y/x) and it will work perfectly for when the Y-axis is either negative or positive.
 
  • #13
Oh I see, so really, you just want to calculate atan(Y/X) as opposed to -atan(Y/X) because Y is replaced by -Y, and -atan(-Y/X) and in this case, you can bring the negative within the argument out and we end up with atan(Y/X). So the way you've constructed where to start your angle 0o and to rotate clockwise is equivalent to the standard way it is done in maths.
So we do

angle = atan(y/x);
if (x<0)
- - - angle += 180;
else if (y<0)
- - - angle += 360;
return angle;
 
  • #14
I think that's what's going on. All I know is that it works, lol.
 

Related to Converting 2 Axis Input to an Angle

1. How do you convert 2-axis input to an angle?

To convert 2-axis input to an angle, you will need to use trigonometry equations. Specifically, you will need to use the inverse tangent function (arctan) to calculate the angle based on the x and y coordinates of the input.

2. What is the purpose of converting 2-axis input to an angle?

The purpose of converting 2-axis input to an angle is to determine the direction or orientation of the input. This is often used in robotics, gaming, and other applications where precise control and movement is necessary.

3. Can 2-axis input be converted to an angle without using trigonometry?

No, trigonometry is essential for converting 2-axis input to an angle. The inverse tangent function is specifically used to calculate angles based on two sides of a right triangle, which is the basis of converting 2-axis input to an angle.

4. What is the difference between converting 2-axis input to an angle and converting 3-axis input to an angle?

The main difference is in the number of coordinates used to calculate the angle. Converting 2-axis input only requires x and y coordinates, while converting 3-axis input requires x, y, and z coordinates. Additionally, 3-axis input allows for angles in three dimensions, while 2-axis input only allows for angles in two dimensions.

5. Is there a specific formula for converting 2-axis input to an angle?

Yes, the formula for converting 2-axis input to an angle is angle = arctan(y/x), where y is the y-coordinate and x is the x-coordinate of the input. However, there may be variations or adjustments to this formula depending on the specific application or context in which it is used.

Similar threads

  • Programming and Computer Science
Replies
2
Views
1K
Replies
2
Views
2K
Replies
20
Views
3K
  • Programming and Computer Science
Replies
1
Views
1K
  • Introductory Physics Homework Help
Replies
6
Views
3K
Replies
3
Views
2K
  • Linear and Abstract Algebra
Replies
1
Views
3K
  • Introductory Physics Homework Help
Replies
3
Views
2K
Back
Top