pouët.net

Frame-independent movement, I'm stuck

category: general [glöplog]
I've been thinking about this issue for about a week now and I still haven't found a solution that works. Maybe you can help me?

What I've done so far:
Frame-Dependent movement, including frameskipping (doesn't matter for now). So every frame, <gravity constant> is added to <vy> (vertical velocity), and <vy> is then added to <y value>. Having a gracity constant of 5, it could look like this:

Code:Step| y |vy ----+---+-- 0 | 1 | 0 1 | 1 | 5 2 | 6 |10 3 |16 |15 4 |31 |...


that works just fine. but i have to move over to frame-independent movement for several reasons. now it doesn't matter anymore how long the frame lasted, I just pass a float number to the movement update function which represents how long the frame lasted, in comparison to the wanted framelength (e.g. 1 = perfect length, 2 = double length, 0.5 = half length). However, now I'm stuck with the maths. What do I have to do now so it will run as fast as it did before? I figure out that i won't do vy += gravity anymore, but vy += gravity * frameduration. However, after looking at the chart above, this is not everything. After 2 steps (i.e. frameduration = 2, starting from row 1 in the example table), y should be 16, but it would be 11. That's the part where I'm stuck. What do I have to do?
you can measure the time spent between the two frames and run your gravity routine enough times
added on the 2009-01-01 21:31:41 by Gargaj Gargaj
well, that's what I did before, but I can't execute it "1.25" times...
ok, that was a bit murky. assume your "ideal" frame lasts 10ms - if your last frame was 30ms, run the routine 3 times :)
added on the 2009-01-01 21:33:12 by Gargaj Gargaj
well, that's exactly how I do it atm. but i think that i get very inaccurate results here - or else, it wouldn't make such a different between compiling my game with BASS and without it. Ian told me that BASS will change internal timer resolution 1ms, so the game should actually run smoother, but it's even slower than running without BASS. I guess that I get frame durations like 1.5, and then neither 1 or 2 would be an accurate result.
if you want to avoid having fractions, you can either just increase granularity, or simply discard it (gets less accurate but if your routine only makes simple movements, it shouldnt be a problem)
added on the 2009-01-01 21:36:30 by Gargaj Gargaj
I suspect that discarding the fractions is causing the big differences between the BASS and the non-BASS versions, so either increasing granularity or frame-independent movement seems to be a solution for me. But I'd rather go into the frame-independent direction, as I can imagine that processing 10,000 particles (and all the other stuff) 10 times instead of one time could slow down the game heavily on older machines.
What I do in effects that animate by frame number rather than timer (water/fire effect, physics, etc) to avoid them going to run in future PCs and going too fast, is to maybe execute them not at each frame but restrict at like 50fps or anything that fits with I timer.

I mean, the whole rendering loop of the demo might run at whatever frames fast it can go. But the specific filter or physics algorithm will be executed at only 50fps or another specific number.

I think I had something like this:


int atime;

void calc_physics()
{
if (SDL_GetTicks()-atime>=20)
{
atime = SDL_GetTicks();
....do physics calcs
}
}

void run_physics()
{
calculate_physics();
render_stuff();
etc();
}

So, run_physics may run at 100 or 200 fps or anything, but calculate_physics will only be allowed to run after each 20ms, it will update at 50fps steady, regardless the overall speed of the demo.

Don't know how good this is for physics though. Another thing I did in a game was to restrict all the main loop of the game (rendering, physics, everything) at say 50fps. I am not sure if it's a problem when it runs at much lower fps.
added on the 2009-01-01 21:50:09 by Optimus Optimus
optimus: we're trying to avoid the opposite though, running steady on slower computers.
added on the 2009-01-01 21:52:41 by Gargaj Gargaj
optimus, i actulally have two independent threads for the movement update and the rendering, so this is not my problem. :)
basically I resolve the problem this way :

put the physics part inside a separate thread (with high priority),
main thread will be used for drawing the stuff (low priority)

inside the physic thread , put a Sleep() so it will run at a constant speed (ex : 30 fps) no mather on which computer it runs.....


I know there is an issue if computer is really to slow (cannot maintain the 30 fps) but normally graphics are the big slowdown part, and unless ure doing heavy physics stuff were the load can change dramatically (eg: rigid body with 5000+ objects or so) it wont be a problem.

Also note it will require a few synchronisation if there is some delete/create objects done dynamically (an object cannot be draw while he is being deleted by physics part) but doing this is really trivial. The good news is you will have threaded app that will take advantage of today multicore cpu.
added on the 2009-01-01 22:04:11 by Tigrou Tigrou
tigrou, that's exactly what I do. But there is a way to decrease or increase the accuracy of the windows timer which also affects sleep and stuff, so this is why it runs at different speed here as soon as i initalize BASS.
so you have position, velocity and accelration.

Accelaration = constant;
velocity+=Accelration *deltaT;
position+=velocity*deltaT;

with deltaT being time between frames. Am I missing something here ?
added on the 2009-01-01 22:10:39 by Navis Navis
I usually use fixed delta time time for physics (e.g. 30fps) - dunno if this is the most common way. If framerate drops significantly, adding by deltatime-scaled values is the way to go but gives error, which might get bad if some collision detection related stuff is done.
added on the 2009-01-01 22:20:51 by shadez shadez
you can use function that depends on time f(t-t0) for your phys calcs, where t is current time and t0 is time when your phys effect had begun.

excuse me for my english - it suxx... i hope that you had understood what i mean here. (=
added on the 2009-01-01 22:37:36 by RRROAR RRROAR
suprised that nobody mentioned it..
Saga Musix: you probably want sth. like this
(totally unoptimized, of course;))
added on the 2009-01-01 22:41:53 by xyz xyz
Saga Musix, do you have any kind of collision detection in your physics?

If not, just use time based equations...

Even if there are collisions, you can always do it time based... I know it is easier to code collisions with linear equations, but if the formulas are too complex you can always use numerical methods...
added on the 2009-01-01 22:42:17 by texel texel
Navis: Well, if I simply do it as you suggested (I tried that one many times now), the physics become very unrealistic suddenly. I have no clue what's going wrong...
texel: yes, i have collision detection, that's my problem.
Are you using any kind of space partitioning?
added on the 2009-01-01 22:47:24 by texel texel
I'm not sure if I understood you. What's space partitioning?
Saga Musix, any kind of bsp tree or kd-tree (for example) to subdivide space, to make faster collitision detection with it.
added on the 2009-01-01 22:51:23 by texel texel
http://en.wikipedia.org/wiki/Space_partitioning

My idea reading your post was "10k is very low to be a time problem". If you are not using space partitioning it is, but if you are, then it should be extremelly fast... so you could add granularity or whatever without problems
added on the 2009-01-01 22:53:08 by texel texel
Saga Musix: Have you looked at my code example ? FPS.precision returns what you called "frameduration".

You will need to have to reset the gravity/velocity at some point in your game, most probably when you detected a collision.
added on the 2009-01-01 22:53:34 by xyz xyz

login