Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Rotating sprite in allegro

Credits go to GullRaDriel for helping out!
This thread is locked; no one can reply to it. rss feed Print
Rotating sprite in allegro
Neomex
Member #11,618
January 2010

Hello,
I try to make that my sprite will rotate to mouse position, but it doesnt move.
(I use old allegro)

[code]
player.angle = atan2(player.x-player.y, mouse_x-mouse_y);
rotate_sprite(buf,ppistol, player.x , player.y , ftofix( (player.angle*256)/360.0 ) );
[/code]

---

I found similar thread on this forum, and was trying to make like there, but I still got problem, because it rotates well, but mouse is behind player.

const double rad_to_deg = 180.0/M_PI;
const double deg_to_adeg = 32.0/45.0;
const double rad_to_adeg = 128.0/M_PI;

player.angle = -atan2( mouse_x - player.x, mouse_y-player.y);

rotate_sprite( buf , ppistol , player.x, player.y , ftofix( player.angle*rad_to_adeg ) ); //(player.angle*256)/360.0) );

type568
Member #8,381
March 2007
avatar

You should really read your post at least once after posted, at least unless you learn how to use the forum's formatting.

Neomex said:

I found similar thread on this forum, and was trying to make like there, but I still got problem, because it rotates well, but mouse is behind player.

So put it above the "player"? o0
Use a custom mouse perhaps? (blit some image on mouse coordinates)

Neomex
Member #11,618
January 2010

That's not what I mean, but I just rotated texture at 180 degrees and now works perfectly, but I don't know how to move player to mouse direction.

#SelectExpand
1const double rad_to_deg = 180.0/M_PI;// 360.0/(2.0*M_PI); 2const double deg_to_adeg = 32.0/45.0;// 256.0/360.0; 3const double rad_to_adeg = 128.0/M_PI; 4 5double tab_sin[360]; 6double tab_cos[360]; 7 8void laduj_sin_cos() 9{ 10 for(int i=0; i < 360; i ++) 11 { 12 tab_sin[i] = sin((M_PI*(i))/180); 13 tab_cos[i] = cos((M_PI*(i))/180); 14 } 15} 16 17 18... 19 20 21if( key[KEY_W] ) 22 { 23 //player.x += cos(player.angle) * 5; 24 //player.y += sin(player.angle) * 5; 25 player.angle = player.angle * rad_to_adeg; 26 player.x -= 2*tab_cos[ int( player.angle ) ]; 27 player.y -= 2*tab_sin[ int( player.angle ) ]; 28 29 }

It moves in strange ways :)

GullRaDriel
Member #3,861
September 2003
avatar

What do you want to do exactly ?

According to my crystal ball (which is not really working fine ya know):

1) You have a point that represent the player with x and y
2) You use the mouse pointer and accordingly rotate the player's sprite for it to follow the angle between the mouse coordinate and the player's coordinate
3) You want to press W for making the player move in direction of the mouse

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Neomex
Member #11,618
January 2010

Main.cpp

#SelectExpand
1#include "main.h" 2#include "bmp.h" 3#include "timer.h" 4 5#include "player.h" 6 7int main() 8{ 9allegro_init(); 10depth = desktop_color_depth(); 11if (depth == 0) depth = 32; 12 set_color_depth(depth); 13 14res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, WINDOW_X, WINDOW_Y, 0, 0); 15 if (res != 0) { 16 allegro_message(allegro_error); 17 exit(-1); 18 } 19 20install_timer(); 21install_keyboard(); 22install_mouse(); 23install_sound(DIGI_AUTODETECT,MIDI_AUTODETECT,""); 24set_volume(255,255); 25 26//select_mouse_cursor(1); 27show_mouse(screen); 28LOCK_VARIABLE(speed_counter); //Used to set the timer - which regulates the game's 29LOCK_FUNCTION(increment_speed_counter);//speed. 30 31install_int_ex(increment_speed_counter, BPS_TO_TIMER(60));//Set our BPS 32 33//inits 34Cplayer player; 35 36buf = create_bitmap(WINDOW_X, WINDOW_Y); 37grass = load_bitmap("grass.bmp", 0); 38 39hud = load_bitmap("hud.bmp", 0); 40ppistol = load_bitmap("ppistol.bmp", 0); 41 42laduj_sin_cos(); 43 44while (!key[KEY_ESC]) 45{ 46 /* put your code here */ 47 clear(buf); 48 masked_blit(grass, buf, 0, 0, 0, 0, grass->w, grass->h); 49 masked_blit(hud, buf, 0, 0, 800, 0, hud->w, hud->h); 50 51 while(speed_counter > 0) 52 { 53 if( key[KEY_W] ) 54 { 55 player.x += cos(player.angle) * 5; 56 player.y += sin(player.angle) * 5; 57 //player.angle = player.angle * rad_to_adeg; 58 //player.x -= 2*tab_cos[ int( player.angle ) ]; 59 //player.y -= 2*tab_sin[ int( player.angle ) ]; 60 61 } 62 63 //player.angle = atan2(player.x-player.y, mouse_x-mouse_y); 64 player.angle = -atan2( mouse_x - ( player.x + 25 ), mouse_y - ( player.y + 25 ) ); 65 //player.angle = atan2( mouse_y - player.y, mouse_x-player.x); 66 67 player.hlong+=0.02; 68 69 speed_counter --; 70 } 71 72 //textprintf(buf, font, 0, 0, makecol(255, 0, 0), "Red Text"); 73 74 //SCORES ON HUD 75 textprintf_ex(buf, font, 880, 125, makecol(0, 0, 255), -1, "%i" , player.life); 76 textprintf_ex(buf, font, 880, 185, makecol(0, 0, 255), -1, "%i" , player.score); 77 textprintf_ex(buf, font, 880, 250, makecol(0, 0, 255), -1, "%i" , player.wastedammo); 78 textprintf_ex(buf, font, 880, 320, makecol(0, 0, 255), -1, "%i" , player.ammo); 79 textprintf_ex(buf, font, 880, 380, makecol(0, 0, 255), -1, "%i" , player.score); 80 textprintf_ex(buf, font, 820, 510, makecol(0, 0, 255), -1, "%f" , player.hlong); 81 //TILDE VARIABLES 82 if( key[KEY_TILDE] && console == false ) 83 { 84 console = true; 85 }else 86 if( key[KEY_TILDE] && console == true ) 87 { 88 console = false; 89 } 90 if( console == true ) 91 { 92 textprintf_ex(buf, font, 10, 10, makecol(255, 0, 0), -1, "Player Angle: %f" , player.angle*rad_to_adeg); 93 textprintf_ex(buf, font, 10, 20, makecol(255, 0, 0), -1, "Player X: %f" , player.x); 94 textprintf_ex(buf, font, 10, 30, makecol(255, 0, 0), -1, "Player Y: %f" , player.y); 95 } 96 97 rotate_sprite( buf , ppistol , player.x, player.y , ftofix( player.angle*rad_to_adeg ) ); //(player.angle*256)/360.0) ); 98 //masked_blit(ppistol, buf, 0, 0, player.x, player.y, ppistol->w, ppistol->h); 99 100 masked_blit(buf, screen, 0, 0, 0, 0, buf->w, buf->h); 101} 102 103destroy_bitmap(buf); 104destroy_bitmap(grass); 105destroy_bitmap(ppistol); 106destroy_bitmap(hud); 107 108clear_keybuf(); 109return 0; 110} 111END_OF_MAIN()

main.h

#SelectExpand
1#include <allegro.h> 2#include <math.h> 3 4#define WINDOW_X 1000 5#define WINDOW_Y 600 6 7int depth, res; 8 9#define DEGREES(x) int((x)/360.0*0xFFFFFF) 10#define RADIANS(x) int((x)/2/M_PI*0xFFFFFF) 11 12const double rad_to_deg = 180.0/M_PI;// 360.0/(2.0*M_PI); 13const double deg_to_adeg = 32.0/45.0;// 256.0/360.0; 14const double rad_to_adeg = 128.0/M_PI; 15 16bool console = false; 17 18double tab_sin[360]; 19double tab_cos[360]; 20 21void laduj_sin_cos() 22{ 23 for(int i=0; i < 360; i ++) 24 { 25 tab_sin[i] = sin((M_PI*(i))/180); 26 tab_cos[i] = cos((M_PI*(i))/180); 27 } 28}

player files

#SelectExpand
1#include "player.h" 2 3Cplayer::Cplayer() 4{ 5 x = 400; 6 y = 300; 7 w = 50; 8 h = 50; 9 speed = 5; 10 angle = 0; 11 12 life = 100; 13 score = 0; 14 wastedammo = 0; 15 ammo = 0; 16 killed_zombies = 0; 17 18 hlong = 0; 19} 20 21--- 22 23class Cplayer 24{ 25 public: 26 27 float x , y , w , h; 28 29 float angle; 30 float speed; 31 32 int life; 33 int score; 34 int wastedammo; 35 int ammo; 36 int killed_zombies; 37 38 float hlong; 39 40 Cplayer(); 41};

I want to move player to mouse direction, after pressing W key.
--
Btw, your crystal ball works fine, that's what I'm trying to do. :)

GullRaDriel
Member #3,861
September 2003
avatar

I don't know how to correct your code. I was lazy and I found it better to give you a working example.

#SelectExpand
1#include <math.h> 2#include <allegro.h> 3 4 5BITMAP *scrbuf = NULL ; 6BITMAP *sprite = NULL ; 7 8 9typedef struct PLAYER 10{ 11 double x , 12 y ; 13 fixed angle ; 14} PLAYER ; 15 16PLAYER player; 17 18 19double angle = 0 ; 20 21 22int main( int argc , char *argv[] ) 23{ 24 allegro_init(); 25 install_keyboard(); 26 install_mouse(); 27 install_timer(); 28 set_color_depth( 32 ); 29 set_gfx_mode( GFX_AUTODETECT_WINDOWED , 800 , 600 , 0 , 0 ); 30 31 scrbuf = create_bitmap( SCREEN_W , SCREEN_H ); 32 33 sprite = create_bitmap( 64 , 256 ); 34 clear_to_color( sprite , makecol( 255 , 0 , 255 ) ); 35 rect( sprite , 10 , 10 , 54 , 246 , makecol( 255 , 0 , 0 ) ); 36 line( sprite , 10 , 10 , 32 , 0 , makecol( 255 , 255 , 0 ) ); 37 line( sprite , 32 , 0 , 54 , 10 , makecol( 255 , 255 , 0 ) ); 38 39 player . x = SCREEN_W / 2 ; 40 player . y = SCREEN_H / 2 ; 41 player . angle = 0 ; 42 43 44 while( !key[ KEY_ESC ] ) 45 { 46 player . angle = -fixatan2( ftofix( player . x - mouse_x ) , ftofix( player . y - mouse_y ) ); 47 48 if( key[ KEY_SPACE ] ) 49 { 50 int vx , vy ; 51 double size , cx , cy ; 52 53 54 vx = player . x - mouse_x ; 55 vy = player . y - mouse_y ; 56 57 if( vx || vy ) 58 { 59 size = sqrt( vx*vx + vy*vy ); 60 61 cx = vx/size ; 62 cy = vy/size ; 63 cx = 2 * cx ; 64 cy = 2 * cy ; 65 66 player . x = player . x - cx ; 67 player . y = player . y - cy ; 68 69 } 70 } 71 72 73 clear( scrbuf ) ; 74 75 textprintf_ex( scrbuf , font , 10 , 10 , makecol( 255 , 100 , 200 ) , -1 , "Angle: %0.0f" , fixtof( player.angle ) ); 76 77 line( scrbuf , mouse_x - 5 , mouse_y , mouse_x + 5 , mouse_y , makecol( 255 , 255 , 255 ) ); 78 line( scrbuf , mouse_x , mouse_y - 5 , mouse_x , mouse_y + 5 , makecol( 255 , 255 , 255 ) ); 79 80 81 rotate_sprite( scrbuf , sprite , player . x - sprite -> w / 2 , player . y - sprite -> h / 2 , player . angle ); 82 blit( scrbuf , screen , 0 , 0 , 0 , 0 , SCREEN_W , SCREEN_H ); 83 84 } 85 86 destroy_bitmap( scrbuf ); 87 destroy_bitmap( sprite ); 88 89 allegro_exit(); 90 91}END_OF_MAIN()

I attached source and (alleg4.4) binary.

The sprite is rotating accordingly to the mouse position, and go in direction of the mouse when pressing SPACE.

You were in need of rotation forumulae for the rotating part, but the move is only a vector story.

I just calculated the normalised vector between mouse / player and used it at each frame.

Here is your file. Clicky, isn't it ?

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Neomex
Member #11,618
January 2010

Works perfectly! Thanks a lot! :)

I think I understand (mostly) how does it work.
Oh, what about it?

if( vx || vy )

It means:
if vx or vy is different than 0 then... ?

Arthur Kalliokoski
Second in Command
February 2005
avatar

nvrmnd

They all watch too much MSNBC... they get ideas.

GullRaDriel
Member #3,861
September 2003
avatar

I am not sure if it covers all the cases, but that if( vx ||vy ) is there to ensure that you'll never have a zero size (length) and thus not dividing by 0 in the next steps.

Literately it means vx != 0 or vy != 0

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Neomex
Member #11,618
January 2010

One more question
How to change this code, if I want to move to the left or right?

#SelectExpand
1if( key[ KEY_SPACE ] ) 2 { 3 int vx , vy ; 4 double size , cx , cy ; 5 6 7 vx = player . x - mouse_x ; 8 vy = player . y - mouse_y ; 9 10 if( vx || vy ) 11 { 12 size = sqrt( vx*vx + vy*vy ); 13 14 cx = vx/size ; 15 cy = vy/size ; 16 cx = 2 * cx ; 17 cy = 2 * cy ; 18 19 player . x = player . x - cx ; 20 player . y = player . y - cy ; 21 22 }

{"name":"infof.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/1\/4162db84b71cdf01c513ad41d140d0d9.jpg","w":324,"h":326,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/4\/1\/4162db84b71cdf01c513ad41d140d0d9"}infof.jpg

GullRaDriel
Member #3,861
September 2003
avatar

You have to do a little bit of vector math.

http://stackoverflow.com/questions/1243614/how-do-i-calculate-the-normal-vector-of-a-line-segment said:

The matrix representation of the general 2D transformation looks like this:

x' = x cos(t) - y sin(t)
y' = x sin(t) + y cos(t)
where (x,y) are the components of the original vector and (x', y') are the transformed components.

If t = 90 degrees, then cos(90) = 0 and sin(90) = 1. Substituting and multiplying it out gives:

x' = -y
y' = +x

So, basically you'll have to modify it that way:

#SelectExpand
1if( keypressed() || mouse_b&1 || mouse_b&2 ) 2{ 3 int vx , vy ; 4 double size , cx , cy ; 5 6 7 vx = player . x - mouse_x ; 8 vy = player . y - mouse_y ; 9 10 if( vx || vy ) 11 { 12 size = sqrt( vx*vx + vy*vy ); 13 14 cx = vx/size ; 15 cy = vy/size ; 16 cx = 2 * cx ; 17 cy = 2 * cy ; 18 19 } 20 21 if( key[ KEY_SPACE ] ) 22 { 23 player . x = player . x - cx ; 24 player . y = player . y - cy ; 25 } 26 else 27 { 28 if( mouse_b&1 ) 29 { 30 player . x = player . x - cy ; 31 player . y = player . y + cx ; 32 } 33 else 34 { 35 if( mouse_b&2 ) 36 { 37 player . x = player . x + cy ; 38 player . y = player . y - cx ; 39 } 40 } 41 } 42}

In that modification, I first test if there was a key pressed or a mouse button. We don't need to compute anything if there was no action.

If I have an action, I first start to compute the vector going from object (sprite) to mouse pointer. When I have it, I apply it differently if it's SPACE, mouse button 1 or 2, accordingly to the explanation from stackoverflow.

I attached you the whole thing again. Use SPACE to move to the mouse_pointer, and mouse button left/right for a perpendicular move against it.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Neomex
Member #11,618
January 2010

That's all that I wanted to know!
Thanks a lot!
:)

Go to: