Sprite Movement Angle Or Move To Specific Pixel


Squidge said:
Whatever you do, don't copy that code verbatim, it's meant as an example only. Hopefully your release code will use pre-computed tables.
Agreed, it's ok to use for playing with/prototyping but for serious stuff you need to use pre-computed tables of sin and/or cos values otherwise it just won't be fast enough on the gp2x.

Sphinxter said:
That would be irrational.
Why?
 
Last edited by a moderator:
Squidge said:
Whatever you do, don't copy that code verbatim, it's meant as an example only. Hopefully your release code will use pre-computed tables.
In addition to this you could also write functions that let you use the lookup table like you would use the STL maths sin cos etc functions...
 
Last edited by a moderator:
These are the functions I use (my own code):

CODE
int get_distx(int angle, int dist)
{
return (int)( dist * sin( ( angle + 90000 ) * ( pi / 180000.0 ) ) );
}

int get_disty(int angle, int dist)
{
return (int)( dist * cos( ( angle + 90000 ) * ( pi / 180000.0 ) ) );
}


They add the distance to x and y for the specified angle...
Is this overly complicated?
Any way to optimize these functions?
 
Quiest said:
These are the functions I use (my own code):

CODE
int get_distx(int angle, int dist)
{
return (int)( dist * sin( ( angle + 90000 ) * ( pi / 180000.0 ) ) );
}

int get_disty(int angle, int dist)
{
return (int)( dist * cos( ( angle + 90000 ) * ( pi / 180000.0 ) ) );
}
They add the distance to x and y for the specified angle...
Is this overly complicated?
Any way to optimize these functions?

Using the 90000 constant (which I assume really means 90 degrees) you have swapped the meaning of sin and cos so you can get rid of the 900000s and just swap them back. I am slightly concerned with all the zeros, do you really need 1/1000 th of a degree acuracy? I would doubt it but that said as long as you are consistant it'll be fine. The compiler should pre-calculate the (pi / 180000.0) so that's not an issue.

The problem, in general, is that trig functions are quite slow and that goes doubly for the gp2x without floating point hw support. So what you can do is to create an array in memory of sines and cosses and fill it at the start (or even before) then you can just get the values from the table.
CODE

global double sin_table[360]
global double cos_table[360]

func my_sin(angle)
return sin_table[angle]

func my_cos(angle)
return cos_table[angle]

func init_trig()
for i from 0 to 359
sin_table = sin(i * (pi / (float)180);
cos_table = cos(i * (pi / (float)180);



translating the above to a real programming language is left as an execise to the reader ;)
as is finding a way to achieve this without having to resort to floats.

hint and hint
 
Last edited by a moderator:
motorollin said:
That works! Thanks :D
Now, to work out *why* it works, so I understand for next time...

Thanks again!
squidge posted this link:
http://en.wikipedia.org/wiki/Trigonometry

it wasn't a joke. everything you need to know is in there.

picture a triangle with one leg going in the +x direction, and one leg going in the +y direction, from the origin. the third leg will connect the endpoints of the other two. let's say from (0,4) to (5,0).

so our triangle has points A(0,0), B(0,4), and C(5,0). our sprite is at point B. we need it at C. so we either do x-4 and y+5, or we move along diagonal line BC. but what is the angle of BC?

sine, cosine and tan are the functions will tell us this angle if we know the ratio of the lengths of the sides. since our "sides" are -4 and +5, we can easily get the angle of a line that will get us to the same place.

only problem is, arm cpu is not designed for trig and floating point, it is designed to do simpler math very efficiently at the cost of more complex stuff being slower. so it's best to make a table of the sin & cos functions rather than computing them at runtime.

well, you do compute them at runtime but you do it during loading, like the good example charlieb made.
 
Last edited by a moderator:
Quiest said:
These are the functions I use (my own code):

CODE
int get_distx(int angle, int dist)
{
return (int)( dist * sin( ( angle + 90000 ) * ( pi / 180000.0 ) ) );
}

int get_disty(int angle, int dist)
{
return (int)( dist * cos( ( angle + 90000 ) * ( pi / 180000.0 ) ) );
}
They add the distance to x and y for the specified angle...
Is this overly complicated?
Any way to optimize these functions?

Don't use angles in degrees. Use angles in 256ths/512ths/1024ths of a revolution. Then use table-based sin/cos that returns a fixed-point value. You only need one table to calculate both and the table only needs to cover 1/4 of a revolution. Look at the symmetries of the sine/cosine functions to see how this can work.
 
Last edited by a moderator:
charlieb said:
Squidge said:
Whatever you do, don't copy that code verbatim, it's meant as an example only. Hopefully your release code will use pre-computed tables.
Agreed, it's ok to use for playing with/prototyping but for serious stuff you need to use pre-computed tables of sin and/or cos values otherwise it just won't be fast enough on the gp2x.

Sphinxter said:
That would be irrational.
Why?


Floating point vs. integer.
 
Last edited by a moderator:
Sphinxter said:
charlieb said:
Agreed, it's ok to use for playing with/prototyping but for serious stuff you need to use pre-computed tables of sin and/or cos values otherwise it just won't be fast enough on the gp2x.
Sphinxter said:
That would be irrational.
Why?

Floating point vs. integer.

Oh right yes, you can also go the rational numbers route where instead of using integers or fixed/floating points you store everything as a ratio of two integers.
Also a reasonable choice which I have yet to try.
 
Last edited by a moderator:
The +90000 does not swap it, it just makes it this way:
CODE

90°
180° + 0°
270°


leaving out the +90000 and swapping sin with cos gives:
CODE

270°
180° + 0°
90°


which wouldnt be that bad, but is there any standart, where the
0° should be on screen and if it should turn clockwise or anti clockwise?
 
Quiest said:
The +90000 does not swap it, it just makes it this way:
CODE

90°
180° + 0°
270°
leaving out the +90000 and swapping sin with cos gives:
CODE

270°
180° + 0°
90°



Yep you're quite right, it's a direction change (from the sine/cos swap) and a rotation of 90° from north (+ 90000).
Quiest said:
which wouldnt be that bad, but is there any standart, where the
0° should be on screen and if it should turn clockwise or anti clockwise?
There is a standard: the compass: 0° is north and clockwise from there 90° is east, 180° is south and 270° is west. Of course in computer graphics world up is down (since the coordinate system starts in the top left) so you can really do what you want as long as you are consistant. If you're writing a side scroller it would be a reasonable choice to have 0° pointing right. I would still go with clockwise because then it's just a compass pointing east but as I said the key point is consistency.

cherlieb
 
Last edited by a moderator:
Thanks for the info, I think I will stick to it then, cause its the way I`m used to from Fenix.
And thanks for the lookup table hint, using this now.
 
Back
Top