Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Integer or float? What to use for logic?

This thread is locked; no one can reply to it. rss feed Print
Integer or float? What to use for logic?
Locutus266
Member #7,638
August 2006

Hello,

I am developing a simple 2D pong clone, that has no scrolling or such. As of now, I am holding x/y coordinates and speed values of paddles or ball in floating point values. To display game objects on the screen, I convert these variables to integers.

This is a simplified version of my main game loop:

1while (!game_over)
2{
3 if (blit_buffer)
4 {
5 //Page flipping
6 show_video_bitmap(screen_buffer);
7 
8 if (screen_buffer == page1)
9 screen_buffer = page2;
10 else
11 screen_buffer = page1;
12 
13 clear_to_color(screen_buffer, black); //Reset memory bitmap to blackness.
14 blit_buffer = 0;
15 }
16 
17 poll_user_input();
18 
19 while (pending_cycles > 0) //Timer at 250 times per sec
20 {
21 //Logic stuff using floating point
22
23 ball.x = ball.x + ball.x_speed; //These are all floats that get converted into integers (pixels) by the drawing functions
24 ball.y = ball.y + ball.y_speed;
25
26 ball.x_spd += 0.01f; //Ball gets faster with time
27 ball.y_spd += 0.01f;
28
29 pending_cycles--;
30 cycles_done++; //Overall cycles done since game startup
31 }
32 
33 //Rendering
34 if (pending_frames > 0) //Timer usually at 60 fps
35 {
36 draw_stuff_to_screen();
37 
38 pending_frames--;
39 blit_buffer = 1;
40 }
41}

Now, I could as easily do all the logic calculations with integers using the "cycles_done" variable and the modulo operator:

1while (pending_cycles > 0) //Timer at 250 times per sec
2{
3 //Logic stuff using floating point
4
5 static int ball_speed = 10; //10 in the beginning
6
7
8 if (cycles_done % ball_speed == 0) //Every tenth cycle, do...
9 {
10 ball.x = ball.x + ball.x_speed; //In this version, x and y speed are -1, 0 or 1
11 ball.y = ball.y + ball.y_speed;
12 }
13
14 if (cycles_done % 5) //every 5th cycle...
15 ball_speed --;
16
17 pending_cycles--;
18 cycles_done++; //Overall cycles done since game startup
19}

Of course, the result wouldn't be exactly the same. But I think using the modulo operator together with cycles_done is a way to time events such as positional updates. What do you think? I'd like your advise...

Is the modulo method, I came up with a common technique and is it advisable concerning performance to use integers or is the floating-point approach a better one?

Thanks for all your suggestions and your time!

Best regards,
Christoph B.

HoHo
Member #4,534
April 2004
avatar

Does your target computers not have a FPU co-processor that you want to use integers? If so then fixed-point would probably be better. I wouldn't use ints for anything with variable speed, they don't have enough accuaricy.

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

ImLeftFooted
Member #3,935
October 2003
avatar

What kind of computer CPU doesn't have a FPU co-processor? Not one I'm going to be programming for any time soon...

I recommend using floating point, it is teh bettar.

Jonatan Hedborg
Member #4,886
July 2004
avatar

Use floats. IF (and only if) your code runs slowly, check it out in a profiler. It will not be the floats fault. Continue to use floats :)

Premature optimization kills creativity!

HoHo
Member #4,534
April 2004
avatar

Quote:

What kind of computer CPU doesn't have a FPU co-processor?

Some starting from 486's they had FPU integrated into the CPU. On older CPU's it was an optional addon.

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

Jonatan Hedborg
Member #4,886
July 2004
avatar

I think that was a rhetorical question HoHo ;)

Locutus266
Member #7,638
August 2006

Thanks for your input so far.

I am using Allegro on a Linux-based handheld called GP2X. It has an ARM CPU and only does software floating point. I have ported my code to use Allegro's fixed point functions, but lately the idea of the modulo thing came to my mind.

Does anybody know, if this technique is widely used?

ImLeftFooted
Member #3,935
October 2003
avatar

I've used it before. But, btw, doesnt a modulo have the same performance hit as a floating point divide anyway?

HoHo
Member #4,534
April 2004
avatar

Quote:

It has an ARM CPU and only does software floating point

Well, thats a whole different story. There indeed floating point can take quite a while to compute. First I'd try to run some profiling on the handheld. From the results you can see how long time is spent in the functions that use floats. If it is too much I'd try replacing them with allegro's fixed-point math. Basically it is quite similar to the modulo thing but more accurate and you won't have to write the code yourself :)

__________
In theory, there is no difference between theory and practice. But, in practice, there is - Jan L.A. van de Snepscheut
MMORPG's...Many Men Online Role Playing Girls - Radagar
"Is Java REALLY slower? Does STL really bloat your exes? Find out with your friendly host, HoHo, and his benchmarking machine!" - Jakub Wasilewski

orz
Member #565
August 2000

I would not recommend the modulo-with-cycles_done aproach. Modulo can be slow (though there's ways to make if faster in some cases; compilers can even figure out some of them, some of the time). Furthermore, there is little benefit to only doing your physics only every X cycles - you could simply slow down the cycle rate instead, from 250 to 50. The only advantage is the ability to have some of your physics run more often than other bits of your physics, as you do there by having ball position update less often than ball speed. But that's only valuable if some of your physics is much slower than the rest and doesn't need updating very often at all.

I would recommend the use of fixed point numbers on CPUs that lack good FPUs. Fixed point can improve performance a lot, and in some cases it can also improve stability and/or accuracy. Unfortunately, it can take more effort, and can produce weird bugs (mainly overflow issues). If your don't need much performance, floating point might work fine.

You might also consider supporting either floating point or fixed point as a compile time option. If you're using C++, this could probably be achieved with a simple typedef for your own numeric type to either Allegro's fixed point class or to the normal floating point type. Something along the lines of:

#define USE_ALLEGRO_FIXEDPOINT
#if defined USE_ALLEGRO_FIXEDPOINT
  typedef fix MyReal;
#else
  typedef float MyReal;
#endif

However, you also have to keep in mind the differences in the angle units (from radians to 256ths), at which point you might add more like this:

#define USE_ALLEGRO_FIXEDPOINT
#if defined USE_ALLEGRO_FIXEDPOINT
  typedef fix MyReal;
  const float RadiansPerAngleUnit_float = 256.0 / (3.14159265358979 * 2);
  const MyReal RadiansPerAngleUnit_real = fix(256.0 / (3.14159265358979 * 2));
  const float AngleUnitsPerRadian_float = (3.14159265358979 * 2) / 256.0;
  const MyReal AngleUnitsPerRadians_real = fix((3.14159265358979 * 2) / 256.0);
#else
  typedef float MyReal;
  const float RadiansPerAngleUnit_float = 1.0;
  const MyReal RadiansPerAngleUnit_real = 1.0;
  const float AngleUnitsPerRadian_float = 1.0;
  const MyReal AngleUnitsPerRadians_real = 1.0;
#endif

Or perhaps numbers for degrees instead if you prefer degrees.

ImLeftFooted
Member #3,935
October 2003
avatar

If posts could receive star ratings, I would give the above post full stars.

Locutus266
Member #7,638
August 2006

Hello orz,

that was very helpful. Thank you for your insight knowledge. I might consider, decreasing the logic timer (to 50 times per sec instead of 250) and increase speeds to compensate.

I am not working with angles, yet. My collision detection approach depends on the ball speed not getting higher than 1 (so it doesn't skip any pixels). I suppose, a solution based on vectors or trajectories would be better / more efficient, but I still have to do some math for that, I think.

Is it advisable to round the values when converting floating point values to on-screen coordinates for drawing?

Also, I do not fully understand your typedef statements. Allegro fixed point values have to be converted to integers using fixtoi() and related functionality, which isn't normally necessary for normal floats. I believe "fixed" and "float" cannot be treated the same way in all situations. For example, you cannot simply add an integer to a fixed point value, or do you?

Best regards,
Christoph B.

orz
Member #565
August 2000

Quote:

If posts could receive star ratings, I would give the above post full stars.

Thanks.

Locutus266:

Quote:

that was very helpful. Thank you for your insight knowledge. I might consider, decreasing the logic timer (to 50 times per sec instead of 250) and increase speeds to compensate.

250 is overkill for most purposes. 100 is quite likely to be more than enough. 50 might be plenty.

Quote:

I am not working with angles, yet. My collision detection approach depends on the ball speed not getting higher than 1 (so it doesn't skip any pixels). I suppose, a solution based on vectors or trajectories would be better / more efficient, but I still have to do some math for that, I think.

Perhaps you don't need trig functions for your game. If so, that will simplify the conversion back and forth between floats and fixed point types.

Quote:

Is it advisable to round the values when converting floating point values to on-screen coordinates for drawing?

Well, the advantages to explicitly rounding are often small, but the only disadvantage is that you have to type a few extra characters.

Several kinds of rounding are common:
1. float -> int (i.e. (int)my_float or int(my_float)) normally rounds towards zero i.e. 1.9 becomes 1, -1.9 becomes -1 (This is slightly obnoxious when a move objects coordinates pass an axi, because the rounding hickups... the object can move almost 2 pixels while still appearing in the same spot instead of the usual almost 1 pixel. Still, a pretty minor issue, not worth noticing in most cases.)
2. fixtoi(fixed) or fix -> int rounds to the nearest integer value, or towards positive infinity if two integers are equally close. i.e. 1.5 becomes 2, 1.49 becomes 1, -1.5 becomes -1, -1.51 becomes -2.
3. Other rounding methods are possible, but require more work and are usually slower. There are a few rounding methods that are faster than the regular ones, but they generally either aren't much faster or have drawbacks, and I'm not going in to them here as you don't really need them and this post will be big enough anyway.

Quote:

Also, I do not fully understand your typedef statements. Allegro fixed point values have to be converted to integers using fixtoi() and related functionality, which isn't normally necessary for normal floats. I believe "fixed" and "float" cannot be treated the same way in all situations. For example, you cannot simply add an integer to a fixed point value, or do you?

The confusion arises because Allegro has two different fixed point types. There is the "fixed" type, which is documented, and uses functions like fixtoi() etc. There is also a special "fix" type, which is only briefly mentioned in the docs. The "fix" type is a wrapper for "fixed" that uses C++ operator overloading to make it behave much like a regular floating point type. ie you can just add ints or floats to it or whatever you want, and it will (usually) figure out what you mean. "fix" is only available if you are compiling as C++. You still occaisonally have to be careful... C-style text output functions like printf and textprintf often accept typeless parameters, and therefore you might have to explicitly cast a "fix" to an int or float (like: int(my_fix) or float(my_fix) when using it with a "%d" or "%f".

Locutus266
Member #7,638
August 2006

Thanks once more for your remarks. Since I am programming in good old C, I won't be able to use the "fix" type, I guess.

I think, I'll just try out some of your suggestions.

Best regards,
Christoph B.

Go to: