FreeBasic's Timer

General FreeBASIC programming questions.
Post Reply
fxm
Moderator
Posts: 11930
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

Lite procedure for in-loop regulating the FPS

At the end of the wiki (in an appendix), I could propose a lite version of regulation, universal without thresholds to adjust and not bringing significant CPU load (adapted to old PC), a version that I have already named 'regulateLite()'.
But this lite version is less precise (precision of the 'Sleep' keyword that is some ms quantification, instead of a few microseconds) and does not support high FPS because it cannot generate waiting times lower than the OS cycle period (corresponding to 'Sleep 1,1').

All-in-one 'regulateLite()' version:

Code: Select all

Function regulateLite(ByVal MyFps As Ulong) As Ulong
    '' 'MyFps' : requested FPS value, in frames per second
    '' function return : applied FPS value, in frames per second
    Static As Double t1
    Dim As Single tf = 1 / MyFps
    Dim As Double t3 = t1 + tf
    Dim As Double t2 = Timer
    #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
    If t2 < t1 Then t1 -= 24 * 60 * 60
    #endif
    Dim As Single dt = (tf - (t2 - t1)) * 1000
    Sleep Iif(dt > 1, dt, 1), 1
    t2 = Timer
    #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
    If t2 < t1 Then t1 -= 24 * 60 * 60
    #endif
    tf = 1 / (t2 - t1)
    t1 = t2
    Return tf
End Function

Example of use/test:

Code: Select all

'Declare Function _setTimer Lib "winmm" Alias "timeBeginPeriod"(ByVal As Ulong = 1) As Long
'_setTimer()

Function regulateLite(ByVal MyFps As Ulong) As Ulong
    '' 'MyFps' : requested FPS value, in frames per second
    '' function return : applied FPS value, in frames per second
    Static As Double t1
    Dim As Single tf = 1 / MyFps
    Dim As Double t3 = t1 + tf
    Dim As Double t2 = Timer
    #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
    If t2 < t1 Then t1 -= 24 * 60 * 60
    #endif
    Dim As Single dt = (tf - (t2 - t1)) * 1000
    Sleep Iif(dt > 1, dt, 1), 1
    t2 = Timer
    #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
    If t2 < t1 Then t1 -= 24 * 60 * 60
    #endif
    tf = 1 / (t2 - t1)
    t1 = t2
    Return tf
End Function

Screen 12
Dim As Ulong MyFPS = 10
Do
    Static As Ulongint l
    Static As Double dt
    Static As Ulong fps
    Screenlock
    Cls
    Color 11
    Print "Called procedure : regulateLite ( " & MyFPS & " )"
    Print
    Print Using "Measured FPS             : ###"; fps
    Print Using "Applied delay            : ###.### ms"; dt
    Print
    Print
    Print
    Color 14
    Print "<+>         : Increase FPS"
    Print "<->         : Decrease FPS"
    Print "<other key> : Quit"
    Line (0, 80)-(639, 96), 7, B
    Line (0, 80)-(l, 96), 7, BF
    Screenunlock
    l = (l + 1) Mod 640
    Dim As String s = Inkey
    Select Case s
    Case "+"
        If MyFPS < 100 Then MyFPS += 1
    Case "-"
        If MyFPS > 10 Then MyFPS -= 1
    Case Chr(27)
        Exit Do
    End Select
    dt = Timer
    fps = regulateLite(MyFPS)
    dt = (Timer - dt) * 1000
Loop
deltarho[1859]
Posts: 4158
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

fxm wrote:The first parameter of sleep is defined as LONG.
Yeah, good point.

I tried your regulateLite and used

Code: Select all

Dim As Ulong MyFPS = 60
in the example.

Something is wrong because I get 'Measured FPS' flickering between 26 and 32.

If I use _setTimer I get flickering around 58.

It made me smile because you have dropped the 'anchoring' and allowed 'Measured FPS' a 'degree of freedom' which I have been screaming for. I had noticed that with your original 'Lite' version, but did not mention it.

The CPU Load has vanished – surprise, surprise. :)

