Allegro.cc Forums » Programming Questions » Any Direction in 2d??

 Any Direction in 2d??
 CursedTyrant Member #7,080 April 2006 If I understand correctly, you need something like this: ```void CEnemy::Move(float nX, float nY) { float Angle = atan2(nY-Y, nX-X)*180.0f/M_PI; X += cosf(Angle*M_PI/180.0f)*Speed; Y += sinf(Angle*M_PI/180.0f)*Speed; } ``` What it does is make the CEnemy object move towards the (nX; nY) coordinates.And in the bullet object you just do something like: ```CBullet::CBullet(float nAngle) { Angle = nAngle; //other stuff here } void CBullet::Move() { X += cosf(Angle*M_PI/180.0f)*Speed; Y += sinf(Angle*M_PI/180.0f)*Speed; } ``` That should work fine. ---------Signature.----[My Website] | [My YouTube Channel]
 Mark Oates Member #1,146 March 2001 yes, what Mr. Tyrnat said. It all basically comes down to angles, sin, and cosine. I recommend this tutorial to help clear things up:http://pixwiki.bafsoft.com/mags/5/articles/circle/sincos.htm
Jonatan Hedborg
Member #4,886
July 2004

Or you could do it slightly less confusing (and faster) by storing the angle as radians instead...

```void CEnemy::Move(float nX, float nY)
{
float Angle = atan2(nY-Y, nX-X);

X += cosf(Angle)*Speed;
Y += sinf(Angle)*Speed;
}
```

you could also use pure vector maths for this problem;

 1 void CEnemy::Move(float nX, float nY) 2 { 3 float tx,ty,length; 4 5 //This gets a vector pointing at the nx,ny 6 tx = x-nx; 7 ty = y-ny; 8 9 //Gets the length of the vector through pyth's 10 length = sqrt(tx*tx+ty*ty); 11 12 //Normalizes the vector, making it's total length 1. You should also make sure length isnt 0 13 tx = tx/length; 14 ty = ty/length; 15 16 //Update the position 17 X += tx*Speed; 18 Y += ty*Speed; 19 }

Untested, but that ought to work too.

Not sure which one would be faster, but both has some merits.

And as for the bullet, once again, store the angle in the native form:

```CBullet::CBullet(float nAngle)
{
Angle = nAngle*M_PI/180.0f;
//other stuff here
}
void CBullet::Move()
{
X += cos(Angle)*Speed;
Y += sin(Angle)*Speed;
}
```

Or use vectors

```CBullet::CBullet(float nAngle)
{
tx = cos(nAngle);
ty = sin(nAngle);
//other stuff here
}
void CBullet::Move()
{
X += tX*Speed;
Y += tY*Speed;
}
```

In this case vectors would be faster and simpler (heck, you can even store speed right in the tx/ty pair by multiplying them with it in the start).

-------
Sweden: Free from the shackles of Democracy since 2008-06-18!

 dylan sack Member #6,590 November 2005 Wow, three answers, talk about service ^_^ Thanks for the help guys i'm going to go try to work that into my game right now.
 Johan Halmén Member #1,550 September 2001 There are only a few basic facts when talking about 2D coordinates and directions. The rest derives from the basics. In Allegro graphics you have one coordinate growing from left to right, usually called x, and another growing from top to down, usually called y. The rest, especially the direction stuff, is up to you, as I see it. You can use radians or Allegro angle units for the direction. You can decide that zero be to the right, to the left, up or down. And you can choose that growing direction is like rotating clockwise, or counter clockwise. I guess there's a standard used in games, but I've never bothered to figure out that. I might use the stuff differently in different games, because I'm a lousy coder what comes to reusing stuff. Whatever you choose, it affects the trigonometric formulae, which should be clear for you.Jonathan's code said: ```void CBullet::Move() { X += cos(Angle)*Speed; Y += sin(Angle)*Speed; } ``` It works, but it computes the cos(Angle)*Speed each time the bullet moves. It should compute it only when either Angle or Speed is altered. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.
dylan sack
Member #6,590
November 2005

Ok tried a few of the methods out, and i'm having weird errors about converting to fixed or whatever. Can anyone explain this?

 1 class Player 2 { 3 public: 4 int x, y; 5 int p_facing; 6 int p_hp; 7 void move(); 8 }; 9 Player player; 10 11 12 void move(float nX, float nY) 13 { 14 int Speed; 15 float Angle = atan2(nY-player.y, nX-player.x); // conversion from `float' to non-scalar type `fix' requested 16 17 player.x += cos(Angle)*Speed;//conversion from `float' to non-scalar type `fix' requested 18 player.y += sin(Angle)*Speed;//conversion from `float' to non-scalar type `fix' requested 19 }

I'm pretty new to using any kind of maths in games and just coding games in general.. (i'm only a freshman in algebra 2 >.<) So if I did something realllly dumb try to forgive me

 imaxcs Member #4,036 November 2003 Include cmath in your source-file: ```#include ``` I hope that helps...
 CursedTyrant Member #7,080 April 2006 BTW, If you're using floats use cosf and sinf. Like this: ```float Angle = atan2(nY-player.y, nX-player.x); player.x += cosf(Angle)*Speed; player.y += sinf(Angle)*Speed; ``` You could also use atan2f if you really want to. ---------Signature.----[My Website] | [My YouTube Channel]
 Johan Halmén Member #1,550 September 2001 dylan said: So if I did something realllly dumb try to forgive me We forgive you, but I don't see the point in it ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.
dylan sack
Member #6,590
November 2005

Ok so all these variables are kinda confusing me, what exactly needs to be added to if say I wanted to make a keypress have you rotate to the right? I experimented around with adding values to some of the variables and nothing happened, given I never really took the time to fully understand the code you guys gave me, i'm just kinda using it But I donno, I think i'm just generally confused about it still.

 1 class Player 2 { 3 public: 4 int x, y; 5 int p_facing; 6 int p_hp; 7 void move(); 8 }; 9 Player player; 10 11 12 void move(float nX, float nY) 13 { 14 float X,Y; 15 float Speed; 16 float Angle = atan2f(nY-player.y, nX-player.x); 17 18 X += cosf(Angle)*Speed; 19 Y += sinf(Angle)*Speed; 20 21 22 }

 Johan Halmén Member #1,550 September 2001 There's no use in trying to get our examples work if you don't understand them. If it is that hard, you simply have to step back some steps and do something simpler. And try to understand every step. I could point out that your class has members x and y but the member function move()declares the variables X and Y, which you use in the moving. Well, it doesn't work. And if you don't get it, don't waste time in trying to get it work. Spend that valuable time instead in studying more basic things. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.
Mark Oates
Member #1,146
March 2001

Quote:

And if you don't get it, don't waste time in trying to get it work. Spend that valuable time instead in studying more basic things.

Johan speaks the truth. But I believe that you can figure this part out. Let me try and help.

If you change your player class to contain these variables it should make things much more clear:

 1 class player_class 2 { 3 public: 4 float x; 5 float y; 6 float angle; // the player's angle, or heading 7 float speed; // the player's current speed 8 9 float turn_speed; // a constant 10 float walk_speed; // a constant 11 12 player_class() 13 { 14 x = 0.0f; 15 y = 0.0f; 16 angle = 0.0f; 17 speed = 0.0f; 18 19 turn_speed = 0.001f; // don't know about this, you might want to try a larger or smaller number 20 walk_speed = 5.0f; // expirement with this one too 21 } 22 23 void turn_right() { angle += turn_speed; } 24 void turn_left() { angle -= turn_speed; } 25 void walk() { speed = walk_speed; } 26 void stop_walking() { speed = 0.0f; } 27 28 void update() 29 { 30 x += cosf(angle) * speed; 31 y += sinf(angle) * speed; 32 } 33 }; 34 35 player_class player;

so in your logic loop do something like

```if (key[KEY_RIGHT]) player.turn_right();
if (key[KEY_LEFT]) player.turn_left();
if (key[KEY_UP]) player.walk();
if (!key[KEY_UP]) player.stop_walking();

player.update();
```

 dylan sack Member #6,590 November 2005 Thanks for the help, and I know I should go back and really figure it out and understand, which i'm about to do. I was just really excited and kinda rushed because I wanted to see some real progress in my game. Feels like i'm getting somewhere (even though I got a lot of help on this part of it ) The thing is, if I declare x and y as floats, then my compiler says when I try to draw the sprite, you can't draw the sprite at a float location. So maybe I could do another x and y that are ints and make them equal to the float x and y's and draw them there? Thanks for all the help btw guys.
 Mark Oates Member #1,146 March 2001 ```float f; int i = (int)f; ``` you have to 'cast the float as an int'
 dylan sack Member #6,590 November 2005 Thanks for all the help, it works perfectly. I'm pretty sure I can figure out rotating the sprite as it turns by myself. It works perfectly besides that. I'm going to sit out a while and just read the code over and over untill I viualize how it perfectly works in my head.
 Mark Oates Member #1,146 March 2001 haha, ah yes. I know the feeling. It's like taking a dump after being constipated for a long time. "I just want to take a break for a while"
 dylan sack Member #6,590 November 2005 Yea, but then you get constipated again coughrotatespriteisdumbcough and you must learn from your past and get through it on your own :O
 Mark Oates Member #1,146 March 2001 otatespriteisdumb?... Oates' Sprite is Dumb!? YOU DON'T LIKE MY AVATAR!!!?!? ...just kidding.
dylan sack
Member #6,590
November 2005

hey I have one last question , how come this rotate sprite thingy isn't working. It compiles perfectly, and I have no idea why it's not rotating with the turning function. By all means it should, I know the problem isn't it getting drawn cause I tried it with the x and y a little offset and it showed up, it just doesn't rotate...

 1 class player_class 2 { 3 public: 4 float x, y; 5 float speed; // players current speed 6 float angle; // players angle or direction facing 7 8 float turn_speed; // a constant 9 float walk_speed; // a constant 10 BITMAP *robot; 11 bool boost; 12 13 player_class() 14 { 15 x = 0.0f; 16 y = 0.0f; 17 angle = 0.0f; 18 speed = 0.0f; 19 20 turn_speed = .07f; 21 walk_speed = 1.0f; 22 } 23 24 void turn_right() { angle += turn_speed; } 25 void turn_left() { angle -= turn_speed; } 26 void walk() { speed = walk_speed; } 27 void stop_walking() { speed = 0.0f; } 28 29 void update() 30 { 31 x += cosf(angle) * speed; 32 y += sinf(angle) * speed; 33 } 34 35 }; 36 player_class player; 37 //rotate stuff 38 void rotate() { 39 int x = int(player.x); 40 int y = int(player.y); 41 fixed angle = fixed(player.angle); 42 } 43 44 45 void logic() { 46 //more rotate stuff 47 48 if (key[KEY_D]) {player.turn_right(); rotate();} 49 if (key[KEY_A]) {player.turn_left(); rotate();} 50 if (key[KEY_W]) {player.walk();} 51 if (!key[KEY_W]) {player.stop_walking();} 52 53 player.update(); 54 55 if (key[KEY_SPACE]) {player.boost = true;} 56 if(player.boost == true) {player.walk_speed = 2;} 57 if (!key[KEY_SPACE]) {player.boost = false;} 58 if(player.boost == false) {player.walk_speed = 1;} 59 }

I have no idea why coding/life hates me..

 Mark Oates Member #1,146 March 2001 what does your rotate sprite function look like?
 Johan Halmén Member #1,550 September 2001 Your code said: ```//rotate stuff 1: void rotate() { 2: int x = int(player.x); 3: int y = int(player.y); 4: fixed angle = fixed(player.angle); } ``` This function seems to be just a separate function, not a member of the class, right? In this function you declare the variables x, y and angle. These variables live only inside the function. In line 2, x is declared and gets its value from player.x, which implies that player is a global object. player.x itself is not changed, not truncated or rounded or anything. After line 4 all three variables, x, y, and angle come to a peaceful death and won't affect anything else in your program.In my former post I tried to point out a very similar thing. It looks like you're not clear on how functions work and where local variables and global variables live (the scope of the variables).What comes to casting, I have a bad habbit of not casting floats to ints before drawing. I get lots of compiler warnings, but they are only warnings. The program still works. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.
Tobias Dammers
Member #2,604
August 2002

Always treat warnings as errors. Best case, they are a sign that you are debugging (and have commented out some code). Worst case, they are causes for real errors or bugs. Semi-bad case, they show bad style.
That said, a plain cast, IIRC, just cuts off the fractional part of the float. This is not a problem in this case, but when it comes to tile-based collision detection, for example, it can produce nasty bugs. Both -0.8f and 0.8f evalutate to 0. I prefer throwing in an extra floor():

```float f = some_number_you_choose;
int i = (int)floor(f);
```

@dylan: You need to understand the concept of 'scope'. The scope of a variable is the part of the code during which it is valid. There are, basically, 4 kinds of variables in C++:
- Global variables. These are declared outside of all {} braces, that is, outside of all functions, classes, structs, etc. They are valid everywhere in the program. You can mark them as "static", making them available in the current .cpp only.
- Local variables. Declared inside a block of {} braces, typically a function body, but occasionally, a loop body. Loop variables declared on-the-fly, e.g. in a for() loop, are also valid inside the loop only. On some rare occasions, a {} pair is inserted into a block of code for the sole purpose of creating a scope for a few variables. Usually though, such practise is a sign of bad style, and a dedicated function would be more appropriate.
- Member variables. Variables declared inside a class or struct. Each instance of the class will produce its own instance of the variable, and by default, the variable will only be valid in member functions of the class. Public member variables can be accessed through the . operator (e.g. foo.bar) and the shortcut -> operator (e.g. foo->bar which is equivalent to (*foo).bar).
- Function parameters. A named function parameter works like a variable and is valid for the entire function body.

Any two variables may have the same name, provided their scopes don't overlap. It is even possible to have variables with identical names whose scopes overlap (but are not identical), but this causes a whole bunch of problems and is generally strongly advised against.

Example:

 1 int i_am_global; 2 3 void some_function(int param1) { 4 int a; 5 6 for (int i = 0; i < 10; ++i) { 7 if (rand()) 8 a += param1; 9 } // scope of int i ends here. 10 i_am_global = do_something_with(a); 11 } // scope of int a and int param1 ends here. 12 13 void some_other_func(int param1) { 14 /* note that param1 in this function and param1 in some_function() are completely 15 unrelated. */ 16 i_am_global = do_something_with(param1); 17 // ...i_am_global, however, refers to the same variable throughout the entire program. 18 } // scope of param1 ends here

---
Me make music: Triofobie
---
"We need Tobias and his awesome trombone, too." - Johan Halmén

dylan sack
Member #6,590
November 2005

Ok considered what you guys said a bit, and have revised my code.. now it er.. doesn't work still, but i'm pretty sure I stay inside my scopes hah. Anyway, i'm going to post my code again, how about this time you could all just like.. hint towards what i'm supposed to do so I can figure out something on my own for once heh. Anyway, at least i've learned a lot from this about coding in general, right?

 1 int boostenergy = 100; 2 3 class player_class 4 { 5 public: 6 float x, y; 7 float speed; // players current speed 8 float angle; // players angle or direction facing 9 10 float turn_speed; // a constant 11 float walk_speed; // a constant 12 BITMAP *robot; 13 bool boost; 14 15 player_class() 16 { 17 x = 0.0f; 18 y = 0.0f; 19 angle = 0.0f; 20 speed = 0.0f; 21 22 turn_speed = .06f; 23 walk_speed = 1.0f; 24 } 25 26 void turn_right() { angle += turn_speed; } 27 void turn_left() { angle -= turn_speed; } 28 void walk() { speed = walk_speed; } 29 void stop_walking() { speed = 0.0f; } 30 //ROTATE junk. 31 void rotate_right() { 32 int x = int(x); 33 int y = int(y); 34 fixed angle = fixed(angle); 35 int turn_speed = int(turn_speed); 36 angle += turn_speed; 37 rotate_sprite(buffer, robot, y, x, angle); 38 } 39 void rotate_left() { 40 int x = int(x); 41 int y = int(y); 42 fixed angle = fixed(angle); 43 int turn_speed = int(turn_speed); 44 angle -= turn_speed; 45 rotate_sprite(buffer, robot, x, y, angle); 46 } 47 48 void update() 49 { 50 x += cosf(angle) * speed; 51 y += sinf(angle) * speed; 52 } 53 54 }; 55 player_class player; 56 57 58 59 void logic() { 60 //rotate logic 61 if (key[KEY_D]) {player.turn_right(); player.rotate_right();} 62 if (key[KEY_A]) {player.turn_left(); player.rotate_left();} 63 if (key[KEY_W]) {player.walk();} 64 if (!key[KEY_W]) {player.stop_walking();} 65 66 if (key[KEY_SPACE]) {player.boost = true;} 67 if(player.boost == true && boostenergy > 0) {player.walk_speed = 2; boostenergy -=1;} 68 if (!key[KEY_SPACE] || boostenergy <= 0) {player.boost = false;} 69 if(player.boost == false) {player.walk_speed = 1; boostenergy+=1;} 70 71 player.update(); 72 } 73 74 75 void draw() { 76 int x = int(player.x); 77 int y = int(player.y); 78 acquire_screen(); 79 draw_sprite(screen, buffer, 0,0); 80 draw_sprite(buffer, bg, 0, 0); 81 draw_sprite(buffer, player.robot, x, y); 82 release_screen(); 83 } 84 //in main loop 85 clear_keybuf(); 86 draw(); 87 logic(); 88 player.update();

 Onewing Member #6,152 August 2005 Quote: doesn't work still What "doesn't work still"? The rotation? What is it doing? Anyways, where did you learn to do classes? I'm not implying anything, other than I get the feeling you don't completely understand them.BTW, weren't you working on a side-scoller? How did that turn out? ------------Solo-Games.org | My Tech Blog: The Digital Helm
 Go to: Allegro Development Installation, Setup & Configuration Allegro.cc Comments Off-Topic Ordeals The Depot Game Design & Concepts Programming Questions Recent Threads