This might, perhaps, be more suited to Stack Overflow or the Gaming section, but since it's math that is above my head, I thought I'd come straight here for it.
I'm making a space game. So far I have a spaceship that has a maximum velocity (kept in check by a function that finds the hypotenuse of the triangle made by its vx and vy and ensures that the length of the hypotenuse never surpasses the max_speed), and proper acceleration implemented (as well as proper tracking of angle of rotation in order to generate the vx and vy values). It flies quite nicely. What I'm having trouble with is finding the current angle of motion, as opposed to the current angle the ship is facing.
I know that, for a right triangle, I can find the theta (angle/slope) by calculating the arctangent of the length of the opposite side divided by the length of the adjacent side. In my game, this translates to: Math.atan(vy/vx). The only problem is that it only outputs a result between -90 and 90. I know that's how it's supposed to work (based on what I know about the unit circle, etc.), and so I'm stumped. I can't seem to figure out a way to do what I need to do.
Here are two specific examples of troublesome results: -when vx is 1 and vy is 1, I get atan(1) = 45 -when vx is -1 and vy is -1, I get atan(1) = 45
And so therein lies the heart of the issue. The ship could be moving in the exact opposite direction and it would give me the same angle.
I was thinking of writing a function to modify the output depending on which quadrant the motion was facing. For instance: if vx and vy were both negative, then the angle should be between 270 and 360, or if they were both positive, between 90 and 180. The only issue is the reflection of the result across the axes. I rotate clockwise from 0 degrees, and it counts down from 90 to 0, then down to -90 when I reach the 180 mark, then back up from -90 to 0 as I approach 270, and from 0 to 90 as I pass 270 and on to 360.
Is there any formula I can use, into which I can input my current x speed and y speed, and receive the angle, between 0 and 359 (or 1 and 360, whichever works)? By the way, for my purposes, 0/360/2pi is oriented directly up, 12 o'clock, facing the top edge of the screen.
I have looked all over Google all day long for "rigid body dynamics," "kinematics," and any of a number of other keywords I could think of or find to help find a viable solution -- and I have read countless articles and forums threads about related subjects -- but it appears as though nobody has ever asked or answered this question on the internet (I'm sure it's out there someplace and I'm just too dense or unlucky to find it).
I have read these, too:
This one almost answered my question, but I'm not entirely sure how to work with it:
I tried implementing the last suggestion from that thread like so: reverse_angle = roundNumber(radToDeg(Math.cos(vy / (Math.sqrt((vx * vx) + (vy * vy))))),0); but it just gave me angles between 0 and 90, which really wasn't too helpful.
To simplify the question, I'm basically looking for a way to turn the ship to face exactly opposite its current vector, so I can simplify the deceleration process (which I will put to use in the AI when I get to that part, but it's also part of the control scheme: pressing the down arrow reverses your angle as a form of deceleration autopilot to help newbies adjust to unassisted 2D Newtonian spaceflight).
Oh, my. Look at the time. I have to wake up for work in four hours. Goodnight for now!
Thank you very much.
...and here's my current project with the changes in place:
There is still a bug in the max_speed section of the code, which I hadn't noticed before, but I'll work on that in my own time, or maybe post it to stackoverflow, since it doesn't really belong here. This bug happens when you're accelerating in any given direction, and then rotate while accelerating. Somehow the ship's speed escapes the boundaries I placed on it, and then there is no way to get the speed back below the maximum. Oops. :P