Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411423 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 18, 2024, 07:39:56 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Framerate-independent development
Pages: [1] 2
Print
Author Topic: Framerate-independent development  (Read 6770 times)
Akari
Level 2
**



View Profile
« on: January 26, 2010, 12:16:07 PM »

Since I'm pretty much a regular Construct user, this topic has been in my mind for a while. The question basically is what tools/engines/programs support framerate-independent game development and at what ease?

To clarify what framerate-independent game is, it runs at the same speed no matter what the framerate is - basically all commercial 3D games do this. No matter whether the FPS was 120, 80 or 60, your character will move exactly the same amount during a certain time period.

Construct as far as I know is one of the few, if not the only game-development program that makes framerate-independent development easy and encourages all the users to do so. It's basically achieved with the usage of a system variable called TimeDelta. Now for example in MMF or GM or whatever you'd have something along the lines of Always -> Set object.x to .x+5. If your framerate is 60, your object will move 300 pixels in a second. However, rise that to 120 and your object suddenly moves 600 pixels a second. In Construct, you'd use Always -> Set object.x to .x+300*TimeDelta, and the TimeDelta variable will ensure that it'll always move 300 pixels in a second, no matter if the game runs at 60 or 120 fps (or whatever else).

Now I know MMF2 for example supports VSync, but I guess it results in different game speed considering the whole idea of MMF is build around fixed framerates. It's kinda silly that it includes VSync mode to begin with considering that if your screen refresh rate is 120 Hz the game will be basically unplayable if it's twice as fast as it should be.

So what programs/languages even support framerate-independent development and how easy is it do it in them? I have honestly nothing but praise for it. Vsync + framerate-independent code is a lovable combination, and to be honest I'd say development has also become more clear when you think in pixels per second rather than pixels per tick.

Do YOU develop your games to be framerate-independent?
Logged
Farbs
Man
Level 10
*


/Farbs


View Profile WWW
« Reply #1 on: January 26, 2010, 12:34:06 PM »

I pretty much always work framerate-independent. In the rare instances where an engine doesn't give me a delta I just calc it myself by comparing current time to time of previous run. Working with an unfixed timestep can have some nasty downsides though. It's no good for fighting games where you want to precisely define the action in 60ths of a second, and simple physics or movement code (eg a basic platformer jump) can give slightly varied results.
Logged
ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« Reply #2 on: January 26, 2010, 12:42:39 PM »

Fixed timesteps decoupled from the drawing rate are the way to go, and the only thing I'll do in any game I write these days. I've written an article on it: http://sacredsoftware.net/tutorials/Animation/TimeBasedAnimation.xhtml

I like this one, too: http://gafferongames.com/game-physics/fix-your-timestep/
Logged

Zaknafein
Level 4
****



View Profile WWW
« Reply #3 on: January 26, 2010, 12:46:39 PM »

In XNA, framerate independence is managed by the IsFixedTimeStep property of the Game class... For a long time I thought I was using variable time-steps because I had FPS greater than the VSync, but XNA was actually feeding a VSync-compatible elapsed time to my update calls and waited at appropriate times (or doubled updates, or doubled draws) to make it all work.

So when I found out and decided to disable fixed time-steps, a million different physics problems arised, damping/friction wouldn't work (because if you do something like "x *= 0.9" every frame, it's not obvious how to make the effect constant across different time steps), etc.
So I just reverted to fixed time steps.
Screw this.

I still multiply all my deltas by time elapsed, because I think it's a good practice and it keeps the code free from magic numbers, but I know that it's always going to be 1/60 seconds.
Logged

st33d
Guest
« Reply #4 on: January 26, 2010, 12:58:14 PM »

because if you do something like "x *= 0.9" every frame, it's not obvious how to make the effect constant across different time steps

This is pretty straight forward. You just have to reconstruct the equation.

x *= 0.9

becomes

x -= x * 0.1

and to being that in line with the timestep

x -= x * 0.1 * timeStep

I generally prefer fixed timesteps but I wanted to do the Zack Snyder effect:





Everytime the character killed someone I wanted the game to drop down to slow-mo so you could appreciate the kill and then lapse back into normal time.

Unfortunately I was doing this in Flash, so I had to also extend the MovieClip class for all animations that only advanced the frames of animations when a full timeStep had elapsed. Luckily I had a jsfl script handy to do this and the slow animation combined with slow physics when you dispatch an enemy looks great.
« Last Edit: January 26, 2010, 01:04:04 PM by st33d » Logged
J. Kyle Pittman
Level 6
*


PostCount++;


View Profile WWW
« Reply #5 on: January 26, 2010, 01:01:31 PM »

Delta times and framerate-independent motion are awesome, but they come with their own set of baggage: numerical instability.  How much of an issue this is depends on your integration method.  Euler integration is simple and intuitive, but it produces wildly varying results at different framerates.  If you're interested in highly accurate physical simulations that need to run consistently regardless of framerate, you could use a higher-order method like RK4, but for real-time games, we usually want a cheaper method.  Personally, I use Euler most of the time and Velocity Verlet for things that need to be more accurate.

One of the benefits of using a fixed time step is that you can guarantee consistent behavior in all cases, regardless of framerate, CPU speed, or whatever else.  And you can, in fact, have the best of both worlds; motion that follows a consistent time step AND no mandates on Vsync or framerate.  See this article for the full explanation: http://gafferongames.com/game-physics/fix-your-timestep/  It works by only updating your physics simulation once the fixed time step has elapsed.  If your framerate is faster than your time step, you'll only do physics simulation updates on some frames.  If your framerate is slower then your time step, you'll do multiple physics simulation updates on some frames.  Then you can interpolate between steps to improve visual quality without compromising the consistency that you get with a fixed time step.

I haven't yet implemented this technique, so I can't comment on any roadblocks that you might run into, but at a glance, it sounds pretty intuitive, and I can't really think of any downside to using it.

Edit: Look like ThemsAllTook beat me to the punch.  Tongue
Logged

Zaphos
Guest
« Reply #6 on: January 26, 2010, 01:21:20 PM »

Delta times and framerate-independent motion are awesome, but they come with their own set of baggage: numerical instability.
Consistent results and stability are kind of separate things; a fixed time step gives consistency but you can still have instability at a fixed timestep.  In other words, the  difference is that you're more likely to see the same instability on all computers with a fixed timestep, while it may only show up on some computers with a delta time step.

Likewise accuracy and stability are separate things -- if you want to guarantee stability, you might look at implicit integration methods instead of increasing the accuracy.
« Last Edit: January 26, 2010, 01:27:55 PM by Zaphos » Logged
Akari
Level 2
**



View Profile
« Reply #7 on: January 26, 2010, 01:34:43 PM »

Everytime the character killed someone I wanted the game to drop down to slow-mo so you could appreciate the kill and then lapse back into normal time.

Heh, in Construct this is done ridiculously easy. Along with the TimeDelta, there's TimeScale that you can edit, which does exactly what you'd think it does. Set it to 0.5, and everything that uses timescale (which includes all the built-in movements, animations, and all code using TimeDelta) will act accordingly. Pausing the game is as simple as setting timescale to 0.

Really, one of the main reasons why I wouldn't even consider going back to MMF2/GM/whatever is that they don't have TimeDelta and all the awesomeness that comes with it. Of course there's tons of other stuff that wouldn't make me go back either but they're not really to this topic at hand (and no need to make this thread any more Construct advertising by me than it already is, heh).

It'd be interested in hearing some thoughts on the subject by MMF/GM users, if any of you are passing by!
Logged
Glaiel-Gamer
Guest
« Reply #8 on: January 26, 2010, 01:43:35 PM »

Simplest and most stable way to do this:

Just call update multiple times before rendering, depending on the current time.

I.E., you want to update once every 5 ms, and render (if possible) every 16 ms.

Store a timer, and a frame count. Meaning, if the timer is at 50, the frame count should be at 10.

loop{
while(timer > framecount*5) {
update();
framecount++;
}
render();
}

Since rendering is usually the bottleneck, you get consistent speeds with the stability of fixed framerate, at the expense of sometimes skipping a render to catch up.
Logged
J. Kyle Pittman
Level 6
*


PostCount++;


View Profile WWW
« Reply #9 on: January 26, 2010, 01:43:47 PM »

Delta times and framerate-independent motion are awesome, but they come with their own set of baggage: numerical instability.
Consistent results and stability are kind of separate things; a fixed time step gives consistency but you can still have instability at a fixed timestep.  In other words, the  difference is that you're more likely to see the same instability on all computers with a fixed timestep, while it may only show up on some computers with a delta time step.

Likewise accuracy and stability are separate things -- if you want to guarantee stability, you might look at implicit integration methods instead of increasing the accuracy.
Good point.  I tend to associate instability and inconsistency (since the former often manifests itself as the latter when framerates drop), but you're absolutely correct.
« Last Edit: January 26, 2010, 02:58:03 PM by J. Kyle Pittman » Logged

deadeye
First Manbaby Home
Level 10
*



View Profile
« Reply #10 on: January 26, 2010, 03:04:37 PM »

It'd be interested in hearing some thoughts on the subject by MMF/GM users, if any of you are passing by!

If I'm correct, and I might not be, both MMF and GM have a fixed data rate, but not necessarily a dependent one.  As in, on fast computers the data rate will slow to the target fps, but dependency kicks in when the fps dips below the target, which is why they suffer from slowdown on crappy machines.

Whereas in Construct, if your fps drops dramatically for whatever reason, then your TimeDelta-controlled sprites could conceivably jump right past each other without triggering a collision because the amount of pixels they're moving per frame has risen to much higher than normal.  This can be fixed with code of course (a hassle in itself), but it is the one major drawback of delta-time based framerate independence.

So yeah, both systems have their drawbacks, and they basically both stem from playing the games on crappy computers Tongue
Logged

tweet tweet @j_younger
Zaphos
Guest
« Reply #11 on: January 26, 2010, 03:19:12 PM »

Whereas in Construct, if your fps drops dramatically for whatever reason, then your TimeDelta-controlled sprites could conceivably jump right past each other without triggering a collision because the amount of pixels they're moving per frame has risen to much higher than normal.  This can be fixed with code of course (a hassle in itself), but it is the one major drawback of delta-time based framerate independence.
When I've written delta-time code before I've usually added a maxTimeStep variable that restricts the amount of time you can go forward in one step; if you set maxTimeStep carefully then for the cases where it's so bad that you would have sprites jumping through each other (and other game-breaking issues), you get slowdown instead.
Logged
deadeye
First Manbaby Home
Level 10
*



View Profile
« Reply #12 on: January 26, 2010, 03:28:43 PM »

When I've written delta-time code before I've usually added a maxTimeStep variable that restricts the amount of time you can go forward in one step; if you set maxTimeStep carefully then for the cases where it's so bad that you would have sprites jumping through each other (and other game-breaking issues), you get slowdown instead.

I suppose this could be accomplished in Construct by measuring TimeDelta and adjusting TimeScale accordingly.

Hmm, that's really got me wondering... off to experiment!
Logged

tweet tweet @j_younger
Ivan
Owl Country
Level 10
*


alright, let's see what we can see


View Profile
« Reply #13 on: January 26, 2010, 03:32:08 PM »

Yeah you definitely need a max timestep no matter what. For example in OS X, when you hold down the minimize button, it pauses all updates to the app, so when you release it, your timestamp will be whatever the time you held the minimize button for. Not saying its a big use case, but if you dont limit your time step, it can be used to completely break your game and/or cheat in it.
Logged

http://polycode.org/ - Free, cross-platform, open-source engine.
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #14 on: January 26, 2010, 05:41:28 PM »

Yeah you definitely need a max timestep no matter what. For example in OS X, when you hold down the minimize button, it pauses all updates to the app, so when you release it, your timestamp will be whatever the time you held the minimize button for. Not saying its a big use case, but if you dont limit your time step, it can be used to completely break your game and/or cheat in it.

This is caused by your timers not being in the correct run loop modes.  Add your timer to NSEventTrackingRunLoopMode and that shouldn't happen.
Logged



What would John Carmack do?
Montoli
Level 7
**


i herd u liek...?


View Profile WWW
« Reply #15 on: January 26, 2010, 06:36:34 PM »

because if you do something like "x *= 0.9" every frame, it's not obvious how to make the effect constant across different time steps

This is pretty straight forward. You just have to reconstruct the equation.

x *= 0.9

becomes

x -= x * 0.1

and to being that in line with the timestep

x -= x * 0.1 * timeStep

This math doesn't actually work.  (And demonstrates why this can be harder than it looks.)

We'll assume x = 10:

Case 1:  Fixed timesteps:
Time = 0:
(currently x=10) x *= 0.9
new x = 9
Time = 1:
(currently x=9) x *= 0.9
new x = 8.1


Case 2:  Variable timestep, timestep = 2
Time 0:
(currently x=10) x -= x * 0.1 * timeStep (timestep = 2)
new x = 8

8 != 8.1

This difference seems slight, but it will mount up quickly if it happens every frame.  You will NOT get the same results going variable vs. fixed in this case.

Switching over to variable is not always easy, depending on the circumstance.

-Montoli (feverently hoping he didn't make some stupid glaring math error)
Logged

www.PaperDino.com

I just finished a game!: Save the Date
You should go play it right now.
Glaiel-Gamer
Guest
« Reply #16 on: January 26, 2010, 07:01:24 PM »

x = x * (pow(.99, timeStep))

it's way more of a pain to do that though than it is to just execute the code multiple times
Logged
st33d
Guest
« Reply #17 on: January 27, 2010, 02:01:44 AM »

Fair point, I'm pretty new to this time step stuff.

But I'm making a throwing game with it, so I don't really need to worry about accurate physics.

 Durr...?
Logged
Alex May
...is probably drunk right now.
Level 10
*


hen hao wan


View Profile WWW
« Reply #18 on: January 27, 2010, 02:31:56 AM »

(because if you do something like "x *= 0.9" every frame, it's not obvious how to make the effect constant across different time steps)

float frames = 60.0f * TimeStep;
x *= (float)Math.Pow(0.9, frames);

edit BEATENED

postscript I do like the idea of fixed time steps decoupled from rendering though - it also can help with network stuff if you have actual quantised time that says where something definitely was at a certain time. I think.
Logged

Akari
Level 2
**



View Profile
« Reply #19 on: January 27, 2010, 02:53:48 AM »

When I've written delta-time code before I've usually added a maxTimeStep variable that restricts the amount of time you can go forward in one step; if you set maxTimeStep carefully then for the cases where it's so bad that you would have sprites jumping through each other (and other game-breaking issues), you get slowdown instead.

I suppose this could be accomplished in Construct by measuring TimeDelta and adjusting TimeScale accordingly.

Hmm, that's really got me wondering... off to experiment!

I guess an easy approach would be this:

TimeDelta > 1/25 -> Set timescale to lerp(1,0.1,TimeDelta/TimeScale)

Or something along the lines of that, it would start to slow down a bit at 25fps and gradually slows down if the game runs even slower. It'd start at 3.6% slowdown at 25fps and slow down to 10% of original speed at 1fps.

EDIT: Forgot that timescale affects timedelta values in Construct, so added /TimeScale to the formula above.
« Last Edit: January 27, 2010, 04:16:24 AM by Daiz » Logged
Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic