Moving a game object- Cos, Sin, Tan
Eman_321

Hi!
So I have a problem understanding the maths: angles,rotation.

When I turn a player at a specified angle..I need to able to make the player move in the direction at which i am facing.
But apparently that is a big problem and i don't understand it..

I tried finding the new coordinates by using

     angle = 0.0f;
     new_x = cos(angle) * radius ; 
     new_y = sin(angle) * radius ; 
     angle+=0.1f;//or minus depending on which key i am pressing(LEFT or RIGHT)
     rotate_sprite(..) ;

that should give me the new x and y direction for controlled player to move it..
But if I was to add the old vector to the new one..it could "jump" and will get stuck at the (0,0) corner of the screen.

First question I want to know is why is 0.0 the starting angle?
After studying tutorials on the website, they seem to neglect explaining this..it might seem basic to you but I don't understand maths :(
so why is angle set at 0.1f degrees and then incremented..or is it degrees or units?

do I have to convert to degrees to get the proper x and y values..i tried both and either it doesn't move or it gets stuck..
So how do I fix this?

How can I turn my player using the keys and the move in that direction

Can anyone draw a little diagram to help me understand this?
I understand better with that thanks.

X-G
Eman_321 said:

But if I was to add the old vector to the new one..it could "jump" and will get stuck at the (0,0) corner of the screen.

???

That is what you should to do.

Without some actual code and a better description of what isn't working, there is nothing else we can do.

Eman_321

Sorry, my bad

#SelectExpand
1 2#include <allegro.h> 3#include "Vector2.h" 4#include <cmath> 5#define PI 3.14159276535 6int main() 7{ 8 Vector2 pos1(320,100) ; 9 10 Vector2 pos2(-2,-2) ; 11 float new_x=0.0f ; 12 float new_y = 0.0f; 13 14 float angle =0.0f ; 15 16 17 float length = 0; 18 if(!allegro_init()) 19 { 20 BITMAP* backbuffer = create_bitmap(640,480) ; 21 BITMAP* playerOne = create_bitmap(20,20) ; 22 BITMAP* playerTwo = create_bitmap(20,20) ; 23 24 25 install_keyboard() ; 26 // set_color_depth(32) ; 27 28 clear_to_color(playerOne,makecol(0,0,0)); 29 30 31 clear_to_color(playerTwo,makecol(0,0,0)); 32 33 34 35 36 if(!set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0)) 37 { 38 while(!key[KEY_ESC]) 39 { 40 clear_to_color(backbuffer,makecol(0,0,0)); 41 42 triangle(playerOne,0,19,10,0,19,19,makecol(255,255,255)); 43 triangle(playerTwo,0,19,10,0,19,19,makecol(255,255,255)); 44 45 46 47 48 49 length = sqrt(pos1.x*pos1.x + pos1.y * pos1.y) ; 50 51 52 if(key[KEY_RIGHT]) 53 54 { 55 angle+=0.1f; 56 57 } 58 59 if(key[KEY_LEFT]) 60 61 { 62 angle-=0.1f; 63 64 65 } 66 67 68 69 70 if(key[KEY_UP]) 71 { 72 73 74 pos1.x-=new_x; 75 76 pos1.y-=new_y; 77 78 } 79 80 81 82 83 84 85 86 87 target_angle = atan2(pos1.y,pos1.x) ; 88 89 new_x = length * cosf(target_angle) ; 90 new_y = length * sinf(target_angle); 91 target_angle+=1 ; 92 93 94 95 96 rotate_sprite(backbuffer,playerOne,pos1.x ,pos1.y,ftofix(angle)) ; 97 98 draw_sprite(backbuffer,playerTwo,pos2.x,pos2.y) ; 99 100 101 clear_to_color(playerOne,makecol(0,0,0)); 102 103 104 105 106 107 clear_to_color(playerOne,makecol(255,0,0)); 108 109 110 blit(backbuffer,screen,0,0,0,0,SCREEN_W,SCREEN_H) ; 111 clear_bitmap(backbuffer) ; 112 } 113 } 114 } 115 return 0 ; 116}

vector2 just has x and y coordinates nothing more.

gnolam

And are those coordinates integers or floats? :P
If your vector handling might be at fault (which has already been implied), it's probably a good idea to post your code for that too...

Eman_321
#SelectExpand
1 2 3#ifndef Vector2_h 4#define Vector2_h 5class Vector2 6{ 7public: 8 float x ; 9 float y ; 10 float angle ; 11 12public: 13 float length() ; 14 void normalize(float l) ; 15 16 Vector2(float,float) ; 17 18 void add(Vector2 &pos) ; 19 void subtract(Vector2 &pos) ; 20 void scale(float f) ; 21 22 float direction() ; 23 24 void setAngle(float f) ; 25 26 void getVectors(); 27} ; 28#endif 29#include <math.h> 30#include "Vector2.h" 31#include <allegro.h> 32float Vector2::length() 33{ 34 return sqrt(x*x + y*y) ; 35} 36 37void Vector2::normalize(float l) 38{ 39 x = x/l ; 40 y = y/l ; 41} 42 43Vector2::Vector2(float x,float y) 44{ 45 this->x = x; 46 this->y = y; 47} 48 49void Vector2::add(Vector2 &pos) 50{ 51 x +=pos.x ; 52 y+=pos.y ; 53} 54void Vector2::subtract(Vector2 &pos) 55{ 56 x -=pos.x ; 57 y-=pos.y ; 58 59} 60void Vector2::scale(float f) 61{ 62 63 x *=f ; 64 y*=f ; 65} 66 67void Vector2::getVectors() 68{ 69 textprintf(screen,font,320,10,makecol(255,0,0),"Pos X: %f %f", x, y) ; 70 71} 72float Vector2::direction() 73{ 74 angle = atan(y/x) ; 75 76 return angle ; 77 78} 79void Vector2::setAngle(float x1) 80{ 81 //angle+=x1 ; 82}

That is Vector.h and Vector.cpp combined..
but I am not using any member functions within the Vector class.
Everything is mainly procedural now..because I am trying to get sense of the maths..

Trezker

In direction, it's better to use atan2(y, x) since that handles special cases.

And you know you can overload operators right?
Then you can do vector1 += vector2 instead of vector1.add(vector2), I think that's much nicer. Though it doesn't solve your problem.

Eman_321

i haven't gone past polymorphism haha
Yeah I have read of overloading an operator..but too advance at this stage..

i know i can use atan2(..) or sin(..) ...
but my question is how and when do I use them?

why is the angle set to 0.0f? why is it incremented?

Does angle represent degrees or is it just a simple unit?

How can i move the player object in the direction to which i am facing?

Thanks for help

gnolam
Eman_321 said:

why is the angle set to 0.0f

Because... you've initialized it to 0.0f? ???

Quote:

why is it incremented?

Again, you are the one doing it. ???

Quote:

Does angle represent degrees or is it just a simple unit?

Radians.

Quote:

How can i move the player object in the direction to which i am facing?

x += move_speed_per_tick*cos(facing_angle);

// Negative here because Allegro's y axis points down, not up
y -= move_speed_per_tick*sin(facing_angle);



(Note: I have not looked at your code, since I haven't read a good enough explanation of what your problem is yet.)

Eman_321

mmn..
i have a point, a vector on the graph. x and y coordinates.
I want to be able to turn at a certain angle if i press left or right key, and move the player in that direction.

the last parameter takes a fixed angle. In some examples they use 90,64,128...some 0.0f
I have no idea where they get the value from, do I pick a random value to be my fixed angle and simply increment or decrement?

you give me this equation

x += move_speed_per_tick*cos(facing_angle);

// Negative here because Allegro's y axis points down, not up
y -= move_speed_per_tick*sin(facing_angle);

which angle do I use?

angle I have set to rotate about
or another angle I have to find tan(y/x) ?
when do i use atan(y/x) ?

how come you aren't multiplying by magnitude?

OnlineCop

Allegro uses fixed math for its directions. So 256 fixed is 360.0 degrees or 2*PI radians. The examples you're seeing are taking into account that 0..64 gives angles from 0..90 degrees (or 0..PI/2 radians) in order for things such as rotate_sprite() to allow the object to face in the correct direction.

There are two ways to do your movements. You can use cartesian coordinates (x,y) or polar (theta, magnitude). They will equal the same in the end, but lets you choose which math you want to use to get there.

Eman_321

I have used this diagram to try and explain the angle concept in allegro.
Can someone correct it if wrong?
The diagram is attached.

#SelectExpand
1 2#include <allegro.h> 3 4#include <cmath> 5 6 7class Vector2 8{ 9public: 10 float x ; 11 float y ; 12 float angle ; 13 14public: 15 float length() ; 16 void normalize() ; 17 18 Vector2(float,float) ; 19 20 void add(Vector2 &pos) ; 21 void subtract(Vector2 &pos) ; 22 void scale(float f) ; 23 24 float direction() ; 25 26 void setAngle(float f) ; 27 28 29} ; 30 31float Vector2::length() 32{ 33 return sqrt(x*x + y*y) ; 34} 35 36void Vector2::normalize() 37{ 38 float l=length() ; 39 x = x/l ; 40 y = y/l ; 41} 42 43 44 45void Vector2::add(Vector2 &pos) 46{ 47 x +=pos.x ; 48 y+=pos.y ; 49} 50void Vector2::subtract(Vector2 &pos) 51{ 52 x -=pos.x ; 53 y-=pos.y ; 54 55} 56void Vector2::scale(float f) 57{ 58 59 x *=f ; 60 y*=f ; 61} 62float Vector2::direction() 63{ 64 angle = atan(y/x) ; 65 66 return angle ; 67 68} 69void Vector2::setAngle(float x1) 70{ 71 //angle+=x1 ; 72} 73 74#ifndef M_PI 75 #define M_PI 3.1415926535897932385 76 77#endif 78int main() 79{ 80 Vector2 pos1(320,100) ; 81 82 Vector2 pos2(-2,-2) ; 83 float new_x=0.0f ; 84 float new_y = 0.0f; 85 86 float angle =0.0f ; 87 float target_angle=0.0f; 88 89 float length = 0; 90 if(!allegro_init()) 91 { 92 BITMAP* backbuffer = create_bitmap(640,480) ; 93 BITMAP* playerOne = create_bitmap(20,20) ; 94 BITMAP* playerTwo = create_bitmap(20,20) ; 95 96 97 install_keyboard() ; 98 99 100 101 clear_to_color(playerOne,makecol(0,0,0)); 102 103 104 clear_to_color(playerTwo,makecol(255,0,0)); 105 106 triangle(playerOne,0,19,10,0,19,19,makecol(255,255,255)); 107 triangle(playerTwo,0,19,10,0,19,19,makecol(255,255,255)); 108 109 110 111 112 if(!set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0)) 113 { 114 while(!key[KEY_ESC]) 115 { 116 clear_to_color(backbuffer,makecol(0,0,0)); 117 118 119 120 121 122 123 triangle(playerOne,0,19,10,0,19,19,makecol(255,255,255)); 124 125 triangle(playerTwo,0,19,10,0,19,19,makecol(255,255,255)); 126 127 length = sqrt(pos1.x*pos1.x + pos1.y * pos1.y) ; 128 129 130 if(key[KEY_RIGHT]) 131 { 132 if(angle>=256.0f) 133 { 134 angle = 256.0f; 135 } 136 angle= angle +0.1f ; 137 } 138 139 140 141 if(key[KEY_LEFT]) 142 { 143 144 if(angle<=0.0f) 145 { 146 angle = 0.0f; 147 } 148 angle= angle - 0.1f; 149 } 150 151 152 if(key[KEY_UP]) 153 { 154 pos1.x += sin(angle * M_PI/180)*1; 155 pos1.y += cos(angle * M_PI/180)*-1; 156 } 157 if(key[KEY_DOWN]) 158 { 159 pos1.x -= sin(angle * M_PI/180)*1; 160 pos1.y -= cos(angle * M_PI/180)*-1 ; 161 } 162 163 164 //target_angle = atan2(pos1.x,pos1.y) ; 165 166 textprintf(backbuffer,font,320,10,makecol(255,0,0),"Angle: %f", angle) ; 167 168 169 170 171 172 173 rotate_sprite(backbuffer,playerOne,pos1.x ,pos1.y,ftofix(angle)) ; 174 175 176 draw_sprite(backbuffer,playerTwo,pos2.x,pos2.y) ; 177 178 179 clear_to_color(playerOne,makecol(0,0,0)); 180 181 182 183 184 185 clear_to_color(playerTwo,makecol(0,0,0)); 186 187 188 blit(backbuffer,screen,0,0,0,0,SCREEN_W,SCREEN_H) ; 189 clear_bitmap(backbuffer) ; 190 } 191 } 192 } 193 return 0 ; 194} 195 196END_OF_MAIN()

The player moves in the right direction only if its angle is between 0 and 64 degrees, after that it doesn't move in the right direction..
can someone help ?
Thanks

Mark Oates

I'm suprised nobody's mentioned Amarillion's Legendary Sin & Cos Tutorial.

Eman_321

I read it already. I get how to convert from polar to cartesian and vice versa.
But it doesn't explain some basic stuff - which basic, i don't get -
like why is the initial angle set to 0, instead of 90 which makes more sense.
Even then there must be a bug in my code because the sprite does not move in the right direction..after 64 degrees

gnolam
Eman_321 said:

how come you aren't multiplying by magnitude?

I am. move_speed_per_tick. :P

Eman_321 said:

rotate_sprite(backbuffer,playerOne,pos1.x ,pos1.y,ftofix(angle));

ftofix() only converts a float into fixed point - it doesn't change the angle representation. You're trying to pass in degrees (0-360) instead of allegro angles (0-256) to rotate_sprite().
angleallegro = angledeg*256/360.
As a general rule: keep all angles in radians. Only convert them to something else when a function for some reason expects something else (e.g. rotate_sprite() or glRotatef()) or when it needs to be displayed to the player in another format.

Eman_321 said:

like why is the initial angle set to 0

... arrrgh. Because you fucking set it to 0.
If you wanted to, you could have an initial angle of 666 degrees, or ei*pi radians, or...

Eman_321
Quote:

arrrgh. Because you ****ing set it to 0.

;D yes i know i set it to 0, what i don't get is
why is 0 degrees making the bitmap perpendicular<b>
That should be 90 degrees.
Is it the way allegro is set or something?
I tried multiplying by 256/360, and the sprite wouldn't move.

EDIT
OMG it is working now! I don't get it, before when I tried it didn't work!!!!

I understand calculating the angles and cartesian coordinates!
but still not why the initial angle is set to 0 which makes it face upward
but when i make it 90 degrees,it appears to be 60 degrees!

Thread #605510. Printed from Allegro.cc