Added: It looks like you have no intention of allowing your 'flagship' regulate to have a degree of freedom because the 'anchoring' looks better. For some reason, you have not been as concerned with CPU Load as I have. Members who don't have powerful machines should steer clear of your 'flagship' and opt for 'Lite' or dodicat's regulate.
fxm
Moderator
Posts: 11930
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

deltarho[1859] wrote: Jun 05, 2023 7:41
fxm wrote:The first parameter of sleep is defined as LONG.
Yeah, good point.

I tried your regulateLite and used

Code: Select all

Dim As Ulong MyFPS = 60
in the example.

Something is wrong because I get 'Measured FPS' flickering between 26 and 32.

If I use _setTimer I get flickering around 58.

Interesting note.
Am I trying to understand this behavior ?
fxm
Moderator
Posts: 11930
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

I observe that 'Sleep td, 1' produces a wait time that has a scatter within an interval equal to the OS cycle period.
So the waiting time is accurate only when the required time is large compared to the OS cycle period.

So you are right: We have to integrate the smallest delay (so 'Sleep 1, 1') inside a loop testing 'Timer', as you already proposed:

Code: Select all

'Declare Function _setTimer Lib "winmm" Alias "timeBeginPeriod"(ByVal As Ulong = 1) As Long
'_setTimer()

Function regulateLite(ByVal MyFps As Ulong) As Ulong
    '' 'MyFps' : requested FPS value, in frames per second
    '' function return : applied FPS value, in frames per second
    Static As Double t1
    Dim As Single tf = 1 / MyFps
    Dim As Double t3 = t1 + tf
    Dim As Double t2
    Do
        t2 = Timer
        #if Not defined(__FB_WIN32__) And Not defined(__FB_LINUX__)
        If t2 < t1 Then t1 -= 24 * 60 * 60
        #endif
        Sleep 1, 1
    Loop Until Timer >= t3
    tf = 1 / (t2 - t1)
    t1 = t2
    Return tf
End Function

Screen 12
Dim As Ulong MyFPS = 60
Do
    Static As Ulongint l
    Static As Double dt
    Static As Ulong fps
    Screenlock
    Cls
    Color 11
    Print "Called procedure : regulateLite ( " & MyFPS & ")"
    Print
    Print Using "Measured FPS             : ###"; fps
    Print Using "Applied delay            : ###.### ms"; dt
    Print
    Print
    Print
    Color 14
    Print "<+>         : Increase FPS"
    Print "<->         : Decrease FPS"
    Print "<other key> : Quit"
    Line (0, 80)-(639, 96), 7, B
    Line (0, 80)-(l, 96), 7, BF
    Screenunlock
    l = (l + 1) Mod 640
    Dim As String s = Inkey
    Select Case s
    Case "+"
        If MyFPS < 1000 Then MyFPS += 1
    Case "-"
        If MyFPS > 10 Then MyFPS -= 1
    Case Chr(27)
        Exit Do
    End Select
    dt = Timer
    fps = regulateLite(MyFPS)
    dt = (Timer - dt) * 1000
Loop
Last edited by fxm on Jul 27, 2023 4:51, edited 2 times in total.
Reason: Note: This code is buggy, you have to put 't2 = Timer' after 'Sleep 1, 1' and not before.
deltarho[1859]
Posts: 4158
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

So you are right

Image

Added: With a request of 60, and no _setTimer, it looks like 'Measured FPS' is flickering around 64 which is OK, but it occasionally drops to 45. With _setTimer the flickering is closer to 60 and does not occasionally drop to 45.

So, not quite there yet.

I am not convinced that we can avoid _setTimer. Added: Of course, if we are not on Windows, we cannot use _setTimer anyway.
fxm
Moderator
Posts: 11930
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

My previous code is buggy, we have to put 't2 = Timer' after 'Sleep 1, 1' and not before.

The problem is that it does not work much better for me (in basic resolution) even with the simplest code as follows:

Code: Select all

'Declare Function _setTimer Lib "winmm" Alias "timeBeginPeriod"(ByVal As Ulong = 1) As Long
'_setTimer()

Function regulateLite(ByVal MyFps As Ulong) As Ulong
    '' 'MyFps' : requested FPS value, in frames per second
    '' function return : applied FPS value, in frames per second
    Static As Double t1
    Dim As Double t2 = Timer
    Dim As Double t3 = t1 + 1 / MyFps
    Do
        Sleep 1, 1
    Loop Until Timer >= t3
    t2 = Timer
    Dim As Ulong tf = 1 / (t2 - t1)
    t1 = t2
    Return tf
End Function

Screen 12
Dim As Ulong MyFPS = 60
Do
    Static As Ulongint l
    Static As Double dt
    Static As Ulong fps
    Screenlock
    Cls
    Color 11
    Print "Called procedure : regulateLite ( " & MyFPS & " )"
    Print
    Print Using "Measured FPS             : ###"; fps
    Print Using "Applied delay            : ###.### ms"; dt
    Print
    Print
    Print
    Color 14
    Print "<+>         : Increase FPS"
    Print "<->         : Decrease FPS"
    Print "<other key> : Quit"
    Line (0, 80)-(639, 96), 7, B
    Line (0, 80)-(l, 96), 7, BF
    Screenunlock
    l = (l + 1) Mod 640
    Dim As String s = Inkey
    Select Case s
    Case "+"
        If MyFPS < 1000 Then MyFPS += 1
    Case "-"
        If MyFPS > 10 Then MyFPS -= 1
    Case Chr(27)
        Exit Do
    End Select
    dt = Timer
    fps = regulateLite(MyFPS)
    dt = (Timer - dt) * 1000
Loop
It is like synchronizing the 'Sleep' keyword with its biggest error.
I foolishly thought 'Sleep 1, 1' would be more reliable than Sleep '17, 1'!
deltarho[1859]
Posts: 4158
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

I really have to go – I'm putting my other projects on hold. Sorry.

It is only a week ago that we were pushing 3000 views and here we are at over 5300 views.

That is remarkable, but it has only been you and me in that period, which is sad. It is more than sad, but I am not going to rant again.

Of course, it could well be that only you and me understand this subject, but I find that hard to believe.

Fortunately, for me, my latest Windows 10/11 only code is working a treat.
deltarho[1859]
Posts: 4158
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

I must be getting soft in my old age – I feel like I am abandoning a sinking ship – but I am not.

Just a couple of thoughts.

For Windows users, I think that you will need to revisit your 'flagship' and remove the 'anchoring'. Failing that, users should consider using dodicat's regulate.

For Linux users and your 'flagship' we could do with some feedback regarding a threshold of 2 * 10 and its CPU Load. If the CPU Load is not tolerable then, here too, users should consider using dodicat's regulate. I should point out that dodicat's method is not immune to a CPU Load. His 'Spring is in the air' has a CPU Load almost the same as your regulate on Windows.

This is not good news for you, but I cannot think of anything else.
dodicat
Posts: 7919
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: FreeBasic's Timer

Post by dodicat »

I think Quantum Physics strives to get a general formula for everything.
At the moment they have to put up with various bits and pieces.
I think fb graphics is not an exact science, so bits and pieces will do me.
By the way deltarho, this is my 13 th. input into this thread, and my swansong here again.

Code: Select all


Function regulateW(MyFps As Long,Byref fps As Long) As Double
      Dim As Double k=1/MyFps
      Static As Double timervalue
      Var c=timervalue
      Do While (Timer - TimerValue) <= k
      Loop 
      Var ans=(Timer-timervalue)
      timervalue=Timer
      fps=1/(timervalue-c)
      If Abs(Myfps-fps)>MyFps\2 Then fps=60
      Return ans*60
End Function

Function RegulateS(Byval MyFps As Long,Byref fps As Long,Byref gap As Double=0) As Double
      Static As Double timervalue,_lastsleeptime,t3,frames
      Var T=Timer
      frames+=1
      If (t-t3)>=1 Then t3=t:fps=frames:frames=0
      Var sleeptime=_lastsleeptime+((1/myfps)-T+timervalue)*1000
      If sleeptime<1 Then gap=sleeptime:sleeptime= 1
      _lastsleeptime=sleeptime
      timervalue=T
      Return sleeptime
