Rotating sprite in allegro
Neomex

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

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

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

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

Neomex

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

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 ?

Neomex

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

nvrmnd

GullRaDriel

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

Neomex

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

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.

Neomex

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

Thread #603985. Printed from Allegro.cc