Version 2.0!
Features
Tutorials
Files
Glossary
Projects
Contact
Links
Message Board
Extras
LuckyCam
Old News
Sign Guestbook
View Guestbook
VB Horoscope
VB Photo Album
.
ATTENTION READERS! Lucky's VB Gaming Site is no longer active. For updated game programming information and tutorials, please visit The Game Programming Wiki!

Time-Based Modeling

EAT.. MY.. JUSTICE! Anyone ever watch "The Tick"? No? :(

Anyway! I do have a reason for talking about "justice".. do you think it's fair that someone with a Pentium-133 should get the same frame rates in a game as someone with a PIII-800? I mean, c'mon, the person with the PIII deserves a little extra somethin' for all that money they've spent! Putting a frame cap on your game is NOT the only method available to you. Let the computer crank out as many FPS as it can by using "Time-Based Modeling"!

The key to this method is determining the time elapsed since the last frame was displayed. You then use this value in all of your game calculations, effectively giving weight according to the frame rate attained. Also, you'll have to describe your game's "speed" values in units per second (ie. pixels per second) rather than units per frame.

Lets give a simple example to make this perfectly clear. Imagine Mario is running to the right at 20 pixels/second. If our elapsed time since the last frame was 0.05 seconds (50 milliseconds), then Mario will have travelled 1 pixel (20pixels/second * 0.05seconds). If our elapsed time was 200 milliseconds (a REALLY slow computer) then Mario will have travelled 4 pixels. You see, the number of pixels PER FRAME will vary, but the total number of pixels PER SECOND will always remain constant, no matter how slow the computer!

Dim mlngTimer as Long
Dim mlngElapsed as Long
Dim mlngFrameTimer as Long
Dim mintFPSCounter as Integer
Dim mintFPS as Integer

Private Sub Timer()

    mlngElapsed = GetTickCount() - mlngTimer
    mlngTimer = GetTickCount()
    If GetTickCount() - mlngFrameTimer >= 1000 Then
        mlngFrameTimer = GetTickCount()
        mintFPS = mintFPSCounter
        mintFPSCounter = 0
    Else
        mintFPSCounter = mintFPSCounter + 1
    End If

End Sub

Call this little subroutine from within a "Do-While" loop (your main render loop) and it'll place the elapsed time in the variable mlngElapsed. It'll also fill the variable mintFPS with the number of frames displayed last second.

After calling this Timer subroutine, perform your physics calculations using the value of mlngElapsed. Using our Mario example:

    msngMarioX = msngMarioX + mlngElapsed * msngMarioSpeed

So, if Mario was at pixel zero, and 200 milliseconds elapsed while he was moving with a speed of 0.02 pixels/millisecond we'd get:

    msngMarioX = (0) + (200) * (0.02)

Which equals 4 pixels. Easy-shmeasy. Using this method your game will look as good as it can on any given computer; no CPU cycles are wasted! Also, if you're considering a network game I'd highly recommend this architecture. The inescapable latency of network games can easily be accommodated since delay handling is already built into the physics routines!

Download my sample source code if you're still a little foggy on this whole concept.