Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » [Math] Rotation

Credits go to FrankyR for helping out!
This thread is locked; no one can reply to it. rss feed Print
[Math] Rotation
ngiacomelli
Member #5,114
October 2004

In my game the player is divided into three sections. Torso, legs and arms. This is because the game uses an Abuse-style control system. Where you aim with the mouse and the arm rotates accordingly. This works fines.

When rendering the arm I use the following code (please exclude hardcoded values!):

     if( mouse_x >= ( player.x + (player.body[0]->w/2)) ) {
             
             pivot_sprite( bmp, weapon_base[player.inv.weapon[player.inv.c_slot].weap_type].sprite, player.x + 6, player.y - 8, 1, 23, float_to_fixed( player.torso_angle ) );
             
     } else {
         
             pivot_sprite_v_flip( bmp, weapon_base[player.inv.weapon[player.inv.c_slot].weap_type].sprite, player.x + 15, player.y - 8, 0, 13, float_to_fixed( player.torso_angle ) );
                            
     }

The problem I have is with my projectile spawning:

 player.x+(cos(player.torso_angle)*5), 
 player.y+(sin(player.torso_angle)*5),

The problem is the actual start coordinates. Right now the bullets come from 'inside' of the player, rather than the tip of his/her weapon. In my game each weapon has its own set of hands rendered along with it. Meaning the weapons sprites can be of a variable height and width. So what I really need to know is how can I go about getting the coordinates for the 'tip' of the gun 'nozzle'. So that the bullets appear to spawn out of the weapon?

FrankyR
Member #243
April 2000
avatar

You can rotate a vector thusly:

x' = cos(theta)*x - sin(theta)*y
y' = sin(theta)*x + cos(theta)*y

So, starting with a normailized vector ( (1,0) if you want theta to be the angle between the arm and the x-axis, or (0,-1) if you want theta to be the angle between the arm and the y-axis). Apply the above formulas to get the roatated unit vector, then just multiply that by the length of the arm. This will give you the offset from the start of the arm to the end.

ngiacomelli
Member #5,114
October 2004

You'll have to excuse my terrible math knowledge. But can you explain the theta value in greater detail?

x' = cos(theta)*x - sin(theta)*y
y' = sin(theta)*x + cos(theta)*y

As I understand it, I'd take the (x,y) location on the player sprite. The location that the arm actually pivots around. And also the (w,h) of the arm sprite. Then get the rotated values for the arm sprite, and add it to the pivot location... right?

FrankyR
Member #243
April 2000
avatar

Oh, sorry, theta is the angle that you want to rotate.

My suggestion was to take a simple unit-length (i.e. magnitude of 1) vector and rotate that, multiply it by the length of the arm and add it to the point where the arm is attached. I'll go into more detail:

If your player is standing at position (x,y), the shoulder is offset from the player position by (shoulder_offset_x, shoulder_offset_y), and the angle between the x-axis and the arm is theta radians.

I take the axis: (1,0) and rotate it by theta radians:

rotated_axis_x = cos(theta)*1 - sin(theta)*0
rotated_axis_y = sin(theta)*1 + cos(theta)*0

this gives me a new vector: (cos(theta), sin(theta)).

Now, since this is a unit-length vector I multiply it by arm_length to get an offset value from the point where the arm is attached to the end of the arm.

So, now the end of the arm is:

arm_end_x = x + shoulder_offset_x + cos(theta)*arm_length
arm_end_y = y + shoulder_offset_y + sin(theta)*arm_length
            |            |                |
        player position  |      angle between x-axis and arm
                  offset from position
                to where arm is attached

ngiacomelli
Member #5,114
October 2004

I see! So in practice:

         p_x = player.x + 6 + cos( player.torso_angle )*weapon_base[player.inv.weapon[player.inv.c_slot].weap_type].sprite->w;
         p_y = player.y - 8 + sin( player.torso_angle )*weapon_base[player.inv.weapon[player.inv.c_slot].weap_type].sprite->w;

Works perfectly, thanks for the explanation!

Go to: