I figured out how to make DBPro's perftimer() function cpu independent, so I'm posting it here with my timer based movement module.
Functions
Tbm_init(fps) - initialize the timer based movement system (call with sync rate you would normally use)
Tbm_update() - put this at the top of your main loop, it updates the timer system
Tbm_cut() - If you need to pause the game call this function afterwards to ignore all the time passed since the last tbm_update.
Variables
Tbm.freq - This is the frequency of the precision timer.
Tbm.targetfps - The sync rate you called tbm_init() with
Tbm.realfps - The real sync rate the program is running at
Tbm.boot - The perftimer() value when tbm_init() was called
Tbm.pause - The number of perftimer() cycles spent on pause
Tbm.factor - The value you need to multiply all your movement speeds by to make your program timer based
Tbm.time - The number of perftimer() cycles since you called tbm_init() minus the time spent on pause
Tbm.now - Same as tbm.time, except in milliseconds so it's cpu independent.
global Tbm as Tbm
type Tbm
freq as dword
targetfps as double float
realfps as double float
boot as dword
pause as dword
factor as double float
time as dword
now as double float
endtype
function Tbm_init(fps as float)
local freq as dword
`get performance timer frequency
freq = make memory(4)
call dll Kernel32, "QueryPerformanceFrequency", freq
Tbm.freq = *freq
Tbm.boot = perftimer()
Tbm.targetfps = fps
endfunction
`discards all time passed since last update
function Tbm_cut()
local perftime as dword
perftime = perftimer()
Tbm.pause = perftime - Tbm.boot - Tbm.time
Tbm.time = perftime - Tbm.boot - Tbm.pause - Tbm.freq/Tbm.realfps
Tbm.now = (Tbm.time*1000.0)/(Tbm.freq*1.0)
endfunction
`updates timer system
function Tbm_update()
local now as dword
local took as dword
local factor as float
now = perftimer() - Tbm.boot - Tbm.pause
took = now - Tbm.time
Tbm.time = now
Tbm.now = (Tbm.time*1000.0)/(Tbm.freq*1.0)
Tbm.realfps = Tbm.freq/took
Tbm.factor = Tbm.targetfps/Tbm.realfps
endfunction
Note: You must load Kernel32.dll and define a constant or variable called Kernel32 and set it to the dll number for this to work
Also note, Tbm.pause and Tbm.time sometimes get set off a couple hundred milliseconds when pausing/unpausing. I'm working on it but you probably won't notice anything.
Example:
global Kernel32 as dword = 1
global delay as integer = 50
global speed as float = 1.0
local nextcheck as dword
global pausekey as boolean
global lastpausekey as boolean
load dll "Kernel32.dll", Kernel32
sync on
sync rate 0
`start tbm system with a target of 60 frames per second
Tbm_init(60)
`now code your game as you would at 60 fps,
`but be sure to multiply ALL movement speeds
`by Tbm.factor
make object cube 1, 1
do
`calculate time paseed since last update to get movement factor
Tbm_update()
pausekey = keystate(25)
if pausekey && (lastpausekey = 0) then Pause()
lastpausekey = pausekey
`don't check more often than supposed to
if Tbm.now > nextcheck
`increase or decrease delay
`cube still spins at same speed
`when you do this
if upkey() then inc delay, 5
if downkey() then dec delay, 5
if delay < 0 then delay = 0
wait delay
`increase or decrease cube spin speed
if leftkey() then inc speed, 0.5
if rightkey() then dec speed, 0.5
nextcheck = Tbm.now + 17
endif
yrotate object 1, object angle y(1) + (speed * Tbm.factor)
Texts()
sync
loop
function Texts()
text 0, 0, "Target FPS: " + str$(Tbm.targetfps)
text 0, 10, "DBPro FPS: " + str$(screen fps())
text 0, 30, "Real FPS: " + str$(Tbm.realfps)
text 0, 40, "Movement factor: " + str$(Tbm.factor)
text 0, 60, "Use up/down keys to increase/decrease delay"
text 0, 70, "Delay: " + str$(delay) + "ms"
text 0, 90, "Use right/left keys to change cube speed"
text 0, 100, "Speed: " + str$(speed) + " degrees"
text 0, 120, "Press P to pause"
text 0, 150, "Time cube has spent spinning: " + str$(int(Tbm.now)) + "ms"
endfunction
function Pause()
repeat
center text screen width()/2.0, screen height()/2.0, "Paused"
Texts()
lastpausekey = pausekey
pausekey = keystate(25)
sync
until pausekey && (lastpausekey = 0)
Tbm_cut()
endfunction
global Tbm as Tbm
type Tbm
freq as dword
targetfps as double float
realfps as double float
boot as dword
pause as dword
factor as double float
time as dword
now as double float
endtype
function Tbm_init(fps as float)
local freq as dword
`get performance timer frequency
freq = make memory(4)
call dll Kernel32, "QueryPerformanceFrequency", freq
Tbm.freq = *freq
Tbm.boot = perftimer()
Tbm.targetfps = fps
endfunction
`discards all time passed since last update
function Tbm_cut()
local perftime as dword
perftime = perftimer()
Tbm.pause = perftime - Tbm.boot - Tbm.time
Tbm.time = perftime - Tbm.boot - Tbm.pause - Tbm.freq/Tbm.realfps
Tbm.now = (Tbm.time*1000.0)/(Tbm.freq*1.0)
endfunction
`updates timer system
function Tbm_update()
local now as dword
local took as dword
local factor as float
now = perftimer() - Tbm.boot - Tbm.pause
took = now - Tbm.time
Tbm.time = now
Tbm.now = (Tbm.time*1000.0)/(Tbm.freq*1.0)
Tbm.realfps = Tbm.freq/took
Tbm.factor = Tbm.targetfps/Tbm.realfps
endfunction
So hopefully using perftimer() makes the calculations more accurate, what do you guys think? (Let me know if it doesn't work for some reason)