Author Topic: Frame Limiting/Compensation  (Read 179 times)

Offline Steve Elliott

  • Hero Member
  • *****
  • Posts: 667
Frame Limiting/Compensation
« on: November 14, 2017, 02:00:16 PM »
What approach are people taking these days regards frame speed/compensation?
Windows 10, 64-bit, 8Gb RAM, CPU Intel i5, 3.2 GHz, Nvidia GeForce GTX 750 Ti (2Gb)

Online Derron

  • Sr. Member
  • ****
  • Posts: 257
Re: Frame Limiting/Compensation
« Reply #1 on: November 14, 2017, 02:35:42 PM »
Movement Interpolation / Tweening
and traditional delta timing.

So for rendering you mix "last render position" with "now".

For physics ("update loop") you use delta timing ("how much time passed since last step in comparison to the time span each step has").


bye
Ron

Offline BasicBoy

  • Jr. Member
  • **
  • Posts: 39
Re: Frame Limiting/Compensation
« Reply #2 on: November 14, 2017, 04:13:35 PM »
For my SB compo entry I'll be using delta time, obtained via Windows' QueryPerformanceCounter for high precision (although with deltas scaled to milliseconds which should be accurate enough for my purposes). If high precision timers aren't available (they usually will be with Windows PCs), then I can always fall back on timeGetTime or GetTickCount.








 

Offline Qube

  • Administrator
  • Hero Member
  • *****
  • Posts: 504
Re: Frame Limiting/Compensation
« Reply #3 on: November 14, 2017, 05:12:44 PM »
I use delta timing with averaging over X frames.
Until the next time...

Offline therevills

  • Full Member
  • ***
  • Posts: 154
Re: Frame Limiting/Compensation
« Reply #4 on: November 14, 2017, 10:39:55 PM »
This page has a great write up of various framing routines:

http://www.koonsolo.com/news/dewitters-gameloop/

In Diddy2 I've coded a few ways and settled on fixed rate logic and tweening when needed:

https://github.com/therevills/diddy2/blob/master/deltatiming.monkey2
Code: [Select]
' converted from http://www.rightanglegames.com/top-down-shooter-tutorial-with-blitzmax.html
Class FixedRateLogicTimer
Field newTime:Double = Millisecs()
Field oldTime:Double = Millisecs()
Field delta:Float
Field dssOn:Int ' do we use delta spike suppression?
Field dssIndex:Int ' index into DSS_Array where next delta value is written
Field dssArray:Float[] ' this array contains the delta values to smooth
Field dssLenArray:Int ' how big is the array of delta values

Field logicFPS:Float
Field accumulator:Float
Field tween:Float

Field fpsAccumulator:Float
Field updateCount:Int
Field renderCount:Int
Field updatesPerSecond:Int
Field rendersPerSecond:Int
Field logicCyclesPerSecond:Float

Method New(logicCyclesPerSecond:Float, numSamples:Int = 0)
Self.logicCyclesPerSecond = logicCyclesPerSecond
logicFPS = 1.0 / logicCyclesPerSecond
If numSamples
dssOn = True
dssArray = New Float[numSamples]
dssLenArray = numSamples
End
End

Method ProcessTime:Float()
newTime = Millisecs()
delta = Float (newTime - oldTime) * 0.001
oldTime = newTime

If dssOn
dssArray[dssIndex] = delta

Local smoothDelta:Float = 0

For Local i:Int = 0 To dssLenArray - 1
smoothDelta += dssArray[i]
Next
delta = Float(smoothDelta / dssLenArray)

dssIndex += 1
If dssIndex > dssLenArray - 1 Then dssIndex = 0
End

accumulator += delta

fpsAccumulator += delta

If fpsAccumulator > 1.0
fpsAccumulator -= 1.0
updatesPerSecond = updateCount
updateCount = 0
rendersPerSecond = renderCount
renderCount = 0
End
Return delta
End

Method LogicUpdateRequired:Int()
If accumulator > logicFPS
updateCount += 1
accumulator -= logicFPS
Return True
End
Return False
End

Method CalcFrameTime:Float(ms:Float)
Local amount:Float = updatesPerSecond
If amount = 0
amount = logicCyclesPerSecond
End
' convert Hz to ms
Local msPerFrame:Float = 1000.0 / amount
' convert ms to frame time
Local rv:Float = ms / msPerFrame
Return rv
End

Method GetLogicFPS:Float()
Return logicFPS
End

Method GetTween:Float()
renderCount += 1
Return accumulator / logicFPS
End

Method ShowSpikeSuppression(x:Int, y:Int, canvas:Canvas)
Local ty:Int = y - (canvas.Font.Height * (3 + Self.dssLenArray))
canvas.DrawText("Delta Spike Suppressor:", x, ty)
ty += canvas.Font.Height
For Local i:Int = 0 To Self.dssLenArray - 1
canvas.DrawText(dssArray[i], x, ty)
ty += canvas.Font.Height
Next

ty += canvas.Font.Height
canvas.DrawText("Final Delta: " + delta, x, ty)
End

Method ShowFPS(x:Int, y:Int, canvas:Canvas, showUpdateFPS:Int = True, showRenderFPS:Int = True)
Local ty:Int = y - (canvas.Font.Height * 2)

If showUpdateFPS
canvas.DrawText("Logic FPS:  " + updatesPerSecond, x, ty)
ty += canvas.Font.Height
End
If showRenderFPS
canvas.DrawText("Render FPS: " + rendersPerSecond, x, ty)
End
End
End

And how to use it:

Code: [Select]
Global GameTime:FixedRateLogicTimer
Const UPDATE_FREQUENCY:Float = 100.0
Const SPIKE_SUPPRESSION:Int = 10
...
GameTime = New FixedRateLogicTimer(UPDATE_FREQUENCY, SPIKE_SUPPRESSION)
...

...
Local tween:Float
Local delta:Float = GameTime.ProcessTime()
While GameTime.LogicUpdateRequired()
GameLogic(GameTime.GetLogicFPS())
End
tween = GameTime.GetTween()
GameRender(tween)

Offline Steve Elliott

  • Hero Member
  • *****
  • Posts: 667
Re: Frame Limiting/Compensation
« Reply #5 on: November 14, 2017, 11:41:19 PM »
Thanks guys.   :)
Windows 10, 64-bit, 8Gb RAM, CPU Intel i5, 3.2 GHz, Nvidia GeForce GTX 750 Ti (2Gb)

Offline Matty

  • Jr. Member
  • **
  • Posts: 58
Re: Frame Limiting/Compensation
« Reply #6 on: November 18, 2017, 10:28:05 AM »
My approach is non standard but works fine.

If your game, like mine, is non heavy on the CPU and the problem is more likely that the CPU is too fast rather than too slow I simply do this (blitz3d code)

main loop
{
stime = millisecs()
do everything
rendereverything
stime = millisecs() - stime
if stime < 15 then
        delay 15 - stime
endif
}

keeps everything moving nice and the same rate...I generally have simple games that don't exercise the CPU too hard.