Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Rotation & movement

Credits go to Vanneto for helping out!
This thread is locked; no one can reply to it. rss feed Print
Rotation & movement
Demons
Member #8,807
July 2007

I'm able to rotate my sprite with:

    if(key[KEY_Q])
      _angle--;
    if(key[KEY_E])
      _angle++;

rotate_sprite(buffer, _sprite, _position.X, _position.Y, itofix(_angle));

I have a vector for the position of the sprite. Using the above to rotate, how can I get the direction vector so when I move forward it moves the direction that the sprite is rotated? I'd sure it's fairly easy and I just can't find anything.

Or, based on the angle, how can I get the direction vector?

Vanneto
Member #8,643
May 2007

You should have a velocity on the x and y axis for the sprite, and then do this:

vx = cos(angle) * speed;
vy = sin(angle) * speed;

Where speed is the speed by which the sprite should be moving. Then you update the x and y values by the vx,vy values:

_position.X += vx;
_position.Y += vy;

And youre done!

In capitalist America bank robs you.

Demons
Member #8,807
July 2007

Oh ok. I do have a velocity, and I also have a direction vector, but it seems since I have the angle variable I don't need the direction vector. Thanks.

Also, that would call cos() and sin() each cycle. I imagine I could call those and store the value in a variable only when I rotate right?

What variables do I need these declared as? I'm getting errors about fixed and such and when I make the angle 'fix' and the vectors float or anything else I get strange results.

I have my angle init to 0 and when I use that to move forward it moves right. ie I have it so when you press the W key it sets the speed value to > 0 to start the movement.

Vanneto
Member #8,643
May 2007

1. Yes you could calculate the new position only when the ship is rotated. That is a good idea.

2. Well sin() and cos() take floats. So you could make _angle a float and then use ftofix() when calling rotate_sprite().

3. Hmm... Dont know about this one. Try starting with 90 degrees.

In capitalist America bank robs you.

Demons
Member #8,807
July 2007

OK, I must be missing something. Here is my player code, would be great if someone could take a look and let me know what I'm doing wrong.

The sprite does rotate, but the direction of moving doesn't work correctly.

1class Vector2D
2{
3private:
4public:
5 float X, Y;
6};
7 
8 
9class Player
10{
11private:
12 BITMAP *_sprite;
13 Vector2D _position;
14 Vector2D _velocity;
15 Vector2D _direction;
16 float _angle;
17 float _speed;
18 bool _moveForward;
19public:
20 Player()
21 {
22 _moveForward = false;
23 _speed = 0;
24 _angle = 90;
25 _position.X = SCREEN_W/2;
26 _position.Y = SCREEN_H/2;
27 _direction.X = cos(_angle);
28 _direction.Y = sin(_angle);
29 _sprite = load_bitmap("C:\\player.bmp",0);
30 }
31 void draw(BITMAP *buffer)
32 {
33 rotate_sprite(buffer, _sprite, _position.X, _position.Y, ftofix(_angle));
34 }
35 void move()
36 {
37 //_velocity.X = _direction.X * _speed;
38 //_velocity.Y = _direction.Y * _speed;
39 
40 _velocity.X = cos(_angle) * _speed;
41 _velocity.Y = sin(_angle) * _speed;
42 
43 _position.X += _velocity.X;
44 _position.Y += _velocity.Y;
45 }
46 void input()
47 {
48 if(key[KEY_Q])
49 {
50 _angle--;
51 _direction.X = cos(_angle);
52 }
53 if(key[KEY_E])
54 {
55 _angle++;
56 _direction.Y = sin(_angle);
57 }
58 
59 if(key[KEY_W] && !_moveForward)
60 {
61 _speed = .5;
62 _moveForward = true;
63 }
64 else if(!key[KEY_W] && _moveForward)
65 {
66 _speed = 0;
67 _moveForward = false;
68 }
69 }
70};

TeamTerradactyl
Member #7,733
September 2006
avatar

For your move() function doesn't seem to be truly using your _velocity. I would suggest something similar to:

  void move()
  {
    _velocity.X = cos(_angle) * _speed;
    _velocity.Y = sin(_angle) * _speed;

    _position.X += _velocity.X;
    _position.Y += _velocity.Y;
  }

Could you also explain

Demons said:

the direction of moving doesn't work correctly

and say WHAT isn't working?

Demons
Member #8,807
July 2007

I must be missing something. That looks the same except you have ) after speed which shouldn't compile since there is no matching (.

Quote:

and say WHAT isn't working?

I don't know what isn't working or what it's doing. I just know it's not moving it in the right direction. When my guy is facing up, and I try to move (I don't rotate yet) then he goes right.

[EDIT]

OK, something that seems odd. When the angle is 0, cos(angle) is returning a 1, and that gets multiplies by the speed which is .5 making the _velocity.X = to .5, which isn't right I'm thinking, because that makes my image go right, when the image I have visually is pointing up.

TeamTerradactyl
Member #7,733
September 2006
avatar

What direction is your BITMAP *_sprite stored? You may need to rotate the sprite's image by 90 degrees. The "unturned" direction should be facing right when you have _angle=0.0, it should be facing up when _angle=PI/2 (or in the case of Allegro rotations, 128/2, or 64.0).

And the ")" artifact was something that happened when copying/pasting; sorry. I'll edit my post and fix that typo.

EDIT: Sorry; I guess I had not correctly read your code post, so I had re-keyed what you already had.

So please disregard that first bit; I thought your math was wrong, but it turns out, you were correct all along. The relevant thing is that I think your sprite is simply turned 90 degrees. What direction does it go if you use your Q/E keys and accelerate? Does it go "straight" and even rotate correctly, but simply have the bitmap facing the wrong direction?

Demons
Member #8,807
July 2007

My bitmap is stored normally I guess. I created a top down bitmap where you are looking directly down on a person. So you see hit head, shoulders, adn a gun that is pointing "up" or forward.

When angle is 0 the image is facing up. In my code I init angle to 0, and it uses that in rotate_sprite. So if angle is 0 it seems rotate_sprite just draws it normally (up), but moving makes it go right. So how do I rotate my bitmap yet not the angle? Seems I need the bitmap to be facing right at first.

When I move and rotate, sometimes it seems to go the right away and sometimes it doesn't. Seems odd.

[EDIT]

Ok, I rotated the image in the paint editor so now it starts out looking right. So now if I move forward and don't rotate it works by moving right and looks visually right. BUT, if I press Q once then move again the character starts moving up/left, when visually he should move up/right.

Hmm maybe it's because the sprite is rotating around the top/left corner instead of the center of the sprite? I assume rotate_sprite() is doing the rotation around the center of the sprite, and my cos()/sin() is doing it around the top/left of teh sprite.

IonBlade
Member #3,521
May 2003
avatar

[EDIT] Nevermind, I read wrong :P

------

"I've got to choose my words carefully so that I'm not misunderstood, but I think there are fewer developers around today who think about making a good game. As a creator, I find that sad..." - Hideo Kojima

TeamTerradactyl
Member #7,733
September 2006
avatar

1Player::Player()
2{
3 _moveForward = false;
4 _speed = 0.0;
5 _angle = 0.0;
6 _position.X = SCREEN_W/2;
7 _position.Y = SCREEN_H/2;
8 _direction.X = cos(_angle);
9 _direction.Y = sin(_angle);
10 _sprite = load_bitmap("player.bmp",0);
11}
12 
13void Player::draw(BITMAP *buffer)
14{
15 rotate_sprite(buffer, _sprite, _position.X, _position.Y, ftofix(_angle * 128.0));
16}
17 
18 
19void Player::move()
20{
21 _velocity.X = cos(_angle * M_PI) * _speed;
22 _velocity.Y = sin(_angle * M_PI) * _speed;
23 
24 _position.X += _velocity.X;
25 _position.Y += _velocity.Y;
26}
27 
28void Player::input()
29{
30 if(key[KEY_Q])
31 {
32 _angle-=0.05; // If this is too large, it rotates much too quickly
33 _direction.X = cos(_angle);
34 }
35 if(key[KEY_E])
36 {
37 _angle+=0.05; // Same as rotation for KEY_Q
38 _direction.Y = sin(_angle);
39 }
40 if(key[KEY_W] && !_moveForward)
41 {
42 _speed = .5;
43 _moveForward = true;
44 }
45 else if(!key[KEY_W] && _moveForward)
46 {
47 _speed = 0;
48 _moveForward = false;
49 }
50}

Go to: