indpedendent update / render

Started by
8 comments, last by supagu 20 years, 1 month ago
hi, i have an engine, it was signelthreaded, and 40 times per second i would update my world, and 100 times per second, update my physics, now i run into problems when i get less that 100 fps, physics slows down... i tired opening another thread for my render'' but this drops about 30 - 40 fps off is there another solution?
Advertisement
Multiple threads seem really good in a theoretical, aesthetic sense but they are inefficient. There are two options I see for you ina single thread:
1)Change your physics code to update once per graphics frame with a variable timestep so it actually updates the world by the amount of time that has passed since last frame. This is the most theoretically nice option but probably means changing your physics code quite a bit to something more complicated.
2)Something like this:
function GameRender(){float updateTimeStep=0.01f; //how much the physics updates byfloat timeStep=timeNow-timeLastCall; //in secondsint steps = timestep/updateTimeStep; //0 if fps>100for(int i=0;i< steps;++i){ PhysicsUpdate()}}  

This was done in the game I worked on at a real game developer.
Basically it does how every many steps are needed to bring the physics up to date. If the renderer is faster than the physics update rate, some frames no physics will be done. This works well.

[edited by - d000hg on February 28, 2004 12:31:24 PM]
hrmm i like the second idea,

ive implemented it, but running at 150 fps and then at 60fps does feel different :-/

		time = SDL_GetTicks();		physDeltaTime = time - lastPhysTime;		gameDeltaTime = time - lastGameTime;		physStep = physDeltaTime / PHYSICS_UPDATE;		gameStep = gameDeltaTime / GAME_UPDATE;//then inside my phsics loop:lastPhysTime = time;//and in my game loop:lastGameTime = time;


:-/ makes sence on how it works, but it doesnt seem to be perfect :-/


edit: does seem to be working, at 150fps, every second frame its updated once,

at 60 fps, its updated at least once every fps, sometimes 2 times.

hrmm :-/
any way to make it more accurate? maybe determine the remainder after the division?
[edited by - supagu on February 28, 2004 9:07:51 PM]

[edited by - supagu on February 28, 2004 9:14:00 PM]
The typical game main loop is:

lastTime = clock();while( running ) {  while( UIEventsAvailable() ) {    ReadAndProcessUIEvents();  }  now = clock();  if( lastTime < now-MAX_TIME_JUMP ) {    lastTime = now-MAX_TIME_JUMP;  }  while( lastTime < now ) {    StepPhysicsByOneTimestep();    lastTime += TIME_STEP_SIZE;  }  RenderOneFrame();} 


This will make sure that the time step is always the same, and you render when you have CPU left over. If you have more CPU than needed to render once per physics step, you''ll render multiple frames based on the same physics state; you can improve that by reducing the step size (thus giving the CPU more to do) or by rendering a frame that''s interpolated between the last two physics frames, based on (real) time.

If you want to write a program that runs the same speed in debug and release builds, and on a 600 MHz CPU as well as a 3.2 GHz CPU, you''ll need to realize that physics must be very cheap; specifically, it''ll have to be cheap enough to run at full rate in debug mode on a 600 MHz CPU while still leaving some time left for rendering.
enum Bool { True, False, FileNotFound };
The remaining time will make an effect, come to think of it. If you should be doing 1.8 physics updates every frame but always do 1 it'll be wrong. If you get the floating point value for number of physics updates before truncating it and store the fractional part as remainder then each frame, using last frame's remainder:
physStep = (int)(physDeltaTime / PHYSICS_UPDATE + remainder)  
Which'll catch up the updates you're missing.

[edited by - d000hg on February 29, 2004 12:38:05 PM]
nope thats cant be right,

should be something like this:

physReminder += (physDeltaTime % PHYSICS_UPDATE);if( physReminder > 10 ) //10 means 1 step		{		//	printf("adding step!\n");			++physStep;			physReminder -= 10;		}


i tired this, but it still isnt the same speed at differeing frame rates :-/
Ah, you''re dealing in milliseconds right, not actual seconds? I''d certainly find using real seconds and floating point values simpler because then:
timeSinceLastFrame/physicsUpdateInterval gives you a floating point number. The integer part + the fractional part from last frame is then how you work out the number of updates to do each frame.
i put in a 10 second timer that counts the number of physics steps in 10 seconds, and it still like 100 more steps with higher fps :-/

the reminder doesnt add up either!

the one with more physics steps in 10 seconds ahppened to have a greater additive time at the end :-/


[edited by - supagu on March 1, 2004 4:30:48 AM]
I GOT IT!!!!

time = SDL_GetTicks();deltaTime = time - startTime;curPhysSteps = deltaTime / PHYSICS_UPDATE;for( int p = 0; p < curPhysSteps - completePhysSteps; ++p ){//do physics update}completePhysSteps = curPhysSteps;


i also do the same for my game loop,
this usually is with an accuracy of 1 loop in seconds

That was gong to be my last suggestion! It would be nicer to have
while(completePhysSteps++<=curPhysSteps){//do physics update}  
instead of
for( int p = 0; p < curPhysSteps - completePhysSteps; ++p ){//do physics update}  
IMO only this is better but it's just a sytlistic thing. Plus the ++ probably isn't quite right...

[edited by - d000hg on March 1, 2004 10:36:14 AM]

This topic is closed to new replies.

Advertisement