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 19, 2024, 12:35:14 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Keeping measurements in pixels with fps independence/deltatime
Pages: [1] 2
Print
Author Topic: Keeping measurements in pixels with fps independence/deltatime  (Read 2167 times)
Eendhoorn
Level 6
*

Quak


View Profile
« on: June 20, 2017, 08:10:48 PM »

Turns out players on a slow machine will have an unfair advantage because everything will be in slow-motion for them.
The thing is, I really love measuring my speed in pixels per frame.

If I would simply apply deltatime as usual I would be measuring speed in pixels per second;
Code:
velocity.X += acceleration.X * Time.deltaTime

I was thinking I should just calculate the amount of frames that deltaTime takes at my targeted FPS. Unfortunately the result is extremely jumpy.
Code:
            float targetFPS = 60f;
            float singleFrameDuration = 1f / targetFPS;
            float passedFrames = Time.deltaTime / singleFrameDuration;

            position += velocity * pastFrames;//* Time.timeScale; //* (Time.unscaledDeltaTime - (1f/60f) );

Maybe I'm thinking about this the wrong way, any tips?
Logged

JWki
Level 4
****


View Profile
« Reply #1 on: June 20, 2017, 10:35:12 PM »

Turns out players on a slow machine will have an unfair advantage because everything will be in slow-motion for them.
The thing is, I really love measuring my speed in pixels per frame.

If I would simply apply deltatime as usual I would be measuring speed in pixels per second;
Code:
velocity.X += acceleration.X * Time.deltaTime

I was thinking I should just calculate the amount of frames that deltaTime takes at my targeted FPS. Unfortunately the result is extremely jumpy.
Code:
            float targetFPS = 60f;
            float singleFrameDuration = 1f / targetFPS;
            float passedFrames = Time.deltaTime / singleFrameDuration;

            position += velocity * pastFrames;//* Time.timeScale; //* (Time.unscaledDeltaTime - (1f/60f) );

Maybe I'm thinking about this the wrong way, any tips?

If you want to measure speeds in pixels per tick (which is a really weird metric but okay), you'll want fixed tick rates independent of machine speed - fix your time step, essentially.
Logged
DrHogan
Level 0
***



View Profile WWW
« Reply #2 on: June 20, 2017, 10:35:48 PM »

If I understood correctly the problem, isn't multiplying a speed per Time.deltaTime (or you might consider using the Time.fixedDeltaTime and using FixedUpdate instead of Update for better reliability maybe) already a way to keep movement frame independent?
Logged

Dr.Hogan-Lead Developer at H&R Games
------------------------------------------------------
Empires in ruins
JWki
Level 4
****


View Profile
« Reply #3 on: June 21, 2017, 05:12:34 AM »

If I understood correctly the problem, isn't multiplying a speed per Time.deltaTime (or you might consider using the Time.fixedDeltaTime and using FixedUpdate instead of Update for better reliability maybe) already a way to keep movement frame independent?

He wants to measure in pixels per frame though, not per second.
Logged
DrHogan
Level 0
***



View Profile WWW
« Reply #4 on: June 21, 2017, 07:49:07 AM »

If I understood correctly the problem, isn't multiplying a speed per Time.deltaTime (or you might consider using the Time.fixedDeltaTime and using FixedUpdate instead of Update for better reliability maybe) already a way to keep movement frame independent?

He wants to measure in pixels per frame though, not per second.


you're right, somehow even after reading i "decided" that he wanted to measure in pixels only to solve the issue Wink
Logged

Dr.Hogan-Lead Developer at H&R Games
------------------------------------------------------
Empires in ruins
ferreiradaselva
Level 3
***



View Profile
« Reply #5 on: June 21, 2017, 09:19:05 AM »

Well, it is one way or another. It doesn't make sense to mix them.
Logged

bateleur
Level 10
*****



View Profile
« Reply #6 on: June 21, 2017, 09:28:50 AM »

He wants to measure in pixels per frame though, not per second.

True, but sometimes in order to really answer a question correctly you have to step back from it a bit.

Specifically: movement is not a thing one would normally process per frame. A frame is a video display concept and simulation has nothing to do with that since it's not 1995 anymore.

So yes, absolutely do all motion processing in FixedUpdate where possible. If there's some good technical reason for doing it in Update() then something like this might work:

Code:
 unprocessedTime += Time.deltaTime;
 while (unprocessedTime > my_cycle_duration) {
  unprocessedTime -= my_cycle_duration;
  processOneCycle();
 }
Logged

Richard Kain
Level 10
*****



View Profile WWW
« Reply #7 on: June 22, 2017, 11:22:48 AM »

Calculating anything based on the update, as opposed to some form of time measurement, is a mistake.

This is not to say that you can't have what you want, you just have to go about it in a proper fashion. What you're actually looking for is to change the position of your elements in a pixel-step fashion. You can still calculate this using standard time delta calculations. You just have to throw in a second calculation after the fact to "step" the animation on a per-pixel basis.

It is worth noting that this sort of behavior assumes a 1x1 pixel relationship for sprites, so you wouldn't be able to scale sprites and have this approach work at the same time.
Logged
ferreiradaselva
Level 3
***



View Profile
« Reply #8 on: June 22, 2017, 12:33:51 PM »

Quote
It is worth noting that this sort of behavior assumes a 1x1 pixel relationship for sprites, so you wouldn't be able to scale sprites and have this approach work at the same time.

It is just a matter of rendering in a framebuffer first and then scaling the framebuffer or truncate the position values sent for rendering (if the engine allows it, if not, then the first solution), then it can work for any scale.
« Last Edit: June 22, 2017, 12:56:31 PM by felipefsdev » Logged

J-Snake
Level 10
*****


A fool with a tool is still a fool.


View Profile WWW
« Reply #9 on: June 22, 2017, 02:19:22 PM »

It looks like you need a little more knowledge in game loops. This article will point you to the solution. http://gafferongames.com/game-physics/fix-your-timestep/
Logged

Independent game developer with an elaborate focus on interesting gameplay, rewarding depth of play and technical quality.<br /><br />Trap Them: http://store.steampowered.com/app/375930
Eendhoorn
Level 6
*

Quak


View Profile
« Reply #10 on: July 01, 2017, 12:45:27 PM »

People see C# and they seem to assume you're on unity, I'm using monogame, no such thing as fixed update :p

Turns out players on a slow machine will have an unfair advantage because everything will be in slow-motion for them.
The thing is, I really love measuring my speed in pixels per frame.

If I would simply apply deltatime as usual I would be measuring speed in pixels per second;
Code:
velocity.X += acceleration.X * Time.deltaTime

I was thinking I should just calculate the amount of frames that deltaTime takes at my targeted FPS. Unfortunately the result is extremely jumpy.
Code:
            float targetFPS = 60f;
            float singleFrameDuration = 1f / targetFPS;
            float passedFrames = Time.deltaTime / singleFrameDuration;

            position += velocity * pastFrames;//* Time.timeScale; //* (Time.unscaledDeltaTime - (1f/60f) );

Maybe I'm thinking about this the wrong way, any tips?

If you want to measure speeds in pixels per tick (which is a really weird metric but okay), you'll want fixed tick rates independent of machine speed - fix your time step, essentially.
It's not a weird metric at all, many games work on duration or speed based in frames; It makes a lot more sense to think of how high mario can jump in 10 frames vs how long mario can jump in 0.1667 seconds.

I think I should put more focus on that I want to simulate movement based in 60 frames per second.

Code:
            float targetFPS = 60f;
            float singleFrameDuration = 1f / targetFPS;
            float passedFrames = Time.deltaTime / singleFrameDuration;

So let's say my character moves 3 pixels per frame at the target FPS of 60.
Players on a machine that can only run 30fps should instead move 6 pixels in a single frame, so they moved the same amount of pixels in 1/60 = 0.01667 seconds.

In theory the snippet above should work, but the outcame is very choppy.


(the gif framerate is smooth, the choppyness comes from apply the "passed frames" on the players velocity)

Here's what the "passed frames" look like, pretty stable but every dozen of frames there's a fluctuation which generates the jitter. The gameplay seems unreasonably choppy for such small fluctations so I feel like I'm missing something.

Quote
1.05993
1.05993
1.05993
1.05993
1.05993
1.05993
1.05993
1.05993
1.05993
1.05993
1.05993
1.05993
1.09902
1.09902
1.09902
1.09902
1.09902
1.09902
1.09902
Logged

JWki
Level 4
****


View Profile
« Reply #11 on: July 01, 2017, 01:19:40 PM »

You can still make your update fixed rate, just saying. That'd make things easier.
Logged
Polly
Level 6
*



View Profile
« Reply #12 on: July 01, 2017, 01:25:32 PM »

Code:
float passedFrames = Time.deltaTime / singleFrameDuration;

You can't calculate the number of passed frames like that .. you're omitting the remaining sub-frame time from the last frame.

By the way, i'm not a fan of the fixed time-step approach ( as proposed by some in this thread ) .. just saying Wink
Logged
ThemsAllTook
Administrator
Level 10
******



View Profile WWW
« Reply #13 on: July 01, 2017, 02:11:25 PM »

By the way, i'm not a fan of the fixed time-step approach ( as proposed by some in this thread ) .. just saying Wink

How come? It categorically solves quite a lot of problems, with relatively few drawbacks. If you calculate position adjustments or other things while multiplying by delta time, your simulation becomes nondeterministic and unstable. I'm not saying fixed timestep is perfect, but I'm highly interested to hear what downsides you see to it.
Logged

J-Snake
Level 10
*****


A fool with a tool is still a fool.


View Profile WWW
« Reply #14 on: July 01, 2017, 03:19:39 PM »

People see C# and they seem to assume you're on unity, I'm using monogame, no such thing as fixed update :p
You can (and should) implement a fixed timestep yourself inside monogame then. Most jitters are usually unnecessary and come from numerically unstable game loop implementations (the article I pointed you to presents also an unstable game loop, but the article is a good start for unexperienced). But I won't go into detail about that here.
Logged

Independent game developer with an elaborate focus on interesting gameplay, rewarding depth of play and technical quality.<br /><br />Trap Them: http://store.steampowered.com/app/375930
ferreiradaselva
Level 3
***



View Profile
« Reply #15 on: July 01, 2017, 09:57:00 PM »

It's not a weird metric at all, many games work on duration or speed based in frames; It makes a lot more sense to think of how high mario can jump in 10 frames vs how long mario can jump in 0.1667 seconds.

There's nothing wrong in using delta time-based movement or using frame-based movement. What is weird is mixing both. Which doesn't make sense. One is based on a time that will be different each frame, the other is assumming that each frame will take the same time. It's one or the other.

Be aware that consoles (from that era) at least assumed a kind of game and most of the time that game would run smoothly on that hardware. Consoles were made to run at certain FPS and games were made to run at that FPS. Today, computers have each different hardware, and your game might run nicely on your computer, but maybe it will run super fast on mine or super slow, or worse, sometimes super fast, sometimes slow.
Logged

Polly
Level 6
*



View Profile
« Reply #16 on: July 02, 2017, 02:32:21 AM »

There's nothing wrong in using delta time-based movement or using frame-based movement. What is weird is mixing both.

It's fine. You can have delta-time based movement and use "speed" units / values of for example 3 pixels per frame ( at the default 60 fps ). Multiplied by delta-time this will become 1.5 pixels when running at 120fps and 6 pixels when running at 30fps. So, essentially this means that all his values are multiplied by 60 ( 3 instead of 0.05 ).
Logged
JWki
Level 4
****


View Profile
« Reply #17 on: July 02, 2017, 02:49:18 AM »

Now I'm also curious on what you dislike about fixed timestep tbh.
Logged
Eendhoorn
Level 6
*

Quak


View Profile
« Reply #18 on: July 02, 2017, 05:56:46 AM »

You can still make your update fixed rate, just saying. That'd make things easier.
Well it's a bit unfair that you can just play on a slow pc or purposely slow it down in order to play in slow motion and get a better score :p

People see C# and they seem to assume you're on unity, I'm using monogame, no such thing as fixed update :p
You can (and should) implement a fixed timestep yourself inside monogame then. Most jitters are usually unnecessary and come from numerically unstable game loop implementations (the article I pointed you to presents also an unstable game loop, but the article is a good start for unexperienced). But I won't go into detail about that here.
The framework I'm using (Nez) supplies me with a stable loop already, and supplies me with delta time. I just need to somehow handle the deltatime in such a way that I can still use my pixels per frame values, as opposed to scaling everything to accomodate for the deltatime.

Code:
float passedFrames = Time.deltaTime / singleFrameDuration;

You can't calculate the number of passed frames like that .. you're omitting the remaining sub-frame time from the last frame.

By the way, i'm not a fan of the fixed time-step approach ( as proposed by some in this thread ) .. just saying Wink
The remaining sub-frame? What do you mean exactly? Sounds like the thing I was missing .
I love fixed time steps, keeps thing deterministic. But it would be unfair in this particular project. And I want to give networking a go as well.

There's nothing wrong in using delta time-based movement or using frame-based movement. What is weird is mixing both.

It's fine. You can have delta-time based movement and use "speed" units / values of for example 3 pixels per frame ( at the default 60 fps ). Multiplied by delta-time this will become 1.5 pixels when running at 120fps and 6 pixels when running at 30fps. So, essentially this means that all his values are multiplied by 60 ( 3 instead of 0.05 ).
Yeah I'm not really mixing it, I just explained myself poorly. I don't want to adjust my values to accommodate for delta time as I prefer to think of things in frames when I design movement or durations.
Logged

JWki
Level 4
****


View Profile
« Reply #19 on: July 02, 2017, 06:03:20 AM »

You can still make your update fixed rate, just saying. That'd make things easier.
Well it's a bit unfair that you can just play on a slow pc or purposely slow it down in order to play in slow motion and get a better score :p 

You can't with a fixed timestep, that's part of the point. With a fixed update rate you have EXACTLY 60 or whatever simulation ticks per second when implemented properly, no matter how fast or slow the machine is.
Logged
Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic