Happy to explain. I am self taught. In my experience, most of the available online resources (wikipedia, wolfram, etc.) are a little too detailed for the basic things you need to know for 2d graphics programming.
A Google Search of Polar Coordinates will provide an overwhelming amount of information, but I'll provide the salient details here. The velocity is a coordinate pair, and can be represented thusly, as cartesian coordinates.
Any set of cartesian coordinates can also be represented as an angle (a), and the distance from 0,0 (the origin of the two axes). (d,a) are called polar coordinates. The "pole" is 0,0, the center of the imaginary circle shown in the figure. D is not only the distance from the 0,0, it is also the radius of the circle. a is the angle from the x-axis.
Here is the formula to convert cartesian to polar coordinates:
d = sqrt( x*x + y*y); or in processing d = dist(x,y,0,0);
a = atan2(y,x);
Here is the formula to convert polar coordinates to cartesian:
x = cos(a)*d;
y = sin(a)*d;
This is pretty much all the trigonometry you need for basic 2d graphics - you can accomplish a lot with dist,atan2,sin and cos.
So, let's look at what I'm doing. I start with your velocity vector v, which has (x,y) components. I first convert those to polar coordinates.
- float d = dist(v.x, v.y,0,0);
- float a = atan2(v.y,v.x);
Now I have this value a, which is expressed in radians (which go from 0 to 2PI). I change it to a value that goes from 0 to 1 (I "normalize" it).
a = a/TWO_PI
Normalization makes it easier to make it go from 0 to 8 (units=8) I can simply multiply it by units (8).
a = a * units
Then I round it to the nearest integer. If a is 5.12, I just want it to be 5, so that we get 8 discrete directions.
a = round(a)
Then I convert it back to 0 - 1..
a = a / units;
To make it easier to convert back to 0 to TWO_PI (radians)
a = a * TWO_PI;
Since the preceding 5 lines were all successive operations on A, I was able to condense it to a single line:
a = round(a*units/TWO_PI) * TWO_PI/units;
Then I convert a,d back to cartesian coordinates.
return new PVector( cos(a)*d, sin(a)*d );
That's basically it. In the demo code, I am also using polar coordinates to produce a line that is 100 pixels long, and pointing from the center of the screen, towards the mouse.
- float d = 100;
- float a = atan2(mouseY-width/2, mouseX-height/2);
- PVector v = new PVector(cos(a)*d, sin(a)*d);
Hope this helps!