using floats as co-ordinates in a 2D game ...

Started by
5 comments, last by ekrax 19 years, 8 months ago
this is what im doing, and everytime i think about it, it seems stupid ... however the problem is that, moving objects a pixel per frame or more is way to fast ... so i have their velocities as floats, it works ... but i suspect this is what is messing up my collision detection ... i have had a few ideas to fix this problem just wondering if anyone else has any suggestions. i'm thinking i could fix this with sort of a "hack" ... i would simply create a realative timer to all moving objects and objects with the highest velocity (1 pixel per frame) would execute every frame, since you cannot *realy* have half a pixel per frame, i could move it 1 pixel per every 2 frames, and intead of a third pixel every frame, it would be 1 pixel per 3 frames ... implemented something like this (sort of pseudo) ...


// defines some object
class object
{
        // ...
    public:
        int position;
        int speed;
        // ...
};

// a bunch of objects
class objectSystem
{
        int timer;
        std::vector < object > things;
        // ...
    public:
        void move ();
        // ...
};

// where i move my objects ...
objectSystem::void move ()
{
    for (int n = 0; n < things.size (); n ++)
    {
        if (things[n].speed  <= timer)
            position += speed;
    }
    timer ++;
    if (timer == things.size)
        timer = 0;
}


this could work but it seems sorta hacked and just not proper ... then i thought i could use a real timer variable and set event times in milliseconds (not sure how, but im sure i can google this) ... im just wondering if anyone has any suggestions on this ... is a game schedular really neccasry or will the "fake timer" way work? is there any other way to effectivly move objects in 2D smoothly but not insanly fast ... (im using opengl if that makes a difference in any way) ... thanks for any suggestions in advance.
Advertisement
Well, it really isn't that difficult. You *should* store positions as floats. That will solve many problems. Moving in "pixels per frame" is not something i personally would recommend for the very reasons you mentioned (it's hard to move in a "non-chunky" way). If that is throwing off your collision detection, than obviously your collision system is weak. I would fix THAT before i go and try a 2-bit hack on the movement system.

For timing, do it right and do it the same way for everyone. Have a global timer -or- have your Objects get passed a ref to a timer or the time itself -or- have the ObjectSystem include a timer that it can time all Objects on.

For movement, move based on the time in "pixels per second". If your x/y coords are floats, you won't lose anything to rounding off or truncation.

<time.h> will do for milliseconds (microseconds if used on a unix system). If you are using OpenGL, you can also throw in SDL (highly recommended anyway) which includes timers and time keepers as simple as SDL_GetTicks().
Whether using floats or fixed point:
Float: Store the position in pixels or whatever unit you prefer.
Fixed: Store the position in nths of a pixel (or another unit).

Move by adding the velocity*time to the position.
Round the new position to pixel co-ordinates.
Compare the new pixel co-ordinates to the old, and collision detect (in one pixel increments if you need to) from the old pixel coords to the new pixel coords, (not checking the start value).

Simple per-pixel loop for 1 dimension, using fixed point in 1000ths of a pixel. (If you use this change it to something like 256ths of a pixel)
int pos = 12500;int vel =  3000;int oldpix = pos / 1000;int pix;loop {    pos = pos + vel;    pix = pos / 1000;    int delta = pix - oldpix;    int dir;    if(delta < 0) {        dir = -1;         delta = -delta;    } else {        dir = 1;    }    while(delta) {        oldpix += dir;        if(collide(oldpix)) {             pos = oldpix * 1000;             break;        }        delta --;    }    vel = getNewVelocity();}




Slightly offtopic: You might want to consider using fixed point as opposed to floats, for efficiency and accuracy reasons.

Basically, fixed point values are integers that represent sub-units, such as thousandths of a pixel, or better, 256ths or any power of 2.
why dont you just use a cast to convert the float to an int whenever you do a collision detection?

float Xpos;
float Ypos;

if(int(Xpos) == Target.x && int(Ypos) == Target.y){
.........
}
Quote:Original post by ekrax
so i have their velocities as floats, it works ... but i suspect this is what is messing up my collision detection ...

Fix the problem, don't just attempt to hack together something totally different to accomodate something that you've already admitted is broken.

Assuming your collision works with integers then the problem is likely to be that you're attempting to compare if some float positions are equal (with ==). Don't do that with floats as it'll almost always not be true. Instead test using an 'epsilon' (a very small value).

Eg:
float epsilon = 0.00001f;float delta = abs(val1 - val2);if (delta < epsilon)  // val1 and val2 are equal
Be careful with floats. They only have 24 bits of precision, and that can be insufficent more often than people think. For example, float coordinates are not enough for galaxy-level space exploration or earth-level flight simulator.
Abovementioned comparison with epsilon 0.00001f makes only difference, if the absolute values of both operands are < 167. If any of the values is bigger, it is equivalent to (val1 == val2).
In any case, be prepared for:

(val + epsilon) == val

Technically doubles have the same problem, but because of the improved precision, it is much easier to ignore it.
Quote:
float epsilon = 0.00001f;
float delta = abs(val1 - val2);
if (delta < epsilon)
// val1 and val2 are equal


wow that's pretty smart never thought of that. anyways i don't really want to do casts becasue everyone knows the horrible things that happen on integer to float casts and float to integer casts. i think i will try the fixed point method first. thanks for everyones replies.

This topic is closed to new replies.

Advertisement