Beware of the float positioned pixel

Published 2023-06-12



Hi,

I'm working on my "Who dares" game (v0.13.3 for now) and now fight with bullets movements. Player and foes can move and shoot on 8 directions. To prevent all those sprites going faster on diagonals I just multiply their step value by 0.75, an approximation on cos(45) (or sqrt(2)/2, you choose) to get back to integers every 4 frames. Anyway, those sprites move look jagged on diagonals. I first found a way to fix this by copying Y decimals to X coord, but it's rather complicated and not the best way I think. Plus, it also messes with collisions.

So I went to basics: if movement is jagged because of float coords, how is drawn a float positioned pixel? I made the little cart here to experiment this. To make it short, a float pixel will be drawn at a floored, and not rounded, position. So pset(9.75,9.25) will put a pixel at 9,9. Fine with that, but further experimentations show bugs, as shown here.

The cart shows 6 different increment, named px, each one its own line. Every nth frames (fq value set on line 11) a value named x, initiated with 0, has px added, then printed at x position on light green if it's an integer, ie if x==flr(x), dark green otherwise.

Things go well when px=0.25, 0.5, 0.75 and 1: they turn light green when no decimal, the same moment they move 1 pixel right. Can't ask for more.
But things are not too good on first two lines (px=0.1 and 0.2):
x keeps being drawn with dark green, that means the x==flr(x) is always false, even when the value shown have no decimals.
When those values drop their decimal, they should move 1 pixel right. But they don't, it happens on the next increment. As if their no-decimal value is in fact lower than the integer.
While those steps only has 1 decimal, quickly their added value have decimals like 0.999, 0.998, etc. Quicker with px=0.1 (0-1, then 5 and >), later with 0.2 (33 and >)

My jagged movements probably have little to do with this bug and is more about using 0.75 factors and having X and Y that don't have their integer value changing at the same time. But well, I just discovered this and wanted to share.
Anyway if anyone knows how to simply have nice diagonally moving float positioned sprites, I'd really be happy to hear!