Guri
Guri

Reputation: 21

A function for spinning objects around a center point

I am trying to code a game in C++ using SFML, in which several space ships attack a planet from different sides. I want the space ships that attack the planet to face the planet while they attack (obviously). The problem I am having is figuring out a formula that would work for every x and y position. If the sprite for the ship starts off by facing upwards, what would be the best way to approach this?

For example, if the ship spawns on the right side of the planet, the ship sprite should rotate to the left, towards the center of the planet.

Upvotes: 0

Views: 1117

Answers (2)

Lutz Lehmann
Lutz Lehmann

Reputation: 25992

Denote the position of the planet as (xP,yP) and the position of the ship as (xS,yS) with its point facing upwards, direction (0,1)' (the prime denoting transposition to a column vector). To have the ship pointing at the planet, we need it pointing in the opposite direction of the difference vector

(x,y) = (xS-xP, yS-yP).

More precisely, the normalized direction of the point should be (-x/r,-y/r)', using r=sqrt(x^2+y^2). The rotation of the direction vector (0,1)' to (-x/r,-y/r)' is performed using the rotation matrix

( -y/r  -x/r )   ( 0 )    ( -x/r )
(  x/r  -y/r ) * ( 1 ) =  ( -y/r )

for the convention matrix-vector-product. If it is vector-matrix product, use the transpose of it.

Use that if specifying the matrix directly. When using rotation angles, the angle of that rotation is atan2(x,-y) in radians.

Upvotes: 0

bames53
bames53

Reputation: 88155

Below is the math for rotation, which is what you seem to be asking for, however you're probably better off simply using SFML's api for rotating entities: http://www.sfml-dev.org/tutorials/2.0/graphics-transform.php.


Rotating a point around the origin can be represented as a matrix multiplication with the following matrix:

[[ cos(a), sin(a), 0],
 [-sin(a), cos(a), 0],
 [      0,      0, 1]]

where a is the angle to rotate by.

(This can be derived from the trig identities cos(a)sin(b) + cos(b)sin(a) = sin(a + b) and cos(a)cos(b) - sin(a)sin(b) = cos(a + b))

Translating a point so that it is positioned where you want to rotate relative to the origin can also be represented as a matrix multiplication, and of course translating it back can be as well.

To translate a point by a in the horizontal direction and b in the vertical direction you multiply your point [x, y, 1] by the matrix

[[1, 0, 0],
 [0, 1, 0],
 [a, b, 1]]

This produces the matrix [x+a, y+b, 1], which is the translated point (x+a, y+b).

To translate a point in preparation for rotation around a point (Cx, Cy), you first translate it by -Cx in the horizontal direction and -Cy in the vertical direction. The matrix for that is [[1, 0, 0], [0, 1, 0], [-Cx, -Cy, 1]]. After the rotation you translate by the same amounts in the opposite directions, which is the same as multiplying by the inverse matrix: [[1, 0, 0], [0, 1, 0], [Cx, Cy, 1]].

Say your initial point is p, a matrix A translates it to be relative to the origin for rotation, a matrix R rotates about the origin. Then your rotated point is

((p × A) × R) × A-1


Since matrix multiplication is associative you can rearrange this to:

p × ((A × R) × A-1)

Which means you can compute the matrix ARA-1 and then multiply any point by that matrix to rotate that point around a common center. So for each object you want to rotate, compute the matrix that rotates points around the object's center point, and then rotate every point of that object using the matrix.

When you combine the translation matrices with the rotation matrix you get a single matrix:

[[                         cos(a),                          sin(a), 0],
 [                        -sin(a),                          cos(a), 0],
 [-cos(a) * Cx + Cx + Cy * sin(a), -cos(a) * Cy + Cy - Cx * sin(a), 1]]

Multiplying a point (x, y) by this matrix produces a point with the x coordinate:

x × cos(a) - y × sin(a) + (-cos(a) × Cx + Cx + Cy × sin(a))

and the y coordinate:

x × sin(a) + y × cos(a) + (-cos(a) × Cy + Cy - Cx × sin(a))


To try this out, say we want to rotate points around (1, 1). If we rotate the point (2, 1) by pi/2 (90° counter clockwise) we should get the point (1, 2), and rotating the point (2, 1) should give us (0, 1).

Plugging in the coordinates (2, 1) and the angle pi/2 into the equation for the rotated x coordinates produces:

2 * cos(pi/2) - 1 * sin(pi/2) + -cos(pi/2) * 1 + 1 + 1 * sin(pi/2) = 1

and plugging them into the equation for the y coordinate produces:

2 * sin(pi/2) + 1 * cos(pi/2) + (-cos(pi/2) * 1 + 1 - 1 * sin(pi/2)) = 2

Which means the point (2, 1) rotated 90° around (1, 1) is the point (1, 2), just as expected.

Then pluggin in the point (1, 2):

1 * cos(pi/2) - 2 * sin(pi/2) + -cos(pi/2) * 1 + 1 + 1 * sin(pi/2) = 0

2 * sin(pi/2) + 1 * cos(pi/2) + (-cos(pi/2) * 1 + 1 - 1 * sin(pi/2)) = 1

produces the point (0, 1) which is, again, just as expected.

Upvotes: 1

Related Questions