Rotating a ship about an offset point

Hey guys this is rather tricky to explain but I will try my best.

Basically I am making an asteroids game and I have built the basic structure of the game. Now I am working on getting the ship to fly around the level. I have a Ship class which stores the x and y positions as well as the current direction it is facing.

Within my draw() function, I need to draw the ship at the designated point. Only problem with this is that when I rotate the ship using the arrow keys, it rotates from the top part of the ship (which is currently just a triangle). I need it to rotate in the middle (or more accurately to draw it from the middle of the ship to give that illusion).

At the start it draws it fine ( http://img696.imageshack.us/img696/5055/shipstart.png ), but after rotating the ship anticlockwise a certain amount of degrees you can see the end effect is not what is desired ( http://img848.imageshack.us/img848/7332/shipangled.png ).

I want it to still be in the original circle (which is to be its bounding box) but at the angle as shown in the second picture.


This is my code so far for drawing the ship:

1
2
3
4
5
6
7
8
9
10
11
12
void Ship::draw()
{
	//offset values
	int xOffset = 0;
	int yOffset = -30;

	//draw ship
	drawing.drawFilledArc(xPos,yPos+yOffset, 50, utility.degToRad(direction-25), utility.degToRad(direction+25), 10, sf::Color::Cyan);

	//draw bounding box
	drawing.drawArc(xPos, yPos, 30, utility.degToRad(0), utility.degToRad(360), 100, 1, sf::Color::White);
}



The drawing.drawFilledArc is simply a function to draw a circle (arc) using a number of triangle with a start and end point in radians.

Any help with this would be greatly appreciated, thank you.

EDIT: corrected a spelling in my code
Last edited on
I really just get 404's from those links.

Anyways, 2D rotation around coordinate center is
x' = y * sin(ang) - x * cos(ang)
y' = y * cos(ang) + x * sin(ang)

For a rotation around an arbitrary point, you'd just have to translate the coordinates accordingly. I am not really sure what library you are using, so I can't get specific with how to do this in your program.
Ok so I tested the code above, and these are the resulting pictures:

Starting position - http://img560.imageshack.us/img560/5055/shipstart.png
Position after rotation around a few angles ac - http://img858.imageshack.us/img858/7332/shipangled.png

They seem to be rotating around somewhere outside the window (when I make a circle rotation, they rotate out of the screen and back in.

The code I am using is:

1
2
3
4
5
6
7
8
int shipX = yPos * sin(utility.degToRad(direction)) - xPos * cos(utility.degToRad(direction));
int shipY = yPos * cos(utility.degToRad(direction)) + xPos * sin(utility.degToRad(direction));

//draw ship
drawing.drawFilledArc(shipX, shipY, 20, utility.degToRad(direction-25), utility.degToRad(direction+25), 10, sf::Color::Cyan);

//draw bounding box
drawing.drawArc(xPos, yPos, 30, utility.degToRad(0), utility.degToRad(360), 100, 1, sf::Color::White);
Last edited on
You should store the ships coordinates as the coordinates of the centriod of the triangle. Then you can easily rotate about the centroid.
Yeah but I have no idea on how to do that. Because as soon as I set the coords to the triangle centre, the triangle redraws itself using them coords so it becomes useless.
assuming all the logic is correct :
the process of rotation is :
1. translate a line to origin. (i.e. one of the end points of the line segment).
2. rotate it by the angle you want
3. translate it back to the point it was on.

the second time you posted your png's, i think was because of lack of this.

also when your class saves x and y positions, which x and y are those, centroid or circumcenter ?

you should make use of the centroid and the three points or triangles. it would be easiest if you can get an equilateral triangle. then only with direction and centroid, you can get all three points. and hence all three line segments. after that the three TRT' transformations will have to be applied.

If you are drawing the triangle using an arc, you have the center of the arc, if you can change that angle from -20, 20 to -30,30 you have an equilateral triangular arc. so you can find the centroid of the arc which is also its circumcenter and hence the bounding box can be drawn using that circumcenter and circumradius which can be, again, found easily in case of equilateral triangle.

Last edited on

you'd just have to translate the coordinates accordingly


means :
1) get the x/y coordinates
2) translate the coordinates so the point you want to rotate around is in the coordinate center
3) apply the rotation
4) translate the coordinates back

ex: you have a triangle consisting of the points A(2/4), B(2/2) and C(2/3) - you want to rotate around B, with an angle of 90 degrees.
to do that, you first define 2/2 as the coordinate center - to translate the coordinates, just substract the vector 2/2 from all your points. So the translated coordinates are
A(0/2), B(0/0) and C(0/1).
You calculate the new coordinates with the formula I gave you earlier.
You have the points A'(2/0), B'(0/0) and C'(1/0) now.
Now you just add the vector 2/2 you substracted earlier again, and have the final coordinates
A''(4/2), B''(2/2) and C''(3/1).


Oh, and of course that only makes sense if you're actually doing the drawing yourself with primitives. If you draw a Bitmap, you better use your libraries built-in functions to it - drawing a bitmap pixel per pixel is terribly slow.

EDIT: Added ' s to the points to mark them as distinct points.
Last edited on
Cheers guys got it :)
Now I am intrigued - did you use the rotation maths I gave you or did you find a library function that did what you wanted?
In all honesty, I used the rotation maths you gave which navderm gave as a summary, got it working then realised I should be using a sprite anyways so used the SFML library to draw and rotate the sprite in place.

So a bit of both XD
Topic archived. No new replies allowed.