Timing & Game Loop Design
TIMER resets at midnight; handle the wrap for long-running programs:
26.1 Measuring time
TIMER resets at midnight; handle the wrap for long-running programs:
start = TIMER ' seconds since midnight (SINGLE)
FOR i = 1 TO 10000000: NEXT
PRINT "Elapsed:"; TIMER - start; "seconds"
t# = TIMER(.001) ' QB64: request millisecond accuracy
PRINT DATE$, TIME$ ' "mm-dd-yyyy", "hh:mm:ss"elapsed = TIMER - start
IF elapsed < 0 THEN elapsed = elapsed + 86400 ' crossed midnight26.2 Waiting
wait for a keypress wait n seconds or until a key is pressed wait s seconds (fractions allowed, e.g., 0.25), not interrupted by keys (QB64) cap a loop's frequency, sleeping the remainder of each frame (QB64) ON TIMER(n) GOSUB label + TIMER ON call a handler every n seconds (event trapping)
Old programs used empty FOR loops for delays (FOR d = 1 TO 5000: NEXT) — this runs at different speeds on different computers. Never do it in new code.
26.3 The game loop
Every real-time program follows the same pattern:
Two ways to keep speed consistent:
Fixed frame rate with _LIMIT 60 and per-frame movement (x = x + 3). Simple; slows down if the computer can't keep up.
Delta time: measure the seconds since the last frame and scale movement (x = x + speed * dt). Consistent speed at any frame rate.
Initialize
DO
Process input (keyboard, mouse, gamepad)
Update (move objects, physics, AI, collisions, scoring)
Render (clear, draw world, draw HUD, _DISPLAY)
Regulate timing (_LIMIT or delta time)
LOOP UNTIL quitting
Shutdown' Delta-time movement
prevT# = TIMER(.001)
DO
nowT# = TIMER(.001)
dt# = nowT# - prevT#: prevT# = nowT#
IF dt# < 0 THEN dt# = dt# + 86400 ' midnight wrap
IF dt# > 0.1 THEN dt# = 0.1 ' clamp after pauses (window dragging, breakpoints)
x = x + 200 * dt# ' 200 pixels per second
' ... render ...
_LIMIT 240
LOOP26.4 Game states with SELECT CASE
FreeBASIC: Timer (double precision), Sleep ms (milliseconds!), ScreenSync waits for vertical retrace, and Sleep 1, 1 yields CPU time in loops. VB.NET: Stopwatch for precise timing, System.Windows.Forms.Timer for UI events, Await Task.Delay(ms) for asynchronous waits; game loops typically run in Application.Idle or a game framework.
CONST STATE_TITLE = 1, STATE_PLAY = 2, STATE_OVER = 3
state = STATE_TITLE
DO
SELECT CASE state
CASE STATE_TITLE
' draw title; if Enter pressed then reset the game and state = STATE_PLAY
CASE STATE_PLAY
' input, update, render; if lives = 0 then state = STATE_OVER
CASE STATE_OVER
' show score; if Enter pressed then state = STATE_TITLE
END SELECT
_DISPLAY
_LIMIT 60
LOOP UNTIL quitRequested