gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Sprite velocity and Frame rate

#18223 - gbawiz - Mon Mar 22, 2004 7:04 pm

Hello all,
My subject is one which is still causing me confusion, I have gained a bit more understanding of the subject of Sprite velocity and framerate.
My first attempt at incorporating variable speeds into my sprites:

Normally my sprite positions are INT variables (i.e. int mysprite.x =value) but when I changed my INTs to FLOATs I noticed a huge slowdown in my app, close to no movment at all!
1.) Is this typical of using FLOATs or is there a problem with my app?

What I was planning was changing my sprite movement routines to look something like this:

mysprite.x += period * velocity * direction

Since the GBAs framerate is 60hz then 1/60 is the period since last frame update and the velocity can have any number between 0 and 60. because my sprite should only move a maximum of one pixel at a time.
direction is either -1 , 0 , +1 which is LEFT, Still, RIGHT.

2.) is this a good method of moving sprites?

Many thanks
GbaWIZ

#18227 - poslundc - Mon Mar 22, 2004 8:06 pm

gbawiz wrote:
Normally my sprite positions are INT variables (i.e. int mysprite.x =value) but when I changed my INTs to FLOATs I noticed a huge slowdown in my app, close to no movment at all!
1.) Is this typical of using FLOATs or is there a problem with my app?


From the Beginner's FAQ:

Quote:
Avoid floating point. Don't use floating-point arithmetic unless you absolutely have to. The GBA has no dedicated floating-point hardware, and all floating-point operations have to be run in a slow software FPU emulator. Use fixed-point arithmetic instead.


Dan.

#18228 - Gopher - Mon Mar 22, 2004 9:03 pm

Fixed-point math seems a little tricky at first; it's actually pretty simple, though. Just divide your x and y positions by some fixed number before drawing them. I'd recomend picking a power of two, like 128 or 256.

//set pos to ScrPosX, ScrPosY (Screen position)
XPos=ScrPosX*256;
YPos=ScrPosY*256;


//calc the screen position from the stored position
ScrPosX=PosX/256;
ScrPosY=PosY/256;


//check bounds
if (PosX<0 || PosX>=240*245)
...
if (PosY<0 || PosY>=160*256)
...

[/url]
_________________
"Only two things are infinite: the universe, and human stupidity. The first is debatable." -Albert Einstein

#18229 - poslundc - Mon Mar 22, 2004 9:13 pm

Gopher wrote:
Fixed-point math seems a little tricky at first; it's actually pretty simple, though. Just divide your x and y positions by some fixed number before drawing them. I'd recomend picking a power of two, like 128 or 256.


Fixed-point math becomes awfully impractical on a binary machine if you don't use a power of two for your multiplier.

You are better off using the bitshift operator instead of multiplication/division; this lets you directly keep track of your decimal point (VERY important when you start doing multiplication and division) and doesn't rely on the compiler to optimize your transformations into shifts.

Google on fixed-point math

Dan.

#18230 - Gopher - Mon Mar 22, 2004 9:20 pm

I'm aware of that, but I try to explain things in the simplest terms nessicary. If someone asks for a lesson in basic C/C++, it's not always beneficial to give them a lecture on optimization. :)
_________________
"Only two things are infinite: the universe, and human stupidity. The first is debatable." -Albert Einstein

#18234 - poslundc - Mon Mar 22, 2004 10:03 pm

Gopher wrote:
I'm aware of that, but I try to explain things in the simplest terms nessicary.


You find fixed-point math easier with multiplication/division instead of bitshifts?

I think it would drive me insane.

Dan.

#18235 - Gopher - Mon Mar 22, 2004 10:10 pm

<sigh>

Explaining the bitshift method requires an understanding of binary numbers. I suppose you could just accept bitshifting as a magical black-box operator that divides/multiplies by powers of two, but even then it's introducing an element beyond the issue itself. I wasn't really explaining fixed-point math in general, just telling him how to apply it to his specific question.
_________________
"Only two things are infinite: the universe, and human stupidity. The first is debatable." -Albert Einstein

#18247 - gbawiz - Tue Mar 23, 2004 1:51 am

Hello and thanks for the response,
So to use fix point math then you convert the number into a higher one, do the necessary program logic then when finished you convert the number back again?

If so then do you need to translate all variables which are used in the process, i.e when moving a sprite on screen:

sprite_x += velocity*direction

would you have to convert all three parameters this way, perform the above multiplication then translate back?
Also are these INTs ?

#18248 - Gopher - Tue Mar 23, 2004 2:02 am

Ok, with fixed-point math, say your numbers have 8 bits of precision.
You have one integer Time and two fixed-point integers xpos and xvel.

xpos+=xvel*time

time is not a fixed-point number, so no extra conversion would be nessicary. (the usual >>8 applies to get screen coordinates from xpos)
However, if you multiply two fixed-points

xpos*xvel // never mind why, just think about the numbers

since each is implicitly multiplied by 256, the result is multiplied by 65536 (256*256) so you must divide by 256 ( >> 8). Careful here of overflows. If your numbers are too large and are overflowing, you can shift each right by 4 first

(xpos>>4)*(ypos>>4)

this will prevent overflow, but obviously loses 4 bits of precision from the inputs.
_________________
"Only two things are infinite: the universe, and human stupidity. The first is debatable." -Albert Einstein

#18381 - NoMis - Thu Mar 25, 2004 9:30 am

why not use pixel per frame as ur movement unit.
i suggest saving a fixed point value of the position and giving a fixed point pixel per frame value for velocity in x and y direction. you just have to add the values every frame. so you dont need the multiplication wich is slower than the addition.

you then just put the integer part into the register by shifting the value.

if the integerpart gets bigger the sprite moves.

NoMis