Setting the thrust position on a moving and rotating object

Go To


I have a spaceship, that spaceship moves though space 360 Degrees.

The spaceship needs thrust animation in 2d. The trust animation needs to be at the bottom middle line of the spaceship. I have the following variables.


I've uploaded an image of my problem too in-case people don't understand my bad explanation:

Both animation render like so:

this._itemAnimation.render(this.getPosition(), canvas, this._degrees);
this._thrustAnimation.render(this.thrustPosition(), canvas, this._degrees);

I have tried so far and failed:

_thurstPosition.set(((int)_object_x + Math.cos(_degrees) * _itemAnimation.getWidth() / 2) , 
((int)_object_y + Math.sin(_degrees) * _itemAnimation.getWidth() / 2));

I'm fail, somebody help me.

--- UPDATE ---

I've updated the code so it's better understood:

    int SpaceshipCenterX = getPosition().x + (_SpaceshipAnimation.getWidth() / 2) - (_thrustAnimation.getWidth() / 2);
    int SpaceshipCenterY = getPosition().y + ((_SpaceshipAnimation.getHeight() / 2) - (_thrustAnimation.getHeight() / 2));

    double OffSetCos = Math.cos(_spaceshipDegrees);
    double OffSetSin = Math.sin(_spaceshipDegrees);

        (int)(SpaceshipCenterX + (SpaceshipAnimation.getWidth() / 2) * OffSetCos)
        (int)(SpaceshipCenterY + (SpaceshipAnimation.getHeight() / 2) * OffSetSin)

I still can't get it too work. It's going around the spaceship but very fast and flashing everywhere.

--- UPDATE 2 ---

This is almost working but it's going too far out:

    int xOffset = -1 * (_itemAnimation.getWidth() / 2);
    double DegreeToRadien = Math.toRadians(_degrees);

        (int)(((xOffset) * Math.cos(DegreeToRadien)) + getPosition().x),
        (int)(((xOffset) * Math.sin(DegreeToRadien)) + getPosition().y)
2012-04-04 19:44
by Oliver Dixon


double DegreeToRadien = Math.toRadians(_degrees);

    int ObjectXCenter = (int) (_object_x + ((_itemAnimation.getWidth() / 2)) - _thrustAnimation.getWidth() / 2);
    int ObjectYCenter = (int) (_object_y + ((_itemAnimation.getHeight() / 2)) - _thrustAnimation.getHeight() / 2);

    int xOffset = -1 * (_itemAnimation.getWidth() / 2);

        (int)(((xOffset) * Math.cos(DegreeToRadien)) + ObjectXCenter), 
        (int)(((xOffset) * Math.sin(DegreeToRadien)) + ObjectYCenter)
2012-04-05 18:46
by Oliver Dixon


Assuming that you are using this coordinate/angle system:

                90 (pi/2) - Up
Left - 180 (pi) <----|----> 0 - Right
            Down - 270 (3pi/2)

And that your spaceship is going to the right at 0 degrees

>[ } 0

Then for any direction you need to translate the thrust relatively from the centre of the spaceship, let's say we translate in the x direction by

offset = -1 * width/2;

Then rotate it by the angle of the spaceship and finally translate it by the position of the spaceship.

To compute this transformation, write out the 3 transformations as matrices in reverse order and multiply them out, transforming a point starting at (0,0)

   [1 0 spaceshipX] [cos(dir) -sin(dir) 0] [1 0 -width/2] [0]
   [0 1 spaceshipY] [sin(dir)  cos(dir) 0] [0 1     0   ] [0]
   [0 0     1     ] [   0         0     1] [0 0     1   ] [1]

So that would give you the position of the thrust as

thrustX = (-width/2)cos(dir) + spaceshipX
thrustY = (-width/2)sin(dir) + spaceshipY

So I suppose you just missed the fact you need to subtract width/2, not add it.

I've edited this with a correct and more readable syntax. Using underscores everywhere really hurts readability. I am assuming you have a spaceship class, and the spaceship has a width, height, x position, y position and rotation. You have a thruster class which also has a width, height, x position, y position and rotation. (They could inherit from a Sprite abstract class). To set the position of a thruster object we call thruster.setPosition(x,y);

int xOffset = -1 * (spaceship.width / 2);

    (int)(((xOffset) * Math.cos(spaceship.rotation)) + spaceship.x), 
    (int)(((xOffset) * Math.sin(spaceship.rotation)) + spaceship.y)

Hopefully this makes it obvious to you which values you need to be setting where. I can't decipher your code without seeing more of it, where these variables are declared and what they actually mean.


Just to conclude, as I think you may have discovered. Math.cos and Math.sin require angles to be in Radians, not degrees. The solution I have given here is correct, and I have shown how you compute the position of any relatively positioned object by performing the matrix calculation. You just have to remember that spaceship.rotation must be in radians or you must translate it to radians from degrees before passing it to Math.cos() or Math.sin().

int xOffset = -1 * (spaceship.width / 2);
double radians = Math.toRadians(spaceship.rotation);

    (int)(((xOffset) * Math.cos(radians)) + spaceship.x), 
    (int)(((xOffset) * Math.sin(radians)) + spaceship.y)
2012-04-04 20:58
by Matt Esch
Thanks for your reply I've read it carefully. I've adjusted it as you've said but still having problems, now the thrust just appears in a straight line! down the middle of the screen.

I used:

int xOffset = (int)_object_x * (_itemAnimation.getWidth() / 2);
< - Oliver Dixon 2012-04-04 21:25
I noticed I forgot to update the last line properly. I've corrected it. I'm not overly sure what each of your values means, so I have updated that as well to look like your original syntax. xOffset has to be negative half the length of your spaceship. This length does not change regardless of the rotation. it's fixed. I've updated the answer to hopefully make it clear what needs to be set to what. I am assuming that sprite is positioned from the centre - Matt Esch 2012-04-04 22:10
That code still isn't working. I've added an update to my code so it might be better understod? Thanks for helping me by the way. Still not working though :- - Oliver Dixon 2012-04-05 17:10
Updated the answer to fall in line with what was probably your issue (radian/degrees issue) - it's an easy trap to fall into - Matt Esch 2012-04-05 20:09


Your code looks close to me. You need to be careful about what _degrees means. If _degrees is the direction in which the rocket points (counterclockwise from the +x axis), then you'll need to put some minus signs in there because the thrust is at the back of the rocket, not the front. Also, I would think the thrust is on the height end of the rocket, so use getLength instead of getWidth. You may need to add some extra for the height of the thrust animation as well (depending on where its anchor is). So something like

_thurstPosition.set(((int)_object_x - Math.cos(_degrees) * (_itemAnimation.getHeight() / 2 + _thrustAnimation.getHeight() / 2)) , 
((int)_object_y - Math.sin(_degrees) * (_itemAnimation.getHeight() / 2 + _thrustAnimation.getHeight() / 2)));

You'll also need to set thrust orientation if it isn't a circle.

(I'm assuming _degrees == _Rotation)

2012-04-04 19:56
by Keith Randall
I tried your method, I get some werid spazzy effect (Thrust appearing in many places at once). _degrees is the current Rotation of the spaceship, I was hoping I could use both for thrust and spaceship, is that correct? I use width because for some reason Android renders sprites facing sideways as up - Oliver Dixon 2012-04-04 20:01
@OllyDixon Degrees needs to be converted to radians: Math.toRadians(_degrees)Pilot_51 2013-06-22 21:15