What is good cross platform gameloop?

Game development specific discussions.
coderJeff
Site Admin
Posts: 2595
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: What is good cross platform gameloop?

Postby coderJeff » Jun 15, 2018 17:18

About tearing when writing to the display. We have looked at several methods for updating the display. locking, page flipping, etc, There are also several graphics drivers, different on each platform DOS/Win/Lin, etc.

You can see what driver is in use using SCREENCONTROL(fb.GET_DRIVER_NAME,s). If you want to try and force a driver, set the environment variable FBGFX=driver, where driver is DirectX or GDI, for example.

To eliminate tearing, we want to synchronize writing to the display memory, so we won't see top part a frame and the bottom part of the last. Typically some kind of wait for vertical blanking interrupt. SCREENSYNC is supposed to provide

DOS: polls hardware Port &h3DA
Linux: polls ioctl for the device vertical blank interrupt
Windows - DirectX: IDirectDraw2_WaitForVerticalBlank
Windows - GDI: sleep( 1000/refresh_rate) - it's fake.

On Win7 64bit, fbc 64-bit, DirectX (DirectDraw) driver always fails, so always GDI driver is used. Which means, always always going to see tearing in windows even in fullscreen.
On Win7 64bit, with fbc 32-bit, windows provides enough emulation that DirectX succeeds, IDirectDraw2_WaitForVerticalBlank works correctly in fullscreen mode (but not in windowed mode).

It's possible that there is a bug in initializing DirectX on fbc-64bit, but with the DirectDraw interface deprecated by Microsoft, I kind of doubt it.
coderJeff
Site Admin
Posts: 2595
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: What is good cross platform gameloop?

Postby coderJeff » Jun 15, 2018 18:22

dodicat wrote:Here is my simple idea.
1) fix a frame rate via a regulator, and keep it at that value throughout.
or
2) Enable various frame rates, but keep the screen motion constant.

I think a fixed frame rate gives more predictable results. In this next demo, I try to expand on your idea to show what can happen. The results are intended to be a bit exaggerated so the differences show up easily.

I had a closer look at your pendulum example and see you are using approximation formula for the pendulum position (angle). i.e. position(t) = formula(t), Also, visually, very noticeable that there are two pendulums with same length, and different periods.

I wrote a version of the pendulum code that:
1) uses units: meters, seconds, radians
2) shows 6 pendulums
3) the top 3 using the approximation formula, at x1, x2, x4 physics frame rates.
4) the bottom 3 using newton laws, numerical integration, at x1, x2, x4 physics frame rates.
5) Can toggle between fixed and variable frame rate.
6) press SPACE to add 0.5 second delay and see how methods respond.
7) +/- to change starting position of the pendulums
8) [ ] to change the pendulum length

Code: Select all

#include once "fbgfx.bi"
#include once "vbcompat.bi"

const pi = 3.14159265
const g = -9.81

dim shared pen_color( 1 to 6 ) as ulong = _
   { _
      rgb(127, 255, 255), rgb(255, 127, 255), rgb(255, 255, 127), _
      rgb(255, 63, 63), rgb(63, 255, 63), rgb(63, 63, 255) _
   }

type PENDULUM
   px as single          '' [m] pivot point x
   py as single          '' [m] pivot point y
   length as single      '' [m]
   radius as single      '' [m]
   amplitude as single   '' [radians]
   col as ulong          '' colour

   '' newton
   last_w as single      '' last angular velocity
   w as single           '' angular velocity

   '' calculated
   h_angle as single     '' [radians] harmonic (approximation)
   theta as single       '' [radians] calculate position angle
   bx as single          '' [m] center of mass x
   by as single          '' [m] center of mass y

   last_dtheta as single '' [radians] last change in theta
   tstart as double      '' [s] start of period
   last_T as double      '' [s] last measured period
   isstart as boolean    '' true = at start of period

   declare sub SetPosition( x as single, y as single, l as single, r as single, a_amp as single, c as ulong )
   declare sub physApprox( dt as const double )
   declare sub physNewton( dt as const double )
   declare sub draw()
end type

sub PENDULUM.SetPosition( x as single, y as single, l as single, r as single, a_amp as single, c as ulong )
   px = x
   py = y
   length = l
   radius = r
   amplitude = a_amp
   col = c
   w = 0
   last_w = 0
   h_angle = 0
   theta = a_amp
   bx = px + sin( theta ) * length
   by = py + cos( theta ) * length
   last_dtheta = 0
   tstart = timer
   last_T = 0
   isstart = true
end sub

sub PENDULUM.draw()
   
   color rgb(255,255,255)
   ..draw string (px, py - pmap(20, 2)), "T=" & format(last_T, "0.00" ) & " sec"

   line ( px, py ) - ( bx, by ), col
   circle ( bx, by ), radius, col,,,,f
end sub

sub PENDULUM.physApprox( dt as const double )
   
   dim theta0 as single = theta
   
   '' approximate angle, T = 2pi * sqr( L/-g )
   '' where:
   ''   T = period [seconds]
   ''   L = length [m]
   
   h_angle += dt / sqr( length / -g )

   '' theta = approximate position angle
   theta = cos( h_angle ) * amplitude
   bx = px + sin( theta ) * length
   by = py + cos( theta ) * length

   '' calculate change in theta
   dim as single dtheta = theta - theta0

   '' start of period?
   isstart = false
   if ( sgn(last_dtheta) <= 0 ) and ( sgn(dtheta) > 0 ) then
      dim t as double = timer
      last_T = t - tstart
      tstart = t
      isstart = true
   end if
   last_dtheta = dtheta

end sub

sub PENDULUM.physNewton( dt as const double )
   
   dim theta0 as single = theta

   '' compute the change in angular velocity
   '' and angular position

   '' project acceleration due to gravity
   '' on to direction of movement vector

   dim at as single = g * sin( theta )
   
   '' angular velocity
   last_w = w
   w += at * dt / length

   '' change in position
   theta += w * dt

   '' normalize angle
   if( theta > pi ) then theta -= 2 * pi
   if( theta < -pi ) then theta += 2 * pi

   '' calculate position
   bx = px + sin( theta ) * length
   by = py + cos( theta ) * length

   '' calculate change in theta
   dim as single dtheta = theta - theta0

   '' start of period?
   isstart = false
   if ( sgn(last_w) <= 0 ) and ( sgn(w) > 0 ) then
      dim t as double = timer
      last_T = t - tstart
      tstart = t
      isstart = true
   end if
   last_dtheta = dtheta

end sub

type FRAMETIMELIST
   const MAXTIMES = 60
   tlist(0 to MAXTIMES-1) as double
   thead as integer
   declare sub add( dt as double )
   declare sub draw()
end type

sub FRAMETIMELIST.add( dt as double )
   '' circular buffer to store times
   tlist( thead ) = dt
   thead = (thead + 1) mod MAXTIMES
end sub

sub FRAMETIMELIST.draw()
   dim curr as integer = thead, i as integer
   do
      line( 0, i * 6 + 1 ) - ( tlist(curr) * 1000, i * 6 + 4 ), rgb( 192, 127, 127 ), bf
      curr = (curr + 1) mod MAXTIMES
      i += 1
   loop while curr <> thead
end sub

type GRAPH
   const MAXPOINTS = 1000
   tlist(0 to MAXPOINTS-1, 1 to 6) as double
   thead as integer
   declare sub add( a1 as double, a2 as double, a3 as double, a4 as double, a5 as double , a6 as double)
   declare sub draw()
end type

sub GRAPH.add( a1 as double, a2 as double, a3 as double, a4 as double, a5 as double , a6 as double)
   '' circular buffer to store times
   tlist( thead, 1 ) = a1
   tlist( thead, 2 ) = a2
   tlist( thead, 3 ) = a3
   tlist( thead, 4 ) = a4
   tlist( thead, 5 ) = a5
   tlist( thead, 6 ) = a6
   thead = (thead + 1) mod MAXPOINTS
end sub

sub GRAPH.draw()
   for j as integer = 1 to 6
      dim curr as integer = thead, i as integer
      pset( i, 500 + tlist(curr,j) * 50 ), pen_color(j)
      curr = (curr + 1) mod MAXPOINTS
      do
         line -( i, 500 + tlist(curr,j) * 50 ), pen_color(j)
         curr = (curr + 1) mod MAXPOINTS
         i += 1
      loop while curr <> thead
   next
end sub

sub ResetAllPendula( p() as PENDULUM, start_length as single, start_angle as single )
   p(1).SetPosition( 2, 1, start_length, 0.25, start_angle, pen_color(1) )
   p(2).SetPosition( 4, 1, start_length, 0.25, start_angle, pen_color(2) )
   p(3).SetPosition( 6, 1, start_length, 0.25, start_angle, pen_color(3) )
   p(4).SetPosition( 2, 3, start_length, 0.25, start_angle, pen_color(4) )
   p(5).SetPosition( 4, 3, start_length, 0.25, start_angle, pen_color(5) )
   p(6).SetPosition( 6, 3, start_length, 0.25, start_angle, pen_color(6) )
end sub

'' main
dim ft as FRAMETIMELIST
dim gt as GRAPH

dim p( 1 to 6 ) as PENDULUM
dim start_angle as single = (pi/8)
dim start_length as single = 1
ResetAllPendula( p(), start_length, start_angle )

screenres 1024, 768, 32

dim k as string
dim as double t1 = timer, t2, dt

dim refresh_rate as integer
ScreenControl( fb.GET_SCREEN_REFRESH, refresh_rate )
dim fixed_time as double = 1/cdbl(refresh_rate)
dim use_fixed_rate as boolean = false

do
   t2 = timer
   dt = t2- t1
   t1 = t2

   ft.add dt

   if( use_fixed_rate ) then
      if( dt > fixed_time ) then
         dt = fixed_time
      end if
   end if
   
   '' input

   k = inkey
   select case k
   case chr(255) & chr(&h6b)
      exit do
   case chr(27)
      sleep
      exit do
   case "f", "F"
      use_fixed_rate = true
   case "v", "V"
      use_fixed_rate = false
   case "+"
      start_angle += (pi/16)
      ResetAllPendula( p(), start_length, start_angle )
   case "-"
      start_angle -= (pi/16)
      ResetAllPendula( p(), start_length, start_angle )
   case "["
      if start_length > 0.3 then
         start_length -= 0.1
         for i as integer = 1 to 6
            p(i).length = start_length
         next
      end if
   case "]"
      start_length += 0.1
      for i as integer = 1 to 6
         p(i).length = start_length
      next
   case " "
      sleep 500,1
   end select

   '' physics
   p(1).physApprox( dt )
   p(4).physNewton( dt )

   '' double physics
   for i as integer = 0 to 1
      p(2).physApprox( dt/2 )
      p(5).physNewton( dt/2 )
   next i

   '' quadruple physics
   for i as integer = 0 to 3
      p(3).physApprox( dt/4 )
      p(6).physNewton( dt/4 )
   next

   gt.add p(1).theta, p(2).theta, p(3).theta, p(4).theta, p(5).theta, p(6).theta

   '' draw everything
   window screen (0, 0)-(10, 8)
   screensync
   cls
   for i as integer = 1 to 6
      p(i).draw
   next

   window screen (0, 0)-(1000,750)
   ft.draw
   gt.draw

   window screen
   color rgb( 127, 127, 127 )
   locate 2, 10: print "Keys: V=Variable, F=Fixed, SPACE=0.5 sec DELAY, ESC=Exit"
   locate 3, 10: print "      +- Inc Dec Start Angle     [] Inc Dec bar length"
   print
   locate 5, 10
   print "Current Mode: ";
   color rgb( 255, 255, 255 )
   if( use_fixed_rate ) then
      print "FIXED"
   else
      print "VARIABLE"
   end if

loop


Image
Last edited by coderJeff on Jun 15, 2018 20:07, edited 1 time in total.
Reason: Update GRAPH.Draw() routine
fxm
Posts: 8052
Joined: Apr 22, 2009 12:46
Location: Paris suburb, FRANCE

Re: What is good cross platform gameloop?

Postby fxm » Jun 15, 2018 18:35

Aborting due to runtime error 6 (out of bounds array access) at line 191 of C:\Users\fxmam\Documents\Mes Outils Personnels\FBIde0.4.6r4-FreeBASIC1.06.0.win64\FBIDETEMP.bas::DRAW()
coderJeff
Site Admin
Posts: 2595
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: What is good cross platform gameloop?

Postby coderJeff » Jun 15, 2018 19:32

fxm, I copied source from forum and tried it, assuming -exx option. fb 1.04 32-bit gas, 1.05 32-bit gas, current git fbc 1.06 32 bit gas & 64 bit gcc, I cannot make this error happen. What is your fbc command line options? I notice that I get gcc compile warnings fbc -gen gcc - O 1 and higher -O.
fxm
Posts: 8052
Joined: Apr 22, 2009 12:46
Location: Paris suburb, FRANCE

Re: What is good cross platform gameloop?

Postby fxm » Jun 15, 2018 19:42

FreeBASIC1.06.0 64-bit (Win 10) with compile option: -exx -w pedantic
Without doing anything, runtime error after about 20 seconds.

Same behavior with FreeBASIC1.06.0 32-bit gas (Win 10).
fxm
Posts: 8052
Joined: Apr 22, 2009 12:46
Location: Paris suburb, FRANCE

Re: What is good cross platform gameloop?

Postby fxm » Jun 15, 2018 19:46

(191) line -( i, 500 + tlist(curr,j) * 50 ), pen_color(j)
curr = 1000 inducing the runtime error.

Program works with this fix:

Code: Select all

sub GRAPH.draw()
   for j as integer = 1 to 6
      dim curr as integer = thead, i as integer
      pset( i, 500 + tlist(curr,j) * 50 ), pen_color(j)
      curr += 1
      do
         curr = (curr + 1) mod MAXPOINTS
         line -( i, 500 + tlist(curr,j) * 50 ), pen_color(j)
'         curr = (curr + 1) mod MAXPOINTS
         i += 1
      loop while curr <> thead
   next

end sub

[edit]
See the right fix below.
Last edited by fxm on Jun 15, 2018 20:12, edited 1 time in total.
coderJeff
Site Admin
Posts: 2595
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: What is good cross platform gameloop?

Postby coderJeff » Jun 15, 2018 20:06

Ahh, I see it now, I was too impatient. here's what it should be:

Code: Select all

sub GRAPH.draw()
   for j as integer = 1 to 6
      dim curr as integer = thead, i as integer
      pset( i, 500 + tlist(curr,j) * 50 ), pen_color(j)
      curr = (curr + 1) mod MAXPOINTS
      do
         line -( i, 500 + tlist(curr,j) * 50 ), pen_color(j)
         curr = (curr + 1) mod MAXPOINTS
         i += 1
      loop while curr <> thead
   next
end sub

Previously, there was a "curr += 1" statement that could case the array access to go out of bounds. Thanks, fxm. Updated the original post.
h4tt3n
Posts: 661
Joined: Oct 22, 2005 21:12
Location: Denmark

Re: What is good cross platform gameloop?

Postby h4tt3n » Jun 23, 2018 13:21

Hello folks,

First post in a looong time. I've been tampering with a game loop that treats framerate a bit as a damped spring or a constraint. As much cpu time as possible is freed with sleep. By setting the "stiffness" c_sleep to a near 1.0 value, it reaches an equilibrium faster, but you risk large fluctuations. By setting c_sleep to a near 0.0 value, the equation converges slower but is more stable. Press space to give the cpu a lot of heavy work, and notice how it does not affect frame rate:

Code: Select all

''
''
''
#Include "fbgfx.bi"

Using fb

''
Const As Double c_sleep         = 0.5                   '' sleep correction coefficient [0.0 - 1.0]
Const As Double max_sleep_s     = 1.0                   '' max. sleep time ( seconds )
Const As Double min_sleep_s     = 0.001                 '' min. sleep time ( seconds )
Const As Double rest_velocity   = 60.0                  '' desired frame rate ( loops / second )
Const As Double rest_delta_time     = 1.0 / rest_velocity '' desired loop time ( seconds / loop )

Dim As Double acceleration  = 0.0 '' delta frame rate ( loops / second^2 )
Dim As Double velocity      = 0.0 '' actual frame rate ( loops / second )
Dim As Double last_velocity = 0.0 '' actual frame rate ( loops / second )
Dim As Double delta_time_error  = 0.0 '' loop error time ( seconds )
Dim As Double last_loop_s   = 0.0 '' last loop time ( seconds )
Dim As Double this_loop_s   = 0.0 '' current time ( seconds )
Dim As Double delta_time    = 0.0 '' time it takes to do one loop ( seconds )
Dim As Double sleep_s       = 0.0 '' sleep time ( seconds )

Dim As Integer sleep_ms = 0 '' sleep time ( milliseconds )

Dim As Boolean game_is_running = TRUE  ''
Dim As Boolean game_is_working = FALSE ''

ScreenRes( 800, 600, 32 )

While( game_is_running )
   
   '' input
   game_is_running = IIf( MultiKey( fb.SC_ESCAPE ), FALSE, TRUE  )
   game_is_working = IIf( MultiKey( fb.SC_SPACE ) , TRUE , FALSE )
   
   '' loop time ( seconds )
   last_loop_s = this_loop_s
   this_loop_s = Timer()
   delta_time = this_loop_s - last_loop_s
   
   '' loops per second ( framerate )
   last_velocity = velocity
   velocity = 1.0 / delta_time
   
   acceleration = ( velocity - last_velocity ) / delta_time
   
   '' loop time error ( seconds )
   delta_time_error = delta_time - rest_delta_time
   
   '' adjust sleep time ( seconds )
   sleep_s -= delta_time_error * c_sleep
   
   '' clamp sleep time ( seconds )
   If( sleep_s > max_sleep_s ) Then sleep_s = max_sleep_s
   If( sleep_s < min_sleep_s ) Then sleep_s = min_sleep_s
   
   '' sleep time ( integer milliseconds )
   sleep_ms = Cast( Integer, sleep_s * 1000 )
   
   '' sleep
   Sleep( sleep_ms, 1 )
   
   '' write data to screen
   ScreenLock
      
      Cls
      
      Locate  2, 2: Print " delta_time      " & delta_time
      Locate  4, 2: Print " rest_delta_time     " & rest_delta_time
      Locate  6, 2: Print " delta_time_error    " & delta_time_error
      Locate  8, 2: Print " sleep_s         " & sleep_s
      Locate 10, 2: Print " sleep_ms        " & sleep_ms
      Locate 12, 2: Print " velocity        " & velocity
      Locate 14, 2: Print " acceleration    " & acceleration
      Locate 16, 2: Print " rest_velocity   " & rest_velocity
      Locate 18, 2: Print " game_is_working " & game_is_working
      
   ScreenUnLock
   
   '' do some cpu-heavy work to test sleep time correction
   If( game_is_working ) Then
      
      For i As Integer = 1 To 50000
         
         Dim As Single temp = Log( Sqr(i) )
         
      Next
      
   EndIf
   
Wend


Cheers Mike
h4tt3n
Posts: 661
Joined: Oct 22, 2005 21:12
Location: Denmark

Re: What is good cross platform gameloop?

Postby h4tt3n » Jun 23, 2018 13:32

Here is the "Fix your timestep" game loop tutorial by Glemm Fiedler, converted to FreeBASIC.

Cheers, Mike

Part 1: Fixed delta time

Code: Select all

''
'' Glenn Fiedler game loop tutorial
'' Code sample # 1
'' http://gafferongames.com/game-physics/fix-your-timestep/
'' Fixed delta time

'double t = 0.0;
'double dt = 1.0 / 60.0;
'
'while ( !quit )
'{
'    integrate( state, t, dt );
'    render( state );
'    t += dt;
'}

Dim As Double t = 0.0
Dim As Double dt = 1.0 / 60.0

Dim As Boolean quit = FALSE

While( Not quit )
   
   ''integrate( state, t, dt )
   ''render( state )
   Print "t:" & t
   
   t += dt
   
   If MultiKey(1) Then quit = TRUE
      
Wend


Part 2: Variable delta time

Code: Select all

''
'' Glenn Fiedler game loop tutorial
'' Code sample # 2
'' http://gafferongames.com/game-physics/fix-your-timestep/
'' Variable delta time

'double t = 0.0;
'
'double currentTime = hires_time_in_seconds();
'
'while ( !quit )
'{
'    double newTime = hires_time_in_seconds();
'    double frameTime = newTime - currentTime;
'    currentTime = newTime;
'
'    integrate( state, t, frameTime );
'    t += frameTime;
'
'    render( state );
'}

Dim As Double t = 0.0

Dim As Double currentTime = Timer()

Dim As Boolean quit = FALSE

While( Not quit )
   
   Dim As Double newTime = Timer()
   Dim As Double frameTime = newTime - currentTime
   
   currentTime = newTime
   
   ''integrate( state, t, frameTime )
   
   t += frameTime
   
   ''render( state )
   
   Locate 2, 2: Print" currentTime: " & currentTime
   Locate 4, 2: Print" newTime: " & newTime
   Locate 6, 2: Print" frameTime: " & frameTime
   
   If MultiKey(1) Then quit = TRUE
      
Wend


Part 3: Semi-fixed time step

Code: Select all

''
'' Glenn Fiedler game loop tutorial
'' Code sample # 3
'' http://gafferongames.com/game-physics/fix-your-timestep/
'' Semi-fixed time step

'double t = 0.0;
'double dt = 1 / 60.0;
'
'double currentTime = hires_time_in_seconds();
'
'while ( !quit )
'{
'    double newTime = hires_time_in_seconds();
'    double frameTime = newTime - currentTime;
'    currentTime = newTime;
'         
'    while ( frameTime > 0.0 )
'    {
'        float deltaTime = min( frameTime, dt );
'        integrate( state, t, deltaTime );
'        frameTime -= deltaTime;
'        t += deltaTime;
'    }
'
'    render( state );
'}

Dim As Double t = 0.0
Dim As Double dt = 1.0 / 60.0
Dim As Double deltaTime = 0.0

Dim As Double currentTime = Timer()

Dim As Boolean quit = FALSE

While( Not quit )
   
   Dim As Double newTime = Timer()
   Dim As Double frameTime = newTime - currentTime
   
   currentTime = newTime
   
   While( frameTime > 0.0 )
      
      deltaTime = IIf( frameTime < dt , frameTime, dt )
      ''integrate( state, t, deltaTime )
      frameTime -= deltaTime
      t += deltaTime
      
   Wend
   
   ''render( state )
   
   Locate 2, 2: Print" currentTime: " & currentTime
   Locate 4, 2: Print" newTime: " & newTime
   Locate 6, 2: Print" frameTime: " & frameTime
   Locate 8, 2: Print" deltaTime: " & deltaTime
   
   If MultiKey(1) Then quit = TRUE
      
Wend


Part 4: Free the physics

Code: Select all

''
'' Glenn Fiedler game loop tutorial
'' Code sample # 1
'' http://gafferongames.com/game-physics/fix-your-timestep/
'' Free the physics

'double t = 0.0;
'const double dt = 0.01;
'
'double currentTime = hires_time_in_seconds();
'double accumulator = 0.0;
'
'while ( !quit )
'{
'    double newTime = hires_time_in_seconds();
'    double frameTime = newTime - currentTime;
'    currentTime = newTime;
'
'    accumulator += frameTime;
'
'    while ( accumulator >= dt )
'    {
'        integrate( state, t, dt );
'        accumulator -= dt;
'        t += dt;
'    }
'
'    render( state );
'}


Dim As Double t = 0.0
Dim As Double dt = 0.01

Dim As Double currentTime = Timer()
Dim As Double accumulator = 0.0

Dim As Boolean quit = FALSE

While( Not quit )
   
   Dim As Double newTime = Timer()
   Dim As Double frameTime = newTime - currentTime
   
   currentTime = newTime
   
   accumulator += frameTime
   
   While( accumulator >= dt )
      
      ''integrate( state, t, dt )
      accumulator -= dt
      t += dt
      
   Wend
   
   ''render( state )
   
   Locate 2, 2: Print" currentTime: " & currentTime
   Locate 4, 2: Print" newTime: " & newTime
   Locate 6, 2: Print" frameTime: " & frameTime
   Locate 8, 2: Print" accumulator: " & accumulator
   
   If MultiKey(1) Then quit = TRUE
      
Wend


Part 5: The final touch

Code: Select all

''
'' Glenn Fiedler game loop tutorial
'' Code sample # 1
'' http://gafferongames.com/game-physics/fix-your-timestep/
'' The final touch

'double t = 0.0;
'double dt = 0.01;
'
'double currentTime = hires_time_in_seconds();
'double accumulator = 0.0;
'
'State previous;
'State current;
'
'while ( !quit )
'{
'    double newTime = time();
'    double frameTime = newTime - currentTime;
'    if ( frameTime > 0.25 )
'        frameTime = 0.25;
'    currentTime = newTime;
'
'    accumulator += frameTime;
'
'    while ( accumulator >= dt )
'    {
'        previousState = currentState;
'        integrate( currentState, t, dt );
'        t += dt;
'        accumulator -= dt;
'    }
'
'    const double alpha = accumulator / dt;
'
'    State state = currentState * alpha +
'        previousState * ( 1.0 - alpha );
'
'    render( state );
'}

Dim As Double t = 0.0
Dim As Double dt = 1.0 / 60.0'0.01

Dim As Double currentTime = Timer()
Dim As Double accumulator = 0.0

Dim As Boolean quit = FALSE

While( Not quit )
   
   Dim As Double newTime = Timer()
   Dim As Double frameTime = newTime - currentTime
   
   If ( frameTime > 0.25 ) Then frameTime = 0.25
   
   currentTime = newTime
   
   accumulator += frameTime
   
   While( accumulator >= dt )
      
      ''previousState = currentState
      ''integrate( currentState, t, dt )
      t += dt
      accumulator -= dt
      
   Wend
   
   Dim As Double alpha_ = accumulator / dt
   
'   State state = currentState * alpha +
'        previousState * ( 1.0 - alpha )
   
   ''render( state )
   
   Locate 2, 2: Print" currentTime: " & currentTime
   Locate 4, 2: Print" newTime: " & newTime
   Locate 6, 2: Print" frameTime: " & frameTime
   Locate 8, 2: Print" accumulator: " & accumulator
   
   If MultiKey(1) Then quit = TRUE
      
Wend
badidea
Posts: 771
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: What is good cross platform gameloop?

Postby badidea » Jun 23, 2018 13:54

In case someone wonders who Glemm Fiedler is, see: https://gafferongames.com/ (multiple game related tutorials).
Last edited by badidea on Jun 24, 2018 8:37, edited 1 time in total.
coderJeff
Site Admin
Posts: 2595
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: What is good cross platform gameloop?

Postby coderJeff » Jun 24, 2018 2:23

h4tt3n wrote:I've been tampering with a game loop that treats framerate a bit as a damped spring or a constraint.

Neat! Thank you for sharing. This idea, plus dodicat's idea of regulator, sparked an idea for me. In process automation, to control a continuous process, a feedback loop is used with a PID controller. In this case for example: measure an output variable from the process, like frame rate, or frame time, use it in a proportional/integral/derivative function, to set a input variable to the process, like, sleep time, or simulation time. Too complicated? Probably. I think it's interesting though.

Thanks for the conversions of the tutorial code samples. Short and easy to digest for comparison.
MrSwiss
Posts: 2585
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: What is good cross platform gameloop?

Postby MrSwiss » Jun 24, 2018 12:06

coderJeff wrote:In process automation, to control a continuous process, a feedback loop is used with a PID controller.
Too complicated? Probably. I think it's interesting though.
Since I've been working professionally with such systems, I think that, a back propagating AN,
could be the anwswer, to the "too complicated" question. Because currently, the engineer
entering/adjusting the PID's parameters, has to play the part (of the AN).
This is the reason, that such adjustments (based on experience alone) do take quite some
time, until the optimal settings have been achieved (since, outside conditions may vary).

Return to “Game Dev”

Who is online

Users browsing this forum: No registered users and 1 guest