How to Rotate a Point 45 degrees in 2D space?

Started by
13 comments, last by Sean_Seanston 13 years ago
I want to rotate a character in a top down shooter and then figure out where the new position of their weapon should be. The weapon is offset from the character's position.

So say the character is pointing upwards and the weapon is 40 pixels from the left and 32 pixels from the bottom, how do I figure out where they should be relative to the character if the character is rotated 45 degrees?

I've drawn a few triangles but I can't quite figure it out...
I suppose it's taking a triangle like _|, rotating it 45 degrees, then finding out what the opposite and adjacent sides of a new _| triangle starting at the character's origin position would be in order to have its hypotenuse-opposite point in the same place as the newly-rotated first... but I have no idea how to do that :huh:
Advertisement
Given a vector (x,y) with magnitude m that is rotated t (theta) degrees/radians from the positive x axis, the end position of the vector is always defined by:

x = m cos t
y = m sin t

Hope that helps.

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)



x = m cos t
y = m sin t



While it may go without saying be mindful of if you are rotating using degrees or radians.
Haven't been able to get it to work...

Hmmmmmm...

Well I suppose I'm rotating around the centre of the character, so does that mean I need to find the magnitude of the vector from the centre of the character to the point, then change the offset by going offsetX = m.cos.t, offsetY = m.sin.t? Or would that not rotate around the right place? I'm quite bad at trigonometry so I may have missed something big...

But in that case, to get the magnitude of the vector from the centre to the point, could I just get the magnitude of the vector from the origin to the centre and subtract that from the magnitude of the vector from the origin to the point? With the magnitudes being the hypotenuse lengths of 2 triangles? Should rotating by 45 then have it rotated around the centre counter-clockwise by 45 degrees?

That's not working anyway when I tried it. Of course... the offset needs to be from the character's position rather than its centre... maybe that's what's going wrong? I'll experiment in the meantime.

EDIT: If the cos and sin of 45 are around 0.7... then wouldn't that mean that setting a point's x to m.cos.t and y to m.sin.t would just bring the point closer to the start of the vector if you rotate by 45?
While it may go without saying be mindful of if you are rotating using degrees or radians.

Second'd, I've actually made that very mistake before and wondered why giving something a rotational speed of "5/sec" was resulting in such wild spins.
[quote name='Sean_Seanston'] EDIT: If the cos and sin of 45 are around 0.7... then wouldn't that mean that setting a point's x to m.cos.t and y to m.sin.t would just bring the point closer to the start of the vector if you rotate by 45? [/quote]
0.7 * magnitude of the vector (aka the hypotenuse of the triangle formed by the x and y components). One dimension will likely shrink while another will grow due to 0.7 being higher than the sin or cos value of the previous rotational angle. (Try out the math with a simple case: magnitude 5, original angle 0, so vector of (5, 0). Now rotate by 45 degrees. Magnitude should remain the same after you calculate the new x and y components)

The other thing to note here, I just gave you the generic formulae for x and y components of a rotated vector. You likely need to do some pre- and post- rotation translation for the math to work properly at the arbitrary x,y value of the player. If player is at (50,50) and the gun point is at (55,50) you'll need to calculate the relative position/magnitude of the gun first, then apply the math from that relative context.

your high level code would probably look like:

gunposition -= playerposition;
gun.rotate(player.rotationAngle);
gunposition += playerposition;

or some variance thereof.

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

your high level code would probably look like:

gunposition -= playerposition;
gun.rotate(player.rotationAngle);
gunposition += playerposition;

or some variance thereof.


Hmm... checking my code, I actually did that more or less since I just took the offset of the weapon and rotated that, then added it to the character's position. So that part seems alright...

Here's my code here so far:

offsetX = x;
offsetY = y;

float m = sqrt( ( x * x ) + ( y * y ) );

float mCentre = sqrt( 32.0f*32 + 32*32 );

float mPoint = m - mCentre;

offsetX = mPoint * cos( ( D3DX_PI / 180.0f ) * 45 );
offsetY = mPoint * sin( ( D3DX_PI / 180.0f ) * 45 );

xPos = offsetX + parent->getX();
yPos = offsetY + parent->getY();


m is the magnitude of the vector from 0,0 to the point.
mCentre is the magnitude from the centre of the character (or rather, the centre if the character was at 0,0) to the point.
mPoint is then (hopefully... if I did that right) the magnitude from the centre of the character to the point, since I'm rotating around the character's centre.

If I use that, the point goes from being above the character in the centre, to being somewhere near the bottom left corner, when obviously I need it to be somewhere in the top-right to reflect the character now facing that direction.

EDIT: If the cos and sin of 45 are around 0.7... then wouldn't that mean that setting a point's x to m.cos.t and y to m.sin.t would just bring the point closer to the start of the vector if you rotate by 45?


If you asking what I think you the answer is no the distance is the same.

If the point normally is 1.0 on the Y axis and 0.0 on the X axis (0 degrees). 0.7 by 0.7 (45 deg) would be the same length. If you draw a square and then a diagonal line from corner to another you will find the diagonal line is longer than any of the other lines.

This is why the distance for a point from another is the square root of (x*x)+(y*y) (where x and y are the difference in co-ordinates of each).

If you use that formula with 0.707 for x and y you will find its roughly 1.0.
Trigonometry is extremely useful for 2D apps when rotation is involved! I recommend doing a thorough read-up on trigonometry (as well as geometry in general) before continuing, as it will help to make you a better 2D game programmer.

Also, geometry in general is useful -- for example, you might need to find the area of intersection of two rectangles (or just whether or not they intersect) for a pixel-imperfect collision engine.
[font="arial, verdana, tahoma, sans-serif"]I don't think the question has been explicitly answered. The formula for rotating a point some angle alpha around the origin is this:

new_x = old_x * cos(alpha) - old_y * sin(alpha)
new_y = old_x * sin(alpha) + old_y * cos(alpha)

The sine and cosine of 45 degrees are both sqrt(2)/2 = .7071067811865475244...

If you want to rotate around some other point, do as BCullis said: subtract the center of rotation, then rotate around the origin, then add the center of rotation back.
[/font]

It's easy to remember all the trigonometry you need to know if you know how to use complex numbers.

Here's my code here so far:

offsetX = x;
offsetY = y;

float m = sqrt( ( x * x ) + ( y * y ) );

float mCentre = sqrt( 32.0f*32 + 32*32 );

float mPoint = m - mCentre;

offsetX = mPoint * cos( ( D3DX_PI / 180.0f ) * 45 );
offsetY = mPoint * sin( ( D3DX_PI / 180.0f ) * 45 );

xPos = offsetX + parent->getX();
yPos = offsetY + parent->getY();


m is the magnitude of the vector from 0,0 to the point.
mCentre is the magnitude from the centre of the character (or rather, the centre if the character was at 0,0) to the point.
mPoint is then (hopefully... if I did that right) the magnitude from the centre of the character to the point, since I'm rotating around the character's centre.

If I use that, the point goes from being above the character in the centre, to being somewhere near the bottom left corner, when obviously I need it to be somewhere in the top-right to reflect the character now facing that direction.


I think you're making it overly complicated with the additional magnitude calculations, (which won't do what you need anyway since a magnitude is directionless). All you should need to do is find the relative x and y of the gun. This means subtracting the player position vector from the gun vector, doing rotation, then adding back the player position vector to the newly modified gun vector.

Depending on the rest of your code, you should be able to keep the values of your gun vector separate, meaning store the gun vector as its relative values (say, 5,0 if the game starts out with the player facing right) and then do all the rotations internal to that vector. Then when you draw the player and gun, simply draw the gun at playerPosition + gunPosition.

(Keep in mind this is all very off-the-cuff, I prefer to implement a geometric vector class if the API doesn't already have one)

class Gun{
...
float xPos, yPos, magnitude;
...
void rotate(float);
...
};

Gun::Gun()
{
xPos = 5; yPos = 0;
magnitude = sqrt(xPos*xPos + yPos * yPos);
}

void Gun::rotate(float angle)
{
xPos = magnitude * cos(angle);
yPos = magnitude * sin(angle);
}

//later
//draw gun at ((player.xPos + gun.xPos),(player.yPos + gun.yPos))


tl;dr: try keeping all your vectors defined in their local context (i.e. as if they were beginning at the origin) and just add them together for position-related draw calls. Makes the rest of the math a lot simpler.

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

This topic is closed to new replies.

Advertisement