Negative Angles and Rotation

Today I tried to figure out how to use joystick for input for Killing Horizon.  Last weekend I talked with a friend of mine and he thought that, apart from a spinner, a joystick seems the most natural control interface for the game, what with a 360 rotation around a circle and all (compared to a simple left-right motion with the mouse – which works fine for me, but everyone else whose used the mouse to control has had issues).

So the first issue is a mostly solved issue which is you have to convert the values of a joystick to angles.  You have two axes which go from 0 in the center to +1 at the highest value to -1 at the lowest.  On the X axis, this means pushing the joystick all the way to the left gives you -1 and all the way right gives you +1, and then floating point values between them for where you are on that line (.9, .85, -.3, -.777, etc…), and the same goes for the Y axis – Up is positive, Down is negative.

In order to convert the values, you have to take the arctangent of y over x and use the radians to degrees function of Unity’s Mathf functions.

 

Sorry for the shitty code formatting, for some reason WordPress insists that their code tag surrounds text that has no spaces between the lines, and I’m not going to be arsed to mess with it.

Now, this code in itself is kinda screwy beyond just the weird if statements and such – the actual “rotatearound” code is still from my old mouse controls (left-right) so all that’s doing right now is moving the ship as fast as the given angle is (that is, if I have angle 1, the ship is moving at 1 unit per time, and if I have the stick at 359 degrees, it’s moving 359 units per time (this isn’t angle rotation, I don’t believe, though it might be… I think the deltaTime is making it slowdown so it’s not actually moving 359 degrees)

OK, so you see the a = mathf.round stuff.  That’s what I talked about in the first part.

The problem lies in the fact that when do the conversion to angles, you end up with values that are negative for the bottom half of the circle.  It goes like angle 0 is the furthest right on the x axis (and 0 on y axis), and furthest left (-1) on the x axis and 0 on the y axis (i.e. center vertical) gives 180.  So far so good, but what happens if you push the stick down just a bit more?  You would think it would go to 181, then to 182 and so on until you cycle back to 359 right below 0, but you would be wrong!

It goes from 180 to -179, and all the way to -1.  Essentially it is the inverse of the top, a mirror image as it were.  At first this stumped me until I thought it through.  The first solution was to subtract the absolute value of the wrong numbers from 180 and then add 180 to it.

Example: |-179| = 179; 180-179 = 1; 180+1 = 181.

Well, subtracting the absolute value of a negative number is really just adding that number to the other value (180 + -179 = 180 -179).  I wouldn’t need to do any absolute value crap, just add the value to 180 which would then give you the value you need to add to 180 again.

But then I realized I’m adding 180 twice, and so simplify it to 360+negative_angle_value and that is what you need to obtain the proper angle if you continue past 180. 360-179=181

It was really easy once I typed it out to figure out what to do.  So what seemed complicated at first was really as simple as:

angle = 360+a — where a = Mathf.Round(Mathf.Atan2(y, x) * Mathf.Rad2Deg).

So I’m one step farther and it didn’t take that long once I put my mind to it.

Black Box Action and Architecting Killing Horizon

One of the main concepts I’ve taken with me from my High School programming class (Pascal Represent, yo!) is that you can think of computing as a chain:  Input->Process->Output.

This is really, when you think about it, what you do with a computer, that’s all.

You input information, whether it be hand-typed data fields, punch cards, scanned barcodes, joystick position, audio commands into a microphone, a guitar riff into the computer’s audio card…

This input can be acted on in realtime or stored onto some media format (Compact Disc, Flash Drive, Hard Drive, etc…)

The computer then takes this information, whether realtime or stored and loaded, and then performs a process which is what we call a “program” and then outputs something.  It might be a black screen, it might be a video game, it might be bolding a text, it might be hearing that mp3 you just got of your favorite artist, it might be to another file in a different format from the one you just opened).

So you have Input, Process, Output.  I mentioned input and output.  Now, as for process, it’s important to understand what that is.  We can call it a “function” or “procedure” (function is a common term, but subroutine and procedures are also terms of art depending on the language, and I’m sure there are other terms I can’t think of right now).

Up to now, I have been trying to abstract things in various ways, using metaphors of the objects and what they do.

And that’s an important part of the black box.  You need to create a model of this THING you are building.  Furthermore, the model must create specifications on the input, planning for all the type of information it may receive, and in a well coded environment, be ready to catch input that is not capable of being processed.  The function, this black box, then does the process, whatever it is, and then outputs something.  I should note that an output can also be directly into another blackbox so more processing can be applied.  A long chain of this can happen before the user sees a result.

But in my planning, I have been thinking about the process.  The models of the objects, the things to do, but I have not actually sat down and just said : Here is what happens.

That is: INPUT.

I think my next mode of architecting will be to sit down, list the basic concepts from a high level: ship, asteroids, black hole, etc… (this includes things like the score system, the wave system, etc…) and focus on what is counted as “input” to an object, and what I want to happen (the process) and finally deal with how that is output to the user or the system.

Instead of diving vertically into a given system I just am going to write the list of what happens with the user:

“click left mouse: shoot currently selected ‘gun'”

“click right mouse button: launch currently selected ‘explosive'”

“click middle mouse button: activate currently selected special power”

“scroll mouse button up/down: cycle between given weapons in a particular power slot type (gun, explosive, special power).”

etc etc etc…

Remember, however, that input itself is not necessarily confined to the user’s input but also input from the system.  For example, to create my asteroids and have them fly in to the center of the screen, I’ll have a wave system that spawns the asteroids, and then apply force to make them move:

“check wave and other variables that influence on whether to launch an asteroid-> do some mathy stuff to figure out whether can spawn, where from, how hard, etc…-> “yes, I can launch asteroid”-> asteroid launches”

The input here then is other variables in the system overall, not anything the user does, necessarily.

So, instead of diving vertically into the objects and their methods and how they act.  I’m going to work horizontally.  Get a broad based view on what I want to happen.  This can be seen as “Strategy” vs the “Tactics” mode of drilling down to the battlefield of work where the actual processing and action takes place.

This is a form of abstraction as well, but at a higher level, and is done via the InProcOut loop.  Once I get the basics down, I can stat de-abstractifying by drilling down a layer in each type of object, and write skeletal structures of the methods (function) that they do.  Then the implementation of that is left.

Since a good portion of work has already been done on some algorithms, a lot of the implementation on the actual process at that function/method level has already been done.  It’s making sure it’s organized logically, consistently and that things plug in and play nice together with expected inputs and outputs.