It’s GameTime

Naturally, my first OpenGL game was a 3-D version of Pong. I was using an old library called GLUT which included functions for generating primitives like spheres. You could generate them based on the number of lines of latitude and longitude, AKA “UV Spheres”.

More polygons would make the game run slower, so I cranked that number up until the framerate stabilized. This is a highly sophisticated programming technique often referred to as a “cheap hack”. Sure enough, almost 18 years later, it still runs just fine. Which goes to show you that just because it’s a dumb idea doesn’t mean it doesn’t work. But then again just because it works doesn’t mean it’s not stupid.

Anyway, it’s time to get in step with the times, using a high-resolution Time Step. The GameTime Class pre-calculates hundredths and thousandths, as well as several multples of 10. I also use a JEOZ.Average Class to track the FPS.

Public Class GameTime
    Public Step001, Step01, [Step], Step10, Step100, Step1000 As Single
    Public FrameRate, Frame, RealFrame, Age As Single
    Public FPS as New Average(30, 4)
    Public Paused As Boolean, PauseTime As Single

    '// System Functions for High Resolution Millisecond Timestamps
    Private Declare Function QueryPerformanceCounter _
        Lib "Kernel32" (ByRef X As Long) As Short
    Private Declare Function QueryPerformanceFrequency _
        Lib "Kernel32" (ByRef X As Long) As Short
    '// Variables for Storing Performance Data
    Private PerformanceFrequency, PerformanceCounter, LastQPC As Long

    '// StartTime automatically set when the GameTime class is Instantiated:
    Public StartTime As DateTime = Now()
    '// Used for setting TickTock based on StartTime:
    Private SecondsLapsed, SecondsLapsedLast As Integer
    '// TickTock will be True on any GameFrame when a second has elapsed
    Public TickTock As Boolean

In Visual Basic, the word Step is a Reserved Keyword that’s usually only used when doing a For Loop, as in For X = 0 To 100 Step 10. Putting [Square Brackets] around Keywords allows you to define them as Fields. But outside of the Class, you can refer to GameTime.Step without having to use brackets.

    Public Sub CheckGameTime()
        QueryPerformanceFrequency(PerformanceFrequency)
        QueryPerformanceCounter(PerformanceCounter)
        '// If LastQPC = 0 Then LastQPC = PerformanceCounter
        LastQPC = If(LastQPC = 0, PerformanceCounter, LastQPC)

        [Step] = ((PerformanceCounter - LastQPC) / PerformanceFrequency) * 0.1
       
        [Step] = Clamp([Step], 0.0166, 0.25)
        Step001 = [Step] * 0.01
        Step01 = [Step] * 0.1
        Step10 = [Step] * 10
        Step100 = [Step] * 100
        Step1000 = [Step] * 1000

        Age += Step10
        TimeAverage.Add([Step])
       
        '// Add the current Step to the FPS Average Object
        FPS.Add(1 / If(Step10 > 0, Step10, 0.01))
        FrameRate = FPS.Average
        '// Track Seconds Elapsed since GameTime was created
        '// And TickTock = True only on each Frame when a second has passed
        '// These are stored as Integers and rounded automatically
        SecondsLapsed = (Now() - StartTime).TotalSeconds
        TickTock = (SecondsLapsed > SecondsLapsedLast)
        SecondsLapsedLast = SecondsLapsed

        Frame += If(Paused, 0.1, 1)
        RealFrame += 1
        LastQPC = PerformanceCounter
    End Sub

    Public Sub ResetTickTock(Optional TickTockNow As Boolean = True)
        StartTime = Now()
        SecondsLapsedLast = 0
        TickTock = TickTockNow
    End Sub
End Class

Leave a Reply