Page 1 of 1

A need to know a single algorithm to know FPS

Posted: Sat Oct 22, 2022 1:34 pm
by Juan Carlos
I am using this code:

Code: Select all


SetInterval(25, p_Velociclos, 40)

Function p_Velociclos()
  Tiempo=GetTimer(1)
  If Tiempo<=0 Then Tiempo=1
  Formula1=Div(1, Tiempo)
  Formula=Mul(Formula1, 1000)
  Velo=Round(Formula)

  SetFont(#SANS, 20)
  SetFontColor(#WHITE)
  SetFontStyle(#ANTIALIAS)  
  TextOut(380, 440, Velo.." FPS")
  ResetTimer(1)
EndFunction
But, I don't know if this code is good to know the FPS for a game or program, or if it cans improvable, because sometimes with enough visual effects the demo goes slowly.
Thanks.

Re: A need to know a single algorithm to know FPS

Posted: Wed Oct 26, 2022 9:31 pm
by jPV
I haven't used an FPS counter in real world examples yet, but I think I'd do it somehow like this:

Code: Select all

Function p_MyGameDrawFunction()
    Cls
    Box(Rnd(200), Rnd(200), Rnd(90) + 10, Rnd(90) + 10, #WHITE)
    TextOut(#RIGHT, #BOTTOM, g_fps .. " fps")
    ; Wait(Rnd(5))                                    ; Random wait to test if re-draw would be too slow to get full fps.
    g_fps_frames = g_fps_frames + 1                   ; Update the frame count when you have drawn a frame on the screen.
EndFunction

Function p_FPS()
    Local time_elapsed = GetTimer(g_fps_timer)        ; How long ago we calculated the fps value last time?
    g_fps = g_fps_frames / time_elapsed * 1000        ; How many frames have been drawn since the last time? Divide it by time.
    g_fps = Round(g_fps)                              ; Round the fps value to integers.
    DebugPrint(g_fps)
    g_fps_frames = 0                                  ; Reset the frame counter variable.
    ResetTimer(g_fps_timer)                           ; Reset the timer.
EndFunction

Global g_fps = 0                                      ; A global variable to store the FPS value, let's just have it here as a reminder.
Global g_fps_frames = 0                               ; Initialize a global frame counter variable.
Global g_fps_timer = StartTimer(Nil)                  ; Start a timer and store its ID to a global variable. This way we don't accidently create another timer with the same ID.
Global g_fps_interval = SetInterval(Nil, p_FPS, 2000) ; Calculate the FPS value evey 2 seconds. Depends of the game type how often you want to update to get preciser values.

SetInterval(1, p_MyGameDrawFunction, 40)              ; Update a game screen 25 times per second (40 ms), for example.

Repeat
    WaitEvent()
Forever
So basically you just count how many frames the program has drawn and calculate framerate after certain time has elapsed. I think this doesn't make that much overhead like other options either, because actual FPS calculations aren't being made all the time.

Another option would be to measure time spent on drawing one frame and make an estimate of FPS based on that... it would give more immediate results for rapidly changing framerate, but I think it would be generally inaccurate.. and numbers would change too quickly, so you'd need to have some kind of calculation for the short time average. It also depend of your program structure if it'd work correctly at all.
I don't think this would be that good idea, but I mean something like this:

Code: Select all

Function p_MyGameDrawFunction()
    Local fps_timer = StartTimer(Nil)                  ; Measure the time to draw one frame.
    Wait(Rnd(5)*2)                                     ; Simulates a situation where the drawing time varies a lot.
    VWait()
    Cls
    Box(Rnd(200), Rnd(200), Rnd(90) + 10, Rnd(90) + 10, #WHITE)
    Local fps_current = 1 / GetTimer(fps_timer) * 1000 ; Calculate the current FPS value according the time of one frame.
    g_fps = g_fps * 0.9 + fps_current * 0.1            ; Balance the FPS value with previous values to avoid too crazy jumping.
    TextOut(#RIGHT, #BOTTOM, "Current fps: " .. Round(fps_current) .. "\nAverage fps: "  .. Round(g_fps))
    StopTimer(fps_timer)                               ; Timer isn't needed anymore.
EndFunction

Global g_fps = 0                                       ; A global variable to store the average FPS value, let's just have it here as a reminder.

Repeat
    p_MyGameDrawFunction()
Forever