End Function



screen 19
color ,6
dim as long fps,flag
dim as double delay
dim as long MyChoice
dim as double dx =2
dim as double p=50
do
    if p>200 and p<600 then mychoice=180 else mychoice=50
    screenlock
    cls
    p+=dx
    if p<50 or p>800-50 then dx=-dx
    line(200,0)-(200,600),3
    line(600,0)-(600,600),3
    circle(p,200),50,15,,,,f
    line(p,200-50)-(p,200+50),3
    locate 5,5
    print "FPS "; fps,iif(flag=1,"sleep","while")
    screenunlock
     If delay>1 Then '< about 60 fps
            Sleep  regulateS(MyChoice,fps,delay) ,1
            flag=1
      Else
            delay=regulateW(MyChoice,fps)
            flag=2
      End If
      
    
    loop until len(inkey)
 
deltarho[1859]
Posts: 4158
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

@dodicat

My apologies – you have posted code twice in the last week – including your last one above.

Just for the record, your last post got:

Code: Select all

    Press ENTER to stop monitoring PID #3364
         CPU Load:  0.006
         Max Load:  12.50
         95% Conf Interval:  3.58 ± 8.26
         Session Time:  60.0 seconds
The Max Load is a bit naughty when the fps increases in the centre part, but overall in the session time tested it shouldn't be a concern.

The 3.58 - 8.26 should, of course, be read as zero. The statistical analysis doesn't consider that.

With a session time of 120 seconds I get 95% Conf Interval: 3.67 ± 8.27.
deltarho[1859]
Posts: 4158
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

Come to think of it, I don't understand why I am doing a two-sided test when I should be doing a one-sided test.

With a session time of 120 seconds, I am now getting:

Code: Select all

    Press ENTER to stop monitoring PID #12208
         CPU Load:  0.390
         Max Load:  12.70
         95% Conf Interval:  3.67  to  7.72
         Session Time:  120.0 seconds
That's better. :)

Outside the centre part, the load is negligible.

This is your 'Spring is in the air'.

Code: Select all

    Press ENTER to stop monitoring PID #2200
         CPU Load:  2.54
         Max Load:  6.64
         95% Conf Interval:  3.80  to  4.73
         Session Time:  120.0 seconds
The 'CPU Load' is the load at the end of the session time, which, of course, varies during the session time.
fxm
Moderator
Posts: 11930
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

For the moment, I hardly see a solution to this problem without skipping some frames thanks to the 'regulate()' procedure.
For example I tried for FPS > 30 to skip 2 frames out of 3 (2 null wait times followed by the wait time to regulate the all corresponding to FPS/3).
This improves regulation, but for a requested FPS = 30, this induces a visual FPS = 10 which is a bit limit.
fxm
Moderator
Posts: 11930
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

fxm wrote: Jun 05, 2023 18:02 For the moment, I hardly see a solution to this problem without skipping some frames thanks to the 'regulate()' procedure.
For example I tried for FPS > 30 to skip 2 frames out of 3 (2 null wait times followed by the wait time to regulate the all corresponding to FPS/3).
This improves regulation, but for a requested FPS = 30, this induces a visual FPS = 10 which is a bit limit.

Simplistic and rough example:

Code: Select all

'Declare Function _setTimer Lib "winmm" Alias "timeBeginPeriod"(ByVal As Ulong = 1) As Long
'_setTimer()

Function regulateLite(ByVal MyFps As Ulong) As Ulong
    '' 'MyFps' : requested FPS value, in frames per second
    '' function return : applied FPS value, in frames per second
    Static As Double tos
    If tos = 0 Then
        Dim As Double t = Timer
        For I As Integer = 1 To 10
            Sleep 1, 1
        Next I
        tos = (Timer - t) / 10 * 1000
    End If
    Static As Long N = 1
    Static As Double t1
    Static As Double t0
    Dim As Single tf = 1 / MyFps
    Dim As Double t2 = Timer
    Dim As Single dt = (tf - (t2 - t1)) * 1000
    If dt < 2 * tos Then
        If N = 3 Then
            dt = (N * tf - (t2 - t1)) * 1000
            dt -= tos / 4
            Sleep Iif(dt > 1 Or dt = 0, dt, 1), 1
            t2 = Timer
            t0 = 1 / (t2 - t1) * N
            t1 = t2
            N = 0
        Else
            N += 1
        End If
    Else
        dt -= tos / 4
        Sleep Iif(dt > 1 Or dt = 0, dt, 1), 1
        t2 = Timer
        t0 = 1 / (t2 - t1)
        t1 = t2
    End If
    Return t0
End Function

Screen 12
Dim As Ulong MyFPS = 60
Do
    Static As Ulongint l
    Static As Double dt
    Static As Ulong fps
    Screenlock
    Cls
    Color 11
    Print "Called procedure : regulateLite ( " & MyFPS & " )"
    Print
    Print Using "Measured FPS             : ###"; fps
    Print Using "Applied delay            : ###.### ms"; dt
    Print
    Print
    Print
    Color 14
    Print "<+>         : Increase FPS"
    Print "<->         : Decrease FPS"
    Print "<other key> : Quit"
    Line (0, 80)-(639, 96), 7, B
    Line (0, 80)-(l, 96), 7, BF
    Screenunlock
    l = (l + 1) Mod 640
    Dim As String s = Inkey
    Select Case s
    Case "+"
        If MyFPS < 100 Then MyFPS += 1
    Case "-"
        If MyFPS > 10 Then MyFPS -= 1
    Case Chr(27)
        Exit Do
    End Select
    dt = Timer
    fps = regulateLite(MyFPS)
    dt = (Timer - dt) * 1000
Loop
When 'Applied delay' displays 0 ms, only 1 frame out of 3 is visualized.
deltarho[1859]
Posts: 4158
Joined: Jan 02, 2017 0:34
Location: UK
Contact:

Re: FreeBasic's Timer

Post by deltarho[1859] »

The two-sided test was correct but the one-sided test was wrong.

I dropped out of Statistics in my final year of maths and opted for Numerical Analysis. In fact, I doubt that I looked at a one-sided test. I was nearly there. I had to go onto the internet to get up to speed. :)

This is a one-sided test for dodicat's variable fps code using the correct method.

Code: Select all

    Press ENTER to stop monitoring PID #13412
         CPU Load:  0.200
         Max Load:  12.90
         95% Conf Interval: <= 7.06
         Session Time:  120.0 seconds
The confidence interval is a little high, but not a worry. It is the centre part which ramps up the fps which puts the pressure on.

'Spring in the air'

Code: Select all

    Press ENTER to stop monitoring PID #12344
         CPU Load:  4.493
         Max Load:  10.93
         95% Conf Interval: <= 5.09
         Session Time:  120.0 seconds
That spring is doing a lot of work, but again not a worry.

I am out of here now – hopefully :) .
fxm
Moderator
Posts: 11930
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: FreeBasic's Timer

Post by fxm »

The principle of 'image skipping' is not to remove certain images but rather to remove all delays between these images ('regulateLite()' returns immediately) so that the persistence of these images is low compared to that which is followed by a real delay.
The smaller the image tracing time, the less these skipped images are visible.

The temporal principle for skipping 'n - 1' images out of 'n' images is to generate only a single delay after the last image is visualized, with a value such that the total period of the sequence (of 'n' images) is equal to 'n' times the period corresponding to the required FPS.
'n = 1' => no skipped image
'n = 2' => 1 image skipped out of 2
'n = 3' => 2 images skipped out of 3
'n = 4' => 3 images skipped out of 4
..........
..........


The previous 'regulateLite()' procedure is now improved with progressive image skipping depending on requested FPS and measured resolution (duration of 'Sleep 1, 1').

For Windows in basic resolution, transition values for FPS are about:
0 -> 30 : 0 image skipped
30 -> 45 : 1 image skipped out of 2
45 -> 60 : 2 images skipped out of 3
60 -> 75 : 3 images skipped out of 4
75 -> 90 : 4 images skipped out of 5
90 -> 105 : 5 images skipped out of 6
105 -> 120 : 6 images skipped out of 7
..........
..........
For any required FPS > 30, the visible number of images per second is always >= 15
(assumptions : minimum waiting time = 16 µs, minimum accurate waiting time = 32 µs)

For Windows in high resolution, transition values for FPS are about:
0 -> 240 : 0 image skipped
240 -> 360 : 1 image skipped out of 2
360 -> 480 : 2 images skipped out of 3
480 -> 600 : 3 images skipped out of 4
..........
..........
For any required FPS > 240, the visible number of images per second is always >= 120
(assumptions : minimum waiting time = 2 µs, minimum accurate waiting time = 4 µs)

For Linux, transition values for FPS are about:
0 -> 48 : 0 image skipped
48 -> 72 : 1 image skipped out of 2
72 -> 96 : 2 images skipped out of 3
96 -> 120 : 3 images skipped out of 4
120 -> 144 : 4 images skipped out of 5
144 -> 168 : 5 images skipped out of 6
168 -> 192 : 6 images skipped out of 7
..........
..........
For any required FPS > 48, the visible number of images per second is always >= 24
(assumptions : minimum waiting time = 10 µs, minimum accurate waiting time = 20 µs)

Usage example (first two lines to inhibit/activate high resolution in Windows):

Code: Select all

'Declare Function _setTimer Lib "winmm" Alias "timeBeginPeriod"(ByVal As Ulong = 1) As Long
'_setTimer()

Function regulateLite(ByVal MyFps As Ulong) As Ulong
    '' 'MyFps' : requested FPS value, in frames per second
    '' function return : applied FPS value, in frames per second
    Static As Double tos
    Static As Double bias
    If tos = 0 Then
        Dim As Double t = Timer
        For I As Integer = 1 To 10
            Sleep 1, 1
        Next I
        tos = (Timer - t) / 10 * 1000
        bias = 0.549 * tos - 0.78
    End If
    Static As Long N = 1
    Dim As Long k = Int(MyFps / 240 * tos)
    Dim As Single tf = 1 / MyFps
    Static As Double t0
    Static As Double t1
    Dim As Double t2 = Timer
    If N >= K Then
        Dim As Double dt = (N * tf - (t2 - t1)) * 1000 - bias
        Sleep Iif(dt > 0.5, dt, 1), 1
        t2 = Timer
        t0 = N / (t2 - t1)
        t1 = t2
        N = 1
    Else
        N += 1
    End If
    Return t0
End Function

Screen 12
Dim As Ulong MyFPS = 60
Do
    Static As Ulongint l
    Static As Double dt
    Static As Ulong fps
    Screenlock
    Cls
    Color 11
    Print "Called procedure : regulateLite ( " & MyFPS & " )"
    Print
    Print Using "Measured FPS (skipped images included) : ###"; fps
    Print Using "Applied delay (when no skipped image)  : ###.### ms"; dt
    Print
    Print
    Print
    Color 14
    Print "<+>         : Increase FPS"
    Print "<->         : Decrease FPS"
    Print "<other key> : Quit"
    Line (0, 80)-(639, 96), 7, B
    Line (0, 80)-(l, 96), 7, BF
    Screenunlock
    l = (l + 1) Mod 640
    Dim As String s = Inkey
    Select Case s
    Case "+"
        If MyFPS < 500 Then MyFPS += 1
    Case "-"
        If MyFPS > 1 Then MyFPS -= 1
    Case Chr(27)
        Exit Do
    End Select
    dt = Timer
    fps = regulateLite(MyFPS)
    dt = (Timer - dt) * 1000
Loop
When 'Delay applied' is around 0, it means image skipping is active.
Last edited by fxm on Jun 06, 2023 19:06, edited 2 times in total.
Post Reply