Sure. So basically, timer based movement is where you use the actual elapse time, rather than the number of game cycles, to decide how fast your characters should move. Consider the following code.
SetWindowSize( 1024, 800, 0 )
SetVirtualResolution( 1024, 800)
spr = CreateSprite(0)
SetSpriteSize(spr, 10, 10)
SetSpritePosition(spr, 20, 20)
do
SetSpritePosition(spr, GetSpriteX(spr) + 1, GetSpriteY(spr))
Sync()
loop
The white square will move across the screen from left to right, but the speed of that movement is determined by the speed of execution. It will move 1 pixel to the right per cycle. That is, per time that SetSpritePosition(spr, GetSpriteX(spr) + 1, GetSpriteY(spr)) runs. This means that different processors will move the square at different speeds, depending on their execution speed. Equally if we modify the code as follows
SetWindowSize( 1024, 800, 0 )
SetVirtualResolution( 1024, 800)
spr = CreateSprite(0)
SetSpriteSize(spr, 10, 10)
SetSpritePosition(spr, 20, 20)
do
SetSpritePosition(spr, GetSpriteX(spr) + 1, GetSpriteY(spr))
Sleep(100) // slow down the loop
Sync()
loop
the square moves slower, simply because it takes more time to complete a loop and so SetSpritePosition(spr, GetSpriteX(spr) + 1, GetSpriteY(spr)) runs less frequently.
The solution to this problem is timer based movement. The starting point for timer based movement is to know how far you want something to move over a given time. So say I want my white square to move by 100 pixels/second, I would write the following code.
SetWindowSize( 1024, 800, 0 )
SetVirtualResolution( 1024, 800)
spr = CreateSprite(0)
SetSpriteSize(spr, 10, 10)
SetSpritePosition(spr, 20, 20)
lastFrameTime# = Timer()
do
currentFrameTime# = Timer()
deltaTime# = currentFrameTime# - lastFrameTime#
lastFrameTime# = currentFrameTime#
SetSpritePosition(spr, GetSpriteX(spr) + (100.0 * deltaTime#), GetSpriteY(spr))
Sync()
loop
The first thing I do in my loop is to calculate the delta time. This is the time that has elapsed since I last updated the position of the sprite. Given that I know that the deltaTime# value is in seconds, and that I want to move by 100 pixels a second, I simply multiple 100.0 by deltaTime# to work out how far I should have moved in the given timestep. The interesting thing about this is that if we re-insert our sleep like so
SetWindowSize( 1024, 800, 0 )
SetVirtualResolution( 1024, 800)
spr = CreateSprite(0)
SetSpriteSize(spr, 10, 10)
SetSpritePosition(spr, 20, 20)
lastFrameTime# = Timer()
do
currentFrameTime# = Timer()
deltaTime# = currentFrameTime# - lastFrameTime#
lastFrameTime# = currentFrameTime#
SetSpritePosition(spr, GetSpriteX(spr) + (100.0 * deltaTime#), GetSpriteY(spr))
Sleep(100)
Sync()
loop
We will notice that the movement becomes visibly jumpy because of the huge delay between updates, but the actual speed of movement remains the same.
I hope that helps. Do let me know if you have any questions about any of this.