I'm going to mumble about my "aha!" moments and ponderings as I remember them and when they have some kind of point to them. I don't guarantee a good quality, just like I never do ;)
Position, rotate, relocate, drawSo my first version used a set of hardcoded coordinates, yay! I thought that it's a good starting point, but oh, how wrong I was. Maybe the issue was within my own rotation methods and it'd all been awesome if my methods had been fine, but maybe it would've sucked anyway. The initial situation was rendered prettily but a single rotation distorted the form beyond recognition.
Via the zero pointFrom somewhere I came up with an idea (and after talking to a yet another coworker of mine my guess was proven correct) where all the shapes should always be initialized around the (0,0) point. This way the rotation of any polygon would work the same no matter where on the 2d space they are.
So first you always set up the vertices in the same places, then shift the coordinate points to the actual positions where they'll be rendered on the screen. A really simple and I guess it's a childishly basic thing, but who would've told me?
Rotating the 2d coordinatesMy mathematical studies are years old at best and I have to admit that in elementary school (even longer ago) I was one of those fucking annoying brats who declared that I would never need maths or trigonometry after the 9th grade. Oh yeah, once again we see that reality doesn't always agree :)
After a couple of weird and stupid "I'll do this myself"-kind of attempt I encountered something called affine transformation. That was a nice, handy thing and the implementation was just about 1:1 with what my dear friend Wikipedia told me. You just drop it each vertex of the polygon at a time and the desired rotation angle (obviously this is always the same for a single shape), this beast simply returns the new coordinates for the given vertex.
def rotate(self, angle):
rotated_points = 
for point in self._points:
new_point = self.affine_transform(Vector(point.x, point.y), angle)
def affine_transform(self, point, angle):
temp_x = ((point.x * math.cos(angle)) + (point.y * math.sin(angle)))
temp_y = ((-point.x * math.sin(angle)) + (point.y * math.cos(angle)))
return Vector(temp_x, temp_y )
Hah! The next issues I encountered were the angle (I was, again, making a mess with degrees and radians, but that was because of my infinite stupidity) and the movement. The movement was a bigger issue and took quite a bit longer to fix. Pretty soon I was able to rotate my more-or-less-triangular shape around it's own z-axis but if I tried to accelerate, it started flying towards the top-right corner and beyond. If I tried to rotate and accelerate, it did the same but while corkscrewing carelessly. I was baffled.
How do I calculate where my polygon is facing?As my stupid mistake number 74 I forgot my hardcoded "draw this thing in the middle of the surface" -values and another mistake was that the calculate_angle always returned the exact same value for my Object. Somehow I had ended up trying to calculate the facing of my polygon by its sides (because it's basically a triangle). I guess it was otherwise a good idea but it just didn't work here at all.
After a bit of googling and more light headscratching the solution was much more simple than I had thought. Or at least it felt like it for someone as stupid as I am. Because the center point's coordinates are known, as well as the tip's coordinates, you can just take the distance between the coordinate points on x and y axises (Δx and Δy) and feed that to arctan to get the angle in radians.
|I guess that clarifies a bit... or not :p|
def calculate_angle(self, center, nose):
dx = center.x - nose.x
dy = center.y - nose.y
radian_angle = math.atan2(dy, dx)
Geniously simple, I say. At this point it looks like that no one can read one word more of this crap on one go. Therefore I'll continue this topic on the next iteration of the Project Mumblings.