# VBForums UtilityBank > UtilityBank - Tutorials >  Tutorial - Accurate Game Loop

## cyborg

This tutorial will show how to make an accurate game loop
using QueryPerformanceCounter API.


The first thing we need to do is to declare the API functions:

VB Code:
Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
This counter can differ from machine to machine, that's why we
have to get the frequency of it using QueryPerformanceFrequency.


Now we need a variable telling if the loop is on or off.
We also need to know what to lock the FPS at.

VB Code:
Dim Running As Boolean
Cost FPS As Double = 61.3
I've set the FPS to 61.3 just so we can see the accuracy.


Now head on to the loop.
We will nead a few variables to keep track on time and interval in this loop:

VB Code:
Dim cTimer As Currency
Dim cTimer2 As Currency
Dim Freq As Currency
Dim Interval As Double
cTimer is used to get the time when running the game code.
cTimer2 is used to get the time just before the game code.
Freq is used to store the frequency value from the API.
Interval will store the time to wait for next tick based on the FPS and frequency.

The loop will start off by getting the frequency and calculating the interval.
Since this will be constant during the looping, we only need to do this once.

VB Code:
QueryPerformanceFrequency Freq
Interval = Freq / FPS
Now the loop will start.
It will start by checking if the Running boolean is set to True.
Then it will check if it's time to enter the game code part.
Last it will handle windows messages (DoEvents), or else the program will lock.

VB Code:
While Running
    QueryPerformanceCounter cTimer2 'get current time
    If cTimer2 >= cTimer + Interval Then 'compare current time with previous time and see if enough time has passed
        Me.Caption = "FPS: " & Format(Round(Freq / (cTimer2 - cTimer), 1), "0.0") 'display fps on screen
        QueryPerformanceCounter cTimer 'get current time
        
        'Game code goes here.
    End If
    DoEvents
Wend
That's it!
To start the loop set Running to True and call the loop sub.
To end it, set Running to False.


Here's a finished example:


VB Code:
Option Explicit
 Private Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As Currency) As Long
Private Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As Currency) As Long
 Dim Running As Boolean                                                                  'To know if the game is running
Const FPS As Double = 61.3                                                              'Frames Per Second
 Private Sub Form_Load()
    Me.Show                                                                             'Display main window
    Running = True
    GameLoop                                                                            'Start the loop
End Sub
 Private Sub GameLoop()
    Dim cTimer As Currency                                                              'Time of last tick
    Dim cTimer2 As Currency                                                             'Current time
    Dim Freq As Currency                                                                'Frequency of Counter
    Dim Interval As Double                                                              'Time of each frame
    
    QueryPerformanceFrequency Freq                                                      'Get Frequency
    Interval = Freq / FPS                                                               'Calculate interval based on FPS and Frequency
    
    While Running                                                                       'Start loop
        QueryPerformanceCounter cTimer2                                                 'Get current time
        If cTimer2 >= cTimer + Interval Then                                            'Check if it's time to run code
            Me.Caption = "FPS: " & Format(Round(Freq / (cTimer2 - cTimer), 1), "0.0")   'Display FPS on screen
            QueryPerformanceCounter cTimer                                              'Get time for later use
            
            'Enter code here
        End If
        DoEvents
    Wend                                                                                'End loop
End Sub
 Private Sub Form_Unload(Cancel As Integer)
    Running = False                                                                     'Exit loop
End Sub

----------


## diocassius

Wow this is old. But anyway...

I get an error when I try to run the code - "Must have start up form or Sub Main()" Followed by another "Out of Memory".

Any help would be appreciated, I'm new to VB and programming.

EDIT: Nevermind I got it. >.>

----------

