Moving Direction based on sprite rotation [SFML]

I'm trying to make my sprite move in a direction based on its rotation, for example if its rotation angle is at 0 (default) and you press W, the sprite moves up, if the angle is at 90 and you press W, you move right, 180 is down, 270 is left, etc.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void move(std::vector<sf::Texture> &Textures, std::vector<sf::Sprite> &Sprites)
{
    if (Player.isMovingVertical())
    {
        if (Player.isMovingUp() && Sprites[0].getPosition().y >= 0)
            Sprites[0].move(0, -1 * Player.getSpeed() * ElapsedTime);
        else if (!Player.isMovingUp() && Sprites[0].getPosition().y + Textures[0].getSize().y <= Height)
            Sprites[0].move(0, Player.getSpeed() * ElapsedTime);
    }

    if (Player.isMovingHorizontal())
    {
        if (Player.isMovingRight() && Sprites[0].getPosition().x + Textures[0].getSize().x <= Width)
            Sprites[0].setRotation(Sprites[0].getRotation() + (float)Player.getSpeed() / 2.f * ElapsedTime);
        else if (!Player.isMovingRight() && Sprites[0].getPosition().x >= 0)
            Sprites[0].setRotation(Sprites[0].getRotation() + -1.f * (float)Player.getSpeed() / 2.f * ElapsedTime);
    }
}


the rotation works fine, but moving is the problem, I've tried a few different things but they've yet to work, any suggestions?
If, when angle = 0, you'd move in the direction of vector v, in general case, when angle = theta, you'd move in the direction of vector R(theta)*v. Here R(theta) is a rotation matrix:
cos theta    -sin theta
sin theta     cos theta
Last edited on
thanks, but that is about 3 miles above my knowledge of maths, add or take a few thousand intergalactic space slugs.
If you have a vector v and an angle theta, Vector(v.x * cos(theta) - v.y * sin(theta), v.x * sin(theta) + v.y * cos(theta)) is the same vector, rotated by theta. Note that sin and cos from <cmath> both take angle in radians but getRotation returns degrees. 1 radian is 180/pi degrees. Also, I'm not sure whether this will be clockwise or counterclockwise. Test it and add "-" to theta if needed.
Last edited on
Okay, most of that makes sense to me except the Vector and v.x and v.y, is Vector my movement function and v.x and v.y the position of my sprite?

I tried messing around with sin and cos, when rotating while holding W it makes a pattern sort of like a frequency, although going upwards rather than sideways.

 
Sprites[0].move(std::cos(3.14159265 * Sprites[0].getRotation() / 180.f) * (float)Player.getSpeed() * ElapsedTime, std::sin(3.14159265 * Sprites[0].getRotation() / 180.f) * (float)Player.getSpeed() * ElapsedTime);


this works, but it seems to be off by 90 degrees, when moving up while rotation is at 0, the sprite moves right, I've tried several ways of changing it but no luck.
Last edited on
A vector is basically a pair of numbers (x, y) representing how much you want to move along each axis.
If you only care about UP key, you can write 0 instead of v.x and -1 instead of v.y.
In general, if the rotation is 90 degrees wrong, try swapping sin and cos. If it is 180 degrees wrong or to the wrong side, try adding or removing minus signs before them.
Hamsterman is correct, although he's getting into more detail than you probably need. You likely don't need to do a full rotation matrix just to orient your vector.

The math is actually very simple:

1
2
3
4
5
6
7
double speed = 5;  // speed at which the player is moving
double angle = 60 * PI / 2;  // angle, in radians, that the player is facing
   // note:  angle 0 is due east, not due north.  Rotates counter-clockwise,
   //  so angle 90 degrees is due north.

double move_x = speed * cos( angle );
double move_y = speed * sin( angle );


EDIT:

I should probably read the whole thread. Looks like you already have this figured out but are just off by 90 degrees.

Note again the above comment: "angle 0 is due east, angle 90 is due north". You probably are treating angle 0 as due north.
Last edited on
Thanks hamsterman/Disch, I've got it working perfectly now, switching sin for cos fixed the problem with it being off by 90 degrees

 
Sprites[0].move(std::sin(3.14159265 * Sprites[0].getRotation() / 180.f) * (float)Player.getSpeed() * ElapsedTime, -1 * std::cos(3.14159265 * Sprites[0].getRotation() / 180.f) * (float)Player.getSpeed() * ElapsedTime);

Topic archived. No new replies allowed.