Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Trig question

This thread is locked; no one can reply to it. rss feed Print
Trig question
ngiacomelli
Member #5,114
October 2004

I have two sets of locations: x, y and t_x, t_y. When something is fired it is spawned at x, y and travels toward t_x, t_y. How do I increment the change to x,y so that eventually the object will reach t_x and t_y?

Richard Phipps
Member #1,632
November 2001
avatar

1. add dx and dy variables.
2. dist = sqrt(t_x - x * t_x - x + t_y - y * t_y - y);
3. dx = (t_x - x) / dist;
4. dy - (t_y - y) / dist;

ngiacomelli
Member #5,114
October 2004

I take it I would then add dx and dy to x and y?

Richard Phipps
Member #1,632
November 2001
avatar

Arthur Kalliokoski
Second in Command
February 2005
avatar

I believe line 4 "dx - (t_y - y) / dist" should be "dx = (t_y - y) / dist" (typo)

And if the object doesn't move one unit per logic cycle you'd have to multiply it by the units moved per cycle.

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

Richard Phipps
Member #1,632
November 2001
avatar

ngiacomelli
Member #5,114
October 2004

I may be missing something here. Is dx and dy gradually increased over a period of time? Because at the moment the values for dx and dy seem to be coming up with 0, 0. EDIT: sqrt deals in double's. Will I have to cast back for blitting, etc?

1void render_attacks(BITMAP *bmp) {
2
3 int i=0;
4
5 for(i = 0; i < MAX_ATTACK_S; i++ ) {
6
7 if( gAttacks<i>.state ) {
8 line( bmp, gAttacks<i>.x, gAttacks<i>.y, gAttacks<i>.t_x, gAttacks<i>.t_y, makecol(255,255,255));
9 }
10
11 }
12
13}
14 
15void attack_increment(void) {
16
17 int i=0, dist=0;
18
19 for(i = 0; i < MAX_ATTACK_S; i++ ) {
20
21 if( gAttacks<i>.state ) {
22 
23 dist = sqrt(gAttacks<i>.t_x - gAttacks<i>.x * gAttacks<i>.t_x - gAttacks<i>.x + gAttacks<i>.t_y - gAttacks<i>.y * gAttacks<i>.t_y - gAttacks<i>.y);
24 gAttacks<i>.x += ((gAttacks<i>.t_x - gAttacks<i>.x) / dist);
25 gAttacks<i>.y += ((gAttacks<i>.t_y - gAttacks<i>.y) / dist);
26 
27 }
28
29 }
30
31}

Richard Phipps
Member #1,632
November 2001
avatar

You have dist as an int when it should really be a float. You'll need to use floats for the x and y values of your sprites as well.

ngiacomelli
Member #5,114
October 2004

Quote:

You have dist as an int when it should really be a float.

Should x, y and t_x, t_y become floats also?

Richard Phipps
Member #1,632
November 2001
avatar

ngiacomelli
Member #5,114
October 2004

With float values the code does nothing! dist also seems to be giving out junk values.

1 
2struct gAttack {
3
4 int state, type;
5 float x, y, t_y, t_x;
6
7} gAttacks[MAX_ATTACK_S];
8 
9void render_attacks(BITMAP *bmp) {
10
11 int i=0;
12
13 for(i = 0; i < MAX_ATTACK_S; i++ ) {
14
15 if( gAttacks<i>.state ) {
16 line( bmp, gAttacks<i>.x, gAttacks<i>.y, gAttacks<i>.t_x, gAttacks<i>.t_y, makecol(255,255,255));
17 }
18
19 }
20
21}
22 
23void attack_increment(void) {
24
25 int i=0; float dist=0;
26
27 for(i = 0; i < MAX_ATTACK_S; i++ ) {
28
29 if( gAttacks<i>.state ) {
30 
31 dist = sqrt(gAttacks<i>.t_x - gAttacks<i>.x * gAttacks<i>.t_x - gAttacks<i>.x + gAttacks<i>.t_y - gAttacks<i>.y * gAttacks<i>.t_y - gAttacks<i>.y);
32 gAttacks<i>.x += ((gAttacks<i>.t_x - gAttacks<i>.x) / dist);
33 gAttacks<i>.y += ((gAttacks<i>.t_y - gAttacks<i>.y) / dist);
34 
35 }
36
37 }
38
39}
40 
41void local_add_attack( int type, float x, float y, float t_x, float t_y ) {
42
43 int i=0;
44 
45 for(i = 0; i < MAX_ATTACK_S; i++ ) {
46
47 if( !gAttacks<i>.state ) {
48 gAttacks<i>.state = 1;
49 gAttacks<i>.type = type;
50 gAttacks<i>.x = x;
51 gAttacks<i>.y = y;
52 gAttacks<i>.t_x = t_x;
53 gAttacks<i>.t_y = t_y;
54 
55 break;
56 }
57
58 }
59
60}

Richard Phipps
Member #1,632
November 2001
avatar

Not sure why it's not working. Blah, just use some sin/cos/tan:

 float dx, dy, angle;

 dx = x - t_x;
 dy = y - t_y;
  
 angle = atan2(dy, dx);

 dx = cos(angle);
 dy = sin(angle);

 gAttacks<i>.x += dx;
 gAttacks<i>.y += dy;

Frank Drebin
Member #2,987
December 2002
avatar

i use an angle to the target like this:

angle=atan2(y_t-y,x_t-x);

x+=cos(angle);
y+=sin(angle);

gnolam
Member #2,030
March 2002
avatar

1)

Quote:

gAttacks<i>.t_x - gAttacks<i>.x * gAttacks<i>.t_x - gAttacks<i>.x + gAttacks<i>.t_y - gAttacks<i>.y * gAttacks<i>.t_y - gAttacks<i>.y

Should be:(gAttacks<i>.t_x - gAttacks<i>.x)*(gAttacks<i>.t_x - gAttacks<i>.x) + (gAttacks<i>.t_y - gAttacks<i>.y)*(gAttacks<i>.t_y - gAttacks<i>.y)You know, like the Pythagorean theorem. :P
(Phipps made the original mistake)

2) Don't recalculate dx and dy every loop cycle. Compute them once.

3) Make sure you avoid dividing with zero (if (dist > 0) ...).

4) Don't use the bad sin/cos solutions. ;)

--
Move to the Democratic People's Republic of Vivendi Universal (formerly known as Sweden) - officially democracy- and privacy-free since 2008-06-18!

NyanKoneko
Member #5,617
March 2005
avatar

You could compute the X / Y vectors and normalize them. Then you have a ratio for far on the x and y axis your sprite should move each iteration.

Think in terms of triangles...

(x,y)+
  |      + c
a |         +
  |----------(t_x,t_y)     -> x vector
        b
  |
  V
 Y Vector

To normalize the x and y vector, divide each by the hypotenuse of the triangle.

Example:

  (t_y - y)
---------------
sqrt(a^2 + b^2)

Pretty simple huh? Since it's normalized, just multiply the x and y vector by a constant to make it go that speed.

For example, if you want to move the object 5 pixels per frame...

object.x = normalized_vector.x * 5;
object.y = normalized_vector.y * 5;

Indeterminatus
Member #737
November 2000
avatar

On another note, I don't see you initialize values anywhere. Of course, if you already do that you can ignore me now saying to initialize, especially the int state.

_______________________________
Indeterminatus. [Atomic Butcher]
si tacuisses, philosophus mansisses

Johan Halmén
Member #1,550
September 2001

Then there's do_line()but that function returns each int coordinate of the pixels of a line drawn between the start point and end point. Only trouble is that you get different number of pixels on different directions even if the length is the same.

It includes a pointer parameter to a call-back function, which you could set to create an array of all the coordinates you travel through. I once made a class that does something like that, without the callback and array stuff.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.

Go to: