Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » moving character diagonally, instead of walking x direction first, then y...

This thread is locked; no one can reply to it. rss feed Print
moving character diagonally, instead of walking x direction first, then y...
red-dragon
Member #7,722
August 2006

Hey guys,
I've made more progress. Little Link can now move to the spot where the user left clicks. However, it's not the most sophisticated way. As it stands, I compute how many units on the x axis he has to move, then how many y. Then, I make him move, say +5 units on x axis, and then -5 on y. So, Little Link walks to the right, then up.

I would like to change this so that he moves diagonally to that point. If user has left-clicked in northeast direction, I want him to move directly in that direction. Hope I'm being clear here.

In updatesprite I have this:

1...
2..
3.
4 //Note: num2 = 3;
5 
6 //northeast
7 case 5:
8 mario->x += num2;
9 mario->y -= num2;
10 break;
11
12 //souteast
13 case 6:
14 mario->x += num2;
15 mario->y += num2;
16 break;
17
18 //southwest
19 case 7:
20 mario->x -= num2;
21 mario->y += num2;
22 break;
23
24 //northwest
25 case 8:
26 mario->x -= num2;
27 mario->y -= num2;
28 break;

Part of calculate_position:

     if(mario->x < x)  //&& (mario->y > y))
     {          
          if(mario->y > y)
          {
                      //Link will move northeast
                      ydir = 5;
                      ynew = mario->y - y;                      
          }
...
..
.

In while loop in main, if left-click is detected, do this:

1...
2..
3.
4 else if(mario->dir == 5)
5 ynew = ynew/3;
6
7 for(y1 = 0; y1<ynew; y1++)
8 {
9 erasesprite(screen, mario);
10 updatesprite(mario);
11 move_character();
12 acquire_screen();
13 draw_character_mario();
14 release_screen();
15 rest(50);
16 }

OK, so variable names might not make sense since I'm changing code, i.e. Mario should be Link, ynew will be changed to new_dir if I can make this diagonal thing work.

If I run this code, Link walks a perfect diagonal line, even though the cursor might be might be ten units to the left.

Make sense? Hope so; if not, ask away. Or just give me general advice at least ;)

Rick
Member #3,572
June 2003
avatar

Try vector movement. Do a forums search for vector movement.

========================================================
Actually I think I'm a tad ugly, but some women disagree, mostly Asians for some reason.

Steve Terry
Member #1,989
March 2002
avatar

Simple trig should give you the direction angle, from there you can calculate deltax and deltay.

___________________________________
[ Facebook ]
Microsoft is not the Borg collective. The Borg collective has got proper networking. - planetspace.de
Bill Gates is in fact Shawn Hargreaves' ßî+çh. - Gideon Weems

Dustin Dettmer
Member #3,935
October 2003
avatar

double x, y;
double direction, speed;
...
x += sin(direction) * speed;
y += cos(direction) * speed;

direction ranges 0 to (2 * M_PI)
speed ranges 0 to some big number (probably less then 5 or so)

red-dragon
Member #7,722
August 2006

hey Steve, it's been a long time for me since I did simple trig.

Dustin, thanks for the help. Though for the sin, cos, and M_PI (that's pi, right, ha?), is there a library I need to include? If I'm missing the point, please elaborate. Really appreciate your help, thanks.

Dustin Dettmer
Member #3,935
October 2003
avatar

Use

#include <cmath>

red-dragon
Member #7,722
August 2006

Dustin,
I've put this code in, but it's not working properly. At best, when I clicked northeast, Link walked straight then a little curve. Weird.

So, here come the questions:
double x, y: this is Link's x, y coords, right?

"direction rangest 0 to (2 * M_PI)"... I'm a bit lost here. In my code I have the normal 8 directions.

Sorry if I seem a bit dense. Explain away.

Dustin Dettmer
Member #3,935
October 2003
avatar

sin and cos return a number ranging 0 to 1
sin and cos take an input value ranging 0 to (2 * M_PI). *
If you input 0 for sin you get 1 and cos you get 0. If you imagine the value of 0 as 'going right', this is correct. The x should increment and the y should not.
If you input (M_PI / 2) sin will give you 0 and cos will give you 1. Remember we're incrementing x by sin and y by cos. So this means 'go up'.
If you keep going in increments of (M_PI / 4), you'll head in four straight forward directions, right, up, left, and down.

The beauty of this system is that it takes care of all the in-between values, so (M_PI / 4) will go up and right.

Be careful though, cause the screen is actually upside down (ie quadrant 4). Up might easily come out as down.

Quote:

"direction rangest 0 to (2 * M_PI)"... I'm a bit lost here. In my code I have the normal 8 directions.

ok so if directions is a value ranging 0 to 8, you can pass it into sin and cos like so:

x += sin(directions * (2 * M_PI) / 8) * some_value;
y += cos(directions * (2 * M_PI) / 8) * some_valie;

[disclaimer]

  • you can actually pass values above (2 * M_PI) and below 0 and sin / cos will be just fine with it, but its easier conceptually to pretend they can only be in that range.

[edit]
I mixed up the return values for sin / cos, they're wrong.

Owell, hopefully this will clarify why you do that anyway.

Paul whoknows
Member #5,081
September 2004
avatar

Can you post your code? or perhaps a binary? so we can see what you are doing.
I am not sure what you really need, but if I am not wrong, perhaps the Distance formula between 2 points is what you need.
Like I said, post your code or a binary file! that will help a lot!

____

"The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner.

Dustin Dettmer
Member #3,935
October 2003
avatar

Quote:

Can you post your code? or perhaps a binary? so we can see what you are doing.
I am not sure what you really need, but if I am not wrong, perhaps the Distance formula between 2 points [purplemath.com] is what you need.
Like I said, post your code or a binary file! that will help a lot!

I believe he wants to move his character by an arbitrary angle, which the distance formula cant do.

Distance formula is usefull for spherical collision detection.

Paul whoknows
Member #5,081
September 2004
avatar

sorry!, I meant the secant line between 2 points, using it little link would walk in a straight line from his current position to where the user left clicks.

____

"The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner.

Dustin Dettmer
Member #3,935
October 2003
avatar

Ah yes, it would be usefull for that too :)

red-dragon
Member #7,722
August 2006

Paul,
are you talking about the d = sqrt(((x2-x1)^2) + ((y2-y1)^2)) formula?

ok, so that gives me d.... where would I go from here? ...what do I do with it? how will little ol' link walk diagonally?

I have code right here: code
It might not compile right now, but only kuz I'm cleaning code up a bit. He moves in x, then y. You'll see.

Steve Terry
Member #1,989
March 2002
avatar

double x, y;
double direction, speed;
...
x += sin(direction) * speed;
y += cos(direction) * speed;

Here all you need to determine is direction which you can get in radians if you use the nice little function atan2.

#include <math.h>
double direction = atan2(mouse_y - characterY, mouse_x - characerX);

Hope that helps, basically atan2 will return in radians the angle between two given points. Of course give a good speed variable, something less than 1.0 that will move your character smoothly between the two points. Now you have an angle in radians you can also convert that to a fixed point degree angle to pass into rotate_sprite so your character rotates at that angle as well.

___________________________________
[ Facebook ]
Microsoft is not the Borg collective. The Borg collective has got proper networking. - planetspace.de
Bill Gates is in fact Shawn Hargreaves' ßî+çh. - Gideon Weems

Dustin Dettmer
Member #3,935
October 2003
avatar

Quote:

d = sqrt(((x2-x1)^2) + ((y2-y1)^2)) formula?

Instead, you should use this code:

#ifdef MSVC
#define hypot _hypot
#endif
...
d = hypot(x2 - x1, y2 - y1);

Some CPUs may implement hypot as an instruction which would be way faster then the 6 or so instructions of the pre-mentioned method.

Paul whoknows
Member #5,081
September 2004
avatar

Quote:

Paul,
are you talking about the d = sqrt(((x2-x1)^2) + ((y2-y1)^2)) formula?

No no, I meant the secant line between 2 points

{"name":"96215157b42adf1a03b4da860ca80770.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/e\/de5da42bd94caec2d100fcc40dcfb8ef.png","w":261,"h":39,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/e\/de5da42bd94caec2d100fcc40dcfb8ef"}96215157b42adf1a03b4da860ca80770.png

____

"The unlimited potential has been replaced by the concrete reality of what I programmed today." - Jordan Mechner.

Go to: