Jump to content
  • Advertisement
Sign in to follow this  
Norman Barrows

timestep with ET cap

This topic is 1402 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i'm thinking about the basic design for simspace 8, a starship flight sim.

 

i'm considering using a variable timestep with limit:

 

max_et=33ms

start timer

while !quitgame

    {

    render

    process input

    et=elapsed time

    if et>max_et,   et=max_et

    update(et)

    }

 

 

questions:

 

1.  this example would run the simulation at no faster than 33ms per frame when et becomes large (>33ms) - although overall frame rates might drop to some low value (in the 20's or 30's for example). correct?

 

2. and when et was <=33ms, the game would always run at the same speed on different machines, no frame rate limiter required, correct?

 

3. vert refresh rate would limit the overall speed to 60hz (or whatever the vert refresh rate of the current resolution was), correct?

 

4. this is the same basic thing as the variable timestep with limit to avoid the "spiral of death", correct?

 

5. so this could  be a viable alternative to using a framerate limiter to get the same speed on all machines?

 

6. and by changing max_ms, one can control how long the simulation can run before a render is done?

 

7. so a small max_ms would keep the simulation from getting too far ahead before a render and process input is done so the player can react?

 

 

 

 

Share this post


Link to post
Share on other sites
Advertisement

A better approach may be to fix your timestep. That approach allows the simulation to be based on a known fixed delta-time (which you're trying to implement). However, you can then let the rendering go as fast as the machine supports.

Edited by Buckeye

Share this post


Link to post
Share on other sites


A better approach may be to fix your timestep.

 

i'm assuming that et's will not be so large that a fixed timestep (consuming render time in et [33ms?] sized chunks)  is required. also, the game is to be as non-deterministic as possible, so no fixed time step is required for bit accurate reproduce-ability. the idea about the cap is to keep the simulation from running for too long an et between renders and input for the player to react. sort of a safety valve for PC titles when things get hot and heavy and framerates drop.  with the "consume render time in et sized chunks" approach, you might process mutiple "turns" (et's) of simulation before a render. this is what i want to avoid, while still letting the rendering go as fast as the machine supports. i think the algo above will do this, just want to make sure.

Share this post


Link to post
Share on other sites

1. Yes (see 6)
2. Yes. Assuming you're using et in your physics calsulations of course smile.png
However, things may be simulated differently on PCs with different et values. E.g. When using Euler's method of numerical integration (the standard way of adding velocity*et to position per frame, etc) a person with a higher framerate can jump further than someone with a lower framerate,
Due to their gravity/momentum curves being integrated with different accuracies.
If that's an issue, then use a fixed timestep.
3. Only if you've requested vsync to be enabled AND the OS/driver has respected your request (which it may not - e.g. When in windowed mode on WinXP)
4. Yes, this is the standard way I know I to avoid the spiral of death
5. a framerate limiter stops the et from being too small. You might want one of those as well if you're seeing et values so small that they begin to cause issues with your physics/etc (e.g. dividing by zero at some point...)
6. Yes and no. Yes for time as it passes in the game world. No for time passing in the real world. A 33ms time step could still take any amount of real-world time to process.
7. Kind of... In cases where the game is performing at sub-realtime speeds, instead of becoming unresponsive/unplayable, it will instead play in slow motion... The image on screen might still only change (and the inputs might only be polled) at any rate, such as once a second if the simulation code is performing poorly.

Edited by Hodgman

Share this post


Link to post
Share on other sites

Your loop will do that, but (my numbers are not reactions to your numbers):

 

#1: Your inside-of-the-loop is wrong.  Input first, then update, then render.  Until you’ve updated, there is nothing to render, and it doesn’t make sense that the first thing you do on this frame is render the last frame (it may seem as though rendering at the end of the current frame is the same as at the start of the next frame, but updating of clocks happen between these points and these will change how your graphics are interpolated).

Aside from the 3 “main” functions the loop needs to perform (input, logic, and rendering), updating the game clock (and implicitly the delta values) is the absolute first thing that must be done in a game loop.  You need the delta for every other sub-system that is going to run, including input and rendering.

 

#2: I changed my mind about mentioning #2 as you likely simply don’t care about “proper” input-handling.

 

 

L. Spiro

Share this post


Link to post
Share on other sites


2. Yes. Assuming you're using et in your physics calsulations of course
However, things may be simulated differently on PCs with different et values. E.g. When using Euler's method of numerical integration (the standard way of adding velocity*et to position per frame, etc) a person with a higher framerate can jump further than someone with a lower framerate,
Due to their gravity/momentum curves being integrated with different accuracies.
If that's an issue, then use a fixed timestep.

 

this difference on PCs with different ET values, would still be on the order of the usual inaccuracies of Euler integration vs more accurate methods such as rk4 integration, correct? or can it be a big difference? (significant enough to adversely affect game play).

 


3. Only if you've requested vsync to be enabled AND the OS/driver has respected your request (which it may not - e.g. When in windowed mode on WinXP)

 

so a framerate limiter would be required to guarantee a 60hz max framerate under all conditions. 

 


6. Yes and no. Yes for time as it passes in the game world. No for time passing in the real world. A 33ms time step could still take any amount of real-world time to process.

 

a good point. game time vs real world time.   this is the desired effect: limiting et processed between reneders.  i realize that real world processing time will go large and come "unglued" from game time elapsed. the plan is to keep et's low enough that the et cap would almost never take effect. but to still have it in there, just in case. then do as much game as you can without capping out on et too much.

 


7. Kind of... In cases where the game is performing at sub-realtime speeds, instead of becoming unresponsive/unplayable, it will instead play in slow motion... The image on screen might still only change (and the inputs might only be polled) at any rate, such as once a second if the simulation code is performing poorly.

 

cool! looks like i have my bullet time response to low framerates! better that everything runs slow than having render, input, and player run slow and the simulation continue at normal speeds.

 


#1: Your inside-of-the-loop is wrong.  Input first, then update, then render.  Until you’ve updated, there is nothing to render, and it doesn’t make sense that the first thing you do on this frame is render the last frame (it may seem as though rendering at the end of the current frame is the same as at the start of the next frame, but updating of clocks happen between these points and these will change how your graphics are interpolated).
Aside from the 3 “main” functions the loop needs to perform (input, logic, and rendering), updating the game clock (and implicitly the delta values) is the absolute first thing that must be done in a game loop.  You need the delta for every other sub-system that is going to run, including input and rendering.

 

good point. wasn't really thinking about the order of things and when the timers should be set and checked.

 


#2: I changed my mind about mentioning #2 as you likely simply don’t care about “proper” input-handling.

 

ah yes, consuming input in et sized chunks...

 

well lets see,  i use the windows message queue for mouse messages. i could use it for keystrokes too. i assume windows messages have a timestamp.  so that would give me an input queue with timestamp. lets assume the loop is up and running and et is about 15ms, and the input queue gets emptied every every time its processed. now suddenly et jumps high (100ms). but i have a 33ms cap in effect. so i have 100ms worth of input in the queue, but i'm only going to simulate 33ms of game time. so i process the first 33ms worth of input. but since there's a cap, do i discard the remaining input, or process it on the next pass? intuition says discard.  am i on the right track here ?

 

 


5. a framerate limiter stops the et from being too small. You might want one of those as well if you're seeing et values so small that they begin to cause issues with your physics/etc (e.g. dividing by zero at some point...)

 

so  a framerate limiter may be required to keep et from being too small, especially when vsync is not active. got it.

 

L Spiro has a good point though - what about consuming input in et sized chunks, vs the et cap?

 

all the rest sounds pretty much like the behavior i'm looking for. note that i don't plan to actually have et's that hit the cap. i plant to limit scene and simulation complexity as required to keep things running smoothly at all times. i just want to have an architecture that will degrade gracefully under fire - just in case.

 

So, L Spiro,  as the grand champion of consuming input in et sized chunks, how would one handle input given the et cap? 

please lend a machete to my intellectual thicket. <g>

 

one last question:

as L Spiro pointed out, render needs et to tween between the last and current state for drawing. if i don't tween, i will get not-smooth animation. but the physics engine will be unaffected. the render location is simply temporally out of phase with the physics location by the et remainder,  correct?  IE an entity is drawn somewhat behind their actual current position. 

Share this post


Link to post
Share on other sites

well lets see,  i use the windows message queue for mouse messages. i could use it for keystrokes too. i assume windows messages have a timestamp.  so that would give me an input queue with timestamp. lets assume the loop is up and running and et is about 15ms, and the input queue gets emptied every every time its processed. now suddenly et jumps high (100ms). but i have a 33ms cap in effect. so i have 100ms worth of input in the queue, but i'm only going to simulate 33ms of game time. so i process the first 33ms worth of input. but since there's a cap, do i discard the remaining input, or process it on the next pass? intuition says discard.  am i on the right track here ?

You technically have 3 options. Technically you have the option to discard inputs, but that is never a good idea.  The resulting outcome is always the least desirable of the 3 main options.
 
In a typical fixed-step simulation with no caps, you can eat 33 milliseconds of input on each tick and all difficulties are handled implicitly.
When you used a fixed step but with a cap (which is usually expressed in numbers of logical updates, not in the length of an update), if you send a fixed step to the input-giver, each time you cap a step in your game logic the input will lag the accumulated capped amount, so 3 hours into the game your input will be behind by 3 seconds for example.  In this case you need to eat all the inputs that were skipped by the cap, which is just a matter of asking for input based on an uncapped time.
 
In your case, you have 1 update every frame, and the update is capped in time, not units.
 
When dealing with capped time in either of these cases you have 2 options:
#1: Although capping the number of logical updates (or the duration of a single update), request input in an uncapped manner and apply it all to the last update.
For fixed-step updating, this means if you have to do 16 updates in a frame but you cap at no more than 5 updates in a frame, on the 5th update you pass the input for the 5th update’s range and also all the updates from 6 to 16.
In your case this means simply eating all input up to the current absolute timestamp and passing it all to your single update.
 
This has the side-effect of enhancing a player’s in-game actions, as you have now stuffed 78 milliseconds (or whatever) of inputs into a single update.  Depending on how you handle inputs inside the game logic (which is a separate issue from how to gather and distribute inputs), it could leave the player overly powerful (able to get twice as many attacks into a single update) or overly impotent (many attack commands issued but only 1 recognized per update).  If your engine is not robust, rapidly jumping in a tight space might cause the player to go into the ceiling, etc.
 
 
#2: Request inputs at a fixed rate each frame (33 milliseconds in your case) and let any remaining inputs be sent to following frames/updates.
This works significantly differently if you are using a fixed-step with a cap, so I will only explain how this works in your case.
If your cap is 33 milliseconds and you always do 1 update per frame, always eat 33 milliseconds of input.  When the logical update only updates by 3 or so milliseconds, the result will be the same as above where you simply eat all input each update.  This is because the input won’t ever be that far ahead of your game logic.
 
Only when the logical update is capped to 33 milliseconds might you encounter non-eaten inputs in a given frame.  Just leave the rest for the next frame/update.
If the next frame is fast (16 milliseconds for example), eating inputs at a steady 33-millisecond rate will allow your inputs to catch up to the game logic over 1 or 2 frames.
 
The advantage of this is that it won’t strain the limits of your engine, making the player too powerful or suddenly able to jump into ceilings.
On the other hand, when the gameplay slows, so does your response to inputs.
 
 
The down-side to #1 might be desirable in some types of games (still keeping input responsive while the game slows).
The down-side to #2 might be desirable in some types of games (keeping the game stable with a slight bit of lag).
 
It is up to you.
 
 

as L Spiro pointed out, render needs et to tween between the last and current state for drawing. if i don't tween, i will get not-smooth animation. but the physics engine will be unaffected. the render location is simply temporally out of phase with the physics location by the et remainder,  correct?  IE an entity is drawn somewhat behind their actual current position.

In your case, there is no fixed amount between which to interpolate. For this type of loop there is no good way to interpolate, and indeed no need. You have that advantage at least.


L. Spiro

Share this post


Link to post
Share on other sites


You technically have 3 options.

...

It is up to you.

 

as usual, everything is a trade off, eh?

 

thanks for the analysis. i take it that you recommend using a fixed et and capping the number of updates, as in "fix your timestep". and you also don't recommend simply discarding unconsumed input. intuitively to me it seems that by consuming render and input in fixed size chunks they would never go out of sync, correct?

 

its interesting how these various changes to the basic game loop can result in different behaviors under different circumstances.

 

more questions:

 

using the "fix your timestep" algo (making update consume render time in fixed et sized chunks), one must track both the current and previous state of an object for the tween for drawing, correct?

 

and one must multiply everything by et in update, correct? actually, no - update updates for one fixed chunk of time, but may get called more than once per render. 

 

and one must tween everything when drawing, including character animations, correct?

 

so a "fix your timestep" algo actually has some additional overhead above and beyond that of a simple fixed time step?

 

and therefore would run slower that a fixed timestep when et goes large?

 

and the whole purpose of this is primarily for smooth animation with no temporal aliasing, at the cost of some additional overhead and some additional code complexity?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!