Issue #4 ~ January 16th, 2012
"A FreeBASIC, QBasic and QB64 games magazine"
In This Issue
- Lachie Dazdarian (Editor)
- Regular Columns
- Articles & Editorials
"A FreeBASIC, QBasic and QB64 games magazine"
Time for another issue of BASIC Gaming!
Life has been really hectic for me lately and I'm basically running on fumes. For the past two months I had so little free time and Iím still struggling to juggle several projects within that limited amount of time. Luckily, I managed to complete this issue of BASIC Gaming (my number one project on the list) during the past weekend and today, as it was due time for a new release. The other reason is that my FBGD competition is finishing soon, so I'll need time to dedicate to that in the next few weeks. Not to mention some other plans I have that now, with this issue released, have a chance to come to life. All in all, I didn't want to procrastinate with this issue as God knows what awaits me the next few weeks professionally. I sincerely hope this period of madness at work won't continue indefinitely and that I'll be able to return to the community in my usual productive form. This community and hobby I find quite rewarding at this point of my life and I donít want to lose the positive momentum.
Once more, thanks to all developers for developing and allowing me to have something to write about. Let's keep our realistically small and underground community going, because despite that, we know that we are special and will remain that. Others might not understand, but we know we are among the chosen few. We will all cherish our memories of this awesome place and the time we had in it in the winter of our lives. I guarantee you that. But until then, be great!
~ Lachie Dazdarian (email@example.com)
News about the latest FB/QB64/QB games, game engines, game-dev libraries and site updates.
Landeel released his eagerly expected Iceroyds! game in FreeBASIC, a cool Olympics multiplayer game in the style of California Games, with comic ice planet theme, featuring a conflict between a race of sentient penguins and evil snowmen conquerors.
Download the demo or buy the full version here.
yetifoot released an isometric graphics version of rdc's Deep Deadly Dungeons, a FB rogue-like game.
David Mackey ported Hutsellís VGA Civil War Strategy, a classic shareware DOS wargame, to Windows in QB64.
Aleatorylamp released a small QB ASCII adventure game.
M.Vogler released an interesting FB screen by screen scrolling action-adventure game (in German).
Download it here (435 KB).
Laiko released a fun FB 3D Christmas mini-game, based on his and TJF's earlier FroheOstern2011 game.
Download it here (1972 KB).
Kyledub213 released a simple QB64 Nibbles game in November, which he continued to develop for the following months resulting in Slither and its latest verson 1.71.
Official forum thread.
Kyledub213 released a 15-puzzle (sliding puzzle) game in QB64 that downloads a different image to assemble each day. Download it here.
Vanya converted a Delphi version of the classic Lines game to FreeBASIC. For download and more info go here.
Follow the development in this thread.
DarthWho showcases his GO engine in QB64 featuring a basic board renderer, a simple stone renderer and work-in-progress AI.
More info in this forum thread.
jeffepp announces the beginning of his work on converting Eamon, a classic text-based role-playing adventure game, from newer QuickBASIC code (around 2000) to QB64.
Follow the development in this forum thread.
Cyperium started an intiative in the QB64 forum for a joint community game project. Follow the progress in this forum thread.
cole1121 showcases hiw work-in-progress on a DrugWars clone entitled Welcome to the Playground. For more info check out the official forum thread.
Roland Chastain is currently working on an interesting chess program for FB.
Download version 0.6a here.
Follow the development in this forum thread.
Inspired by Roland Chastain's chess game, BasicCoder2 begins working on his own chess program.
Follow the development in this forum thread.
oog released version 1.01 of his Train Simulator. Changes include revised and simplified user-interface, trains can automatically restart, when stopped within a station, some menu buttons now work like switches, showing their state (pressed, released), ...
Download version 1.01 here (4461 KB).
Follow the development in this forum thread.
For more info check the gallery section in this issue.
Gonzo continues to develop fbcraft and implement new features.
Follow the development in the official forum thread.
rdc announces a change in the direction of Underworld development, opting for classic RPG mechanics and changing the title to The Crown
More info here.
D.J.Peters introduces his wrapper for Simple Physics Engine. More info in this forum thread.
D.J.Peters delivers another wrapper for FB. Thank you for your great contributions! More info in this forum thread.
oog released a vector graphics engine that can be used to draw vector models at different zoom levels and with different levels of detail. It is part of the Train Simulator and is now available as a separate library.
For the source go here.
D.J.Peters is on fire! Another great contribution from him - eSpeak for FreeBASIC. eSpeak is a compact open source software speech synthesizer for English and other languages
Download the wrapper here.
For more info visit this forum thread.
Galleon started a cool and much needed QB64 game making competition, with a challenge to port and upgrade any QBasic game to QB64. Entry deadline is 31st of January and submission deadline is 29th of February. To join and/or follow the competition bookmark this forum thread.
As the deadline for FBGD's Rescue the Colors is closing (250$ first prize!), the participants keep revealing their awesome WIP. Just check out some of the screenshots.
For currently available demos and more info visit the official competition thread.
Keep a track on it. The competition closes on 31st of January after which I'll open a community vote poll, whose results will form the overall score of each entry.
Vincent DeCampo, a game developer in FB known for his remakes of classic arcade games, finally got his website back up after loosing it a couple of months ago. The link: http://www.iMakeGames.com
Kyledub213, a QB64 games/game dev tools developer opens a website for his projects: http://kbasic.webs.com/projects.htm
TileCity3D is a tile based 3D world editor, using OpenB3D. It allows you to define the world layout with a simple text file. TileCity generates a 3D world, which you can explore in different vehicles.
Also, don't miss Tilecity_chung, a modified version of TileCity with many new features (car/flight simulator, edit/load/save, cars traffic, gui windows, heightmaps, cars racing, houses, ...) by Chung.
For his great effort on Iceroyds!, the best FB release for the past two months, I award Landeel with the developer of the issue title.
He promised to release updates on the currently available version, so I'm waiting with the review of this wonderful game for the next issue. Until then, play the demo of buy the full version.
Slither is a cool new QB64 release, one of rare on the QB64 scene nowadays, so I feel a need to award the developer's effort with this review.
Besides being a rare QB64 game release, it's also a very good Nibbles game worth being downloaded and played. Actually, it's more a Pizza Worm-type of game, where the snake the player controls can turn with any angle. This core concept is extended with numerous and interesting game modes.
Slither comes with solid presentation, featuring well compiled main menu, instructions and sub-menus. It offers five game modes to play, each featuring both online and offline (local) high score table.
The Original game mode consists of collecting food pieces and surviving as long as possible, with each eaten food piece increasing the size of the snake.
Time Trial is similar to the original game mode, only you have a time limit between two eaten food pieces.
The Feast game mode places the player in a playfield filled with food pieces, which are re-spawned when all eaten, making it a very intensive game mode very quickly.
Speed Freak game mode goes in another direction. In this mode the player can't hit the wall edges (the playfield wraps around itself), but each eaten food pieces increases the speed of the snake.
Lil' Snake, Big World is the last game mode available in this version and to me personally the least successful. It's an interesting attempt to introduce a playfield with scrolling, but lacks the intensity of single screen modes. It's similar to Time Trial mode in concept, where the player has a limited amount of energy between two eaten food pieces. Only this mode features moving warp-holes that swarm through the playfield and transport the snake in a random position if they hit it.
On the top of all these game modes, less or more entertaining to play, you have 15 challenges to beat, from score challenges (accumulative or single round), play time challenges, to several special ones. A great addition to the game highly increasing its replay value.
Once more I should mention the availability of online scores for all game modes, which is a great plus as well, but maybe too saturated by developer's high scores. Perhaps he should have pruned the high score tables from his own repeating scores and only keep the best ones. Beside that, the game keeps your status, outlining your total play time, total accumulative score, food eaten and death count.
The game engine is very simple, but it's slick enough and does what it needs to do. Slither is fun to play, but perhaps not enough addictive for a score-driven game. It is definitely a killer coffee break game that pretty much does everything it needs to gameplay-wise. It only doesn't scratch the surface too much. It's a collection of simple and effective Snake game modes and nothing more. It also lacks more polished graphics and presentation and better sound/music support. In that sense it leaves a lot of space for improvements.
Noting the flaws more to elaborate my final score than actually feeling a need to point them out.
In one sentence, if looking for a simple arcade-style game you can play a little, return later and track your overall effort, Slither is a perfect game for you.
When talking about FreeBASIC classics, The Griffon Legend is a game that mustn't be missed, so it's due time for me to feature it in this series.
It is interesting to note that The Griffon Legend is one of the earliest FreeBASIC games, back from 2005, and it is definitely the first admirable release, one that goes beyond compiler testing and actually tries to be a game of weight outside our community. It is also a Zelda-style RPG that is pretty much unmatched till today in the FreeBASIC community, not counting Lynn's Legacy. Although there were few very potential projects that could have claimed that title, they never reached the final stages of development.
syn9 was known in the QBasic community for his Wipeout clone ZeroG, and some other 3D engines/projects, later extended to FreeBASIC, so this 2D release by syn9 came as a surprise to the community, not only by the fact it was 2D, but by the fact that it was an excellent 2D game in all aspects.
After several other FreeBASIC projects, syn9 switched to another compiler and is currently developing a 2D action RPG in the style of The Griffon Legend (you could call it a spiritual descendant), Rijn the Specpyre. So if curious check syn9's new website and download the promotional demo: http://www.thehideoutgames.com/rijn-the-specpyre
To me personally, The Griffon Legend above all is an excellent game that manages to remain that despite featuring uncommon and, I dare to say, avant-garde style. Even if all of the game eccentricities might result more from syn9's inexperience in 2D game design than from being a series of calculated choices, this key quality of the game remains uncompromised.
On the surface The Griffon Legend is a rather straight-forward, screen by screen scrolling, hack and slash game with role-playing elements, but most of ingredients that make this game have a flavor of uniqueness.
The game opens with a simple, but effectively presented story about the eternal battle between griffons and dragons, with you playing the role of a griffon knight stranded in a town burned to the ground by the dragon forces.
The game is very easy to learn to play, but difficult to master. Attacking is done simply with the SPACE key, where your character jumps in the direction he is facing and makes a lethal spin. If you hit an enemy your attack strength depletes, and the strength of the next attack will depend on how much did you let the strength meter to replenish. So hit and run strategy in this game is simply a rule that has to be obeyed. Later when you acquire spells, same will be applied on them with spell strength that depletes after each used spell. Also, each spell has a mana charger that allows you to use that spell again only after it fully recharges.
The gameplay features a quite steep learning curve, so it the very beginning the game might feel somewhat daunting. You will be quickly faced against fire spewing dragons and wizards which, if not dealt properly and quickly, are very deadly in the start, wizards even to the very end. Luckily, the game features an experience-based leveling up, so after you level up to a certain level, a greater section of the game won't feel so deadly anymore. Also, through-out the game you can find new weapons, shields and armors, increasing the attack and defense strength of your character besides with leveling up. One could say that The Griffon Legend's gameplay is an acquired taste, but I do believe the look of the game, the music, the atmosphere, and the smooth engine help new players to overcome the initial adjusting to the game's tricky mechanics.
The game is split in two main areas, two castles/temples of sort, and after beating the first boss you will learn the ability (a spell) to find new spells, which seem to be placed randomly to some extent, but it's imperative to find them all before the final boss. The very spells add a strategic element into the gameplay, each of them representing the four elements, earth, wind, water and fire, and each having different characteristics. The game features a solid collection of different enemies (including bosses and sub-bosses), some introducing long range weapons you need to evade, all of this very nicely expanding the gameplay as you progress through the game world. A type of enemies to note of are dragons represented with chain-like (or bio) animation, not so often seen nowadays in 2D indie games.
The Griffon Legend features a quite original graphics style. Despite few tiles and sprites looking out of place and clumsy, overall the developer succeeds in creating a curious and unique-looking setting. It is not very varied, but still enough varied for the size of the game. The game also comes packed with great soundtrack. I'm not familiar with the composer and according to syn9 he doesn't do music for games anymore, but the tracks in The Griffon Legend show huge talent. They add great value to the game and are probably its strongest asset.
This is a game of smaller size, providing about two hours of playtime. But it is a very well-rounded game, featuring just about enough of content for the playtime it provides, delivering a rewarding and challenging gameplay that does not pad.
The game has several flaws and it could have benefited from few updates, with some engine glitches and mistakes removed, but none of these flaws compromise the gameplay. They only leave a slightly less positive overall impression.
sny9 mentioned in a private conversation that he plans to remake The Griffon Legend in another compiler, and it's good news, as I do believe that this game deserves a wider appreciation. In that sense, I do hope syn9 won't compromise the unique style of the game, the atmospheric avant-garde look, the dialogue-less and uncompromising action-driven gameplay. Because the game's uncommon style, accidental or calculated, is something which makes it hardly repeatable, therefore special and a product our community should be proud off having.
Give this game another spin. You won't regret. Long live The Griffon Legend!
This tutorial deals with proper timing of programs, namely loops in games.
The method I will be presenting is called variable time step method (aka time-based movement).
Beside this, in my opinion best method, there are several other options for controlling the speed of your programs: limiting the frame rate, vertical refresh and SLEEP command.
All of them have big disadvantages if used alone.
SLEEP is not reliable, varies on different OSes or imposes a minimum value. Limiting the frame rate is problematic because you need to force a pause in your program every cycle until a preset time passes. The question is, what to put in the pause loop? SLEEP? But SLEEP has a minimum value in Windows XP for example (15 milliseconds), so high FPS rates are not an option. The third option is VYSNC command which matches your monitors refresh rate/frequency with the applications frame rate. Problems? Monitors have different refresh rate setups. You can force a preset refresh rate through your program (I'm not sure if all end-users will like that), but even that doesn't work in all situations, because some video cards simply don't allow you to turn on/off vsync via your program. Sooner or later a user on whose PCs your application won't be able to turn on vsync will report that he/she can't play your game.
Solution? Variable time step method. In my opinion, the most reliable and what is the best, it is indiscriminatory. You can use it with vysnc, sleep, whatever. Because it will adjust to the frame rate of your program, no matter how you control this frame rate.
How it works? Basically, all the movement (and animation) in your game should be connected to the time elapsed between two loops in this manner:
object_position_x = object_position_x + object_speed_x * time_elapsed * arbitrary_factor
The higher the speed of your program, the more cycles run in one second, more times the formula above is applied, but the absolute movement remains the same because time_elapsed is lower. The opposite situation, the lower the speed of your program, less number of cycles run in one second, less times the formula above is applied, but the absolute movement remains the same because time_elapsed is higher.
Let's see this applied in an example featuring both movement and animation. To enable variable time step method we will be using the following variables:
Dim Shared As Double loop_time = 1, this_time, tb_movement_factor = 1
loop_time will be used to flag the time passed between two loops. this_time will flag the current time on the start of the loop, later used to calculate loop_time in the next loop. tb_movement_factor is an arbitrary factor times time elapsed I used earlier. It's a dynamic global factor applied on all movement/animation/physics formulae in each loop, and equals loop_time times a factor of your choice. If multiplied with a base FPS value, when the game runs with that frame rate, tb_movement_factor equals (or is quite close to) 1. This means, if you designed you game for 60 FPS and want to switch to variable time step method, your tb_movement_factor must equal loop_time * 60 for your game to run with the same speed. In other words, how your game/program behaves on 60 FPS without variable time step method, it will also behave when this method applied with tb_movement_factor equalling loop_time * 60.
With this method applied our main loop will look like this:
Do loop_time = timer - this_time ' calculate time between two loops this_time = timer ' set the current loop time tb_movement_factor = loop_time * 60 ' adjust movement factor to 60 FPS ' Draw stuff here Loop Until Multikey(FB.SC_ESCAPE)
The following code will put this method in use in an illustrative example. We'll load 6 frames of Guybrush Threepwood, a character from Monkey Island games, and move him across the screen. We will apply the variable time step method on the animation and movement.
We'll need this gfx file.
We'll start by placing the usual header for fbgfx programs, setup a 640*480 screen, 32bit color depth:
#include "fbgfx.bi" Using FB const FALSE = 0 const TRUE = 1 SCREEN 18,32,2,0 ' Sets gfx screen Dim Shared As Integer workpage
The following pointer will point to the graphics data and the code after it loads the sprites from the image file into a memory buffer:
DIM SHARED Frame(6) AS ANY PTR BLOAD "frames.bmp", 0 FOR imagepos AS INTEGER = 1 TO 6 Frame(imagepos) = IMAGECREATE (105, 157) GET (3+(imagepos-1)*104,0)-(103+(imagepos-1)*104,155), Frame(imagepos) NEXT imagepos
Our main loop will now look like this:
Do loop_time = timer - this_time this_time = timer tb_movement_factor = loop_time * 60 guyframe = guyframe + 0.09 * tb_movement_factor if guyframe > 6.5 then guyframe = 0.51 ' loop the frames (6 frames) guybrush_x = guybrush_x + 2 * tb_movement_factor ' movement formula if guybrush_x > 660 then guybrush_x = -120 end if screenlock screenset workpage, workpage xor 1 LINE (0,0)-(639,479), RGB(255,255,255), BF ' Color the background white PUT (guybrush_x ,140), Frame(guyframe), PSET ' Paste the Guybrush sprite workpage xor = 1 screenunlock Loop Until Multikey(FB.SC_ESCAPE)
We need to declare guyframe and guybrush_x variables with DOUBLE precision. guybrush_x flags the x position of Guybrush, and guyframe the current frame of Guybrush. As you can see guyframe loops from 0.51 to 6.5. 0.51 converts to integer 1, and 6.51 to integer 7, so we need to reset back to 0.51 on 6.5 to seamlessly loop from frame 1 to 6.
Note how the guyframe increase factor is connected with tb_movement_factor. 0.09 is derived at with trial and error to sync with the speed of walking.
Same logic is used with guybrush_x, where it increases by the amount of 2 times tb_movement_factor. When Guybrush goes off screen he is reset back to the left side.
You can put a SLEEP command inside the loop with various values to test the speed of the program.
I expanded this program a bit with a FPS counter and walk by time measuring so you can test it on different frame rates and note how the walk by time is always the same. On my PC I was getting a deviation under 4 hundreds of a second between 60 and 1000 FPS in a 6 seconds time range.
The final version of the test program (FreeBASIC):
#include "fbgfx.bi" Using FB const FALSE = 0 const TRUE = 1 SCREEN 18,32,2,0 ' Sets gfx screen DIM SHARED Frame(6) AS ANY PTR ' Pointer to the memory buffer holding the sprites Dim Shared AS Integer workpage Dim Shared AS Double guyframe = 1 ' frame will be used to flag the current frame of Guybrush Dim Shared AS Double guybrush_x = -120 ' this variable will be used to flag the x position of Guybrush Dim Shared As Double walk_by_time = 0, start_walk_time = 0 ' these two variables will be used to flag ' the pass-by time of Guybrush Dim Shared As Double loop_time = 1, this_time, tb_movement_factor = 1 ' variables related to time-based movement ' loop_time -> time passed between two consecutive loops (current time - time in previous loop) ' this_time -> variable used to flag the start time of the previous loop ' tb_movement_factor -> a factor that multiplies with every movement/timing variable in the game ' if you want to sync-it with 60 FPS (make it equal 1 if the game runs 60 FPS), you multiply loop_time ' with 60 ' FPS related variables Dim As Integer frames_per_sec = 0 Dim As Integer fps = 0 Dim As Double start_time = 0 Dim As Double timer_elapsed start_walk_time = timer ' Initial values of our timing variables loop_time = timer-this_time this_time = timer ' The code that loads our Guybrush Threepwood variables BLOAD "frames.bmp", 0 FOR imagepos AS INTEGER = 1 TO 6 Frame(imagepos) = IMAGECREATE (105, 157) GET (3+(imagepos-1)*104,0)-(103+(imagepos-1)*104,155), Frame(imagepos) NEXT imagepos Do loop_time = timer - this_time ' calculate time between two loops this_time = timer ' set the current loop time tb_movement_factor = loop_time * 60 ' adjust movement factor to 60 FPS ' (if the program runs 60 FPS, tb_movement_factor will be 1) guyframe = guyframe + 0.09 * tb_movement_factor ' frame rotation (note how the speed of rotation is ' multiplied with tb_movement_factor) if guyframe > 6.5 then guyframe = 0.51 ' loop the frames (6 frames) guybrush_x = guybrush_x + 2 * tb_movement_factor ' movement formula if guybrush_x > 660 then walk_by_time = timer - start_walk_time ' when Guybrush goes off screen start_walk_time = timer ' calculate walk-by time, reset the timer, guybrush_x = -120 ' set him back on the left side of the screen end if screenlock ' Lock our screen (nothing will be ' displayed until we unlock the screen). screenset workpage, workpage xor 1 ' Swap work pages. LINE (0,0)-(639,479), RGB(255,255,255), BF ' Color the background white PUT (guybrush_x ,140), Frame(guyframe), PSET ' Paste the Guybrush sprite ' Print some variables on the screen. LOCATE 1,1 PRINT "FPS:"; fps PRINT "time-based factor:"; tb_movement_factor PRINT "walk-by time:"; walk_by_time PRINT "guyframe:"; guyframe workpage xor = 1 ' Swap work pages. screenunlock ' Unlock the page to display what has been drawn. 'SLEEP 10, 1 ' Rem/unrem to test different FPS frames_per_sec += 1 ' count loops timer_elapsed = (timer - start_time) ' calculate when one second passes if timer_elapsed > 1 then fps = frames_per_sec/timer_elapsed ' when one second passes calculate FPS frames_per_sec = 0 ' reset loop counter start_time = timer ' reset start time (for 1 second formula) end if Loop Until Multikey(FB.SC_ESCAPE)
QB64 version of the above code:
SCREEN _NEWIMAGE(640, 480, 32) ' Set screen, resolution 640*480, 32 bit DIM SHARED guyframe AS DOUBLE ' frame will be used to flag the current frame of Guybrush DIM SHARED guybrush_x AS DOUBLE ' this variable will be used to flag the x position of Guybrush DIM SHARED walk_by_time AS DOUBLE, start_walk_time AS DOUBLE ' these two variables will be used to flag ' the pass-by time of Guybrush DIM SHARED loop_time AS DOUBLE, this_time AS DOUBLE, tb_movement_factor AS DOUBLE ' variables related to time-based movement ' loop_time -> time passed between two consecutive loops (current time - time in previous loop) ' this_time -> variable used to flag the start time of the previous loop ' tb_movement_factor -> a factor that multiplies with every movement/timing variable in the game ' if you want to sync-it with 60 FPS (make it equal 1 if the game runs 60 FPS), you multiply loop_time ' with 60 ' FPS related variables DIM frames_per_sec AS INTEGER DIM fps AS INTEGER DIM start_time AS DOUBLE DIM timer_elapsed AS DOUBLE start_walk_time = TIMER ' Initial values of our timing variables loop_time = TIMER - this_time this_time = TIMER guyframe = 1 guybrush_x = -120 ' Load the Guybrush frames into a memory buffer frames& = _LOADIMAGE("frames.bmp") DO loop_time = TIMER - this_time ' calculate time between two loops this_time = TIMER ' set the current loop time tb_movement_factor = loop_time * 60 ' adjust movement factor to 60 FPS ' (if the program runs 60 FPS, tb_movement_factor will be 1) guyframe = guyframe + 0.09 * tb_movement_factor ' frame rotation (note how the speed of rotation is ' multiplied with tb_movement_factor) IF guyframe > 6.5 THEN guyframe = 0.51 ' loop the frames (6 frames) guybrush_x = guybrush_x + 2 * tb_movement_factor ' movement formula IF guybrush_x > 660 THEN walk_by_time = TIMER - start_walk_time ' when Guybrush goes off screen start_walk_time = TIMER ' calculate walk-by time, reset the timer, guybrush_x = -120 ' set him back on the left side of the screen END IF LINE (0, 0)-(639, 479), _RGB(255,255,255), BF ' Color the background white _PUTIMAGE (guybrush_x, 140), frames&, 0, (3 + (CINT(guyframe) - 1) * 104, 0)-(103 + (CINT(guyframe)- 1) * 104, 155) ' Paste the proper Guybrush frame on the screen ' Print some variables on the screen. LOCATE 1, 1 PRINT "FPS:"; fps PRINT "time-based factor:"; tb_movement_factor PRINT "walk-by time:"; walk_by_time '_LIMIT 60 ' Rem/unrem to test different FPS _DISPLAY frames_per_sec = frames_per_sec + 1 ' count loops timer_elapsed = (TIMER - start_time) ' calculate when one second passes IF timer_elapsed > 1 THEN fps = frames_per_sec / timer_elapsed ' when one second passes calculate FPS frames_per_sec = 0 ' reset loop counter start_time = TIMER ' reset start time (for 1 second formula) END IF LOOP UNTIL INKEY$ <> ""
Feel free to report your tests.
Walk by time in FB: 6.512 sec (1040 FPS), 6.509 sec (60 FPS)
Walk by time in QB64: 6.539 sec (350 FPS), 6.539 sec (60 FPS)
A disadvantage of this method is that it breaks on low frame rates (objects moving with several pixels per loop speeds, animation skipping whole frames, etc), so you need to cap the maximum value of tb_movement_factor. If will make the game playable on low frame rates, but it will run slower than intended. Then again, no other method can help with this. Also, with really sensitive physics formulae you might get weird behaviour on ultra high FPS values. But really, use VYSNC or SLEEP in your programs and consider this method only as a fail safe of sorts when SLEEP or VSYNC fail to cap the program on the frame rate you intended (like 60 FPS).
I see no reason to avoid this method in conjunction with VSYNC and SLEEP as on targeted FPS values it will be nothing more than multiplying all your movement/animation/physics formula with a factor 1 or close to it, which basically has no effect. But in a chance your program ends up running with 40 or 1000 FPS on someone's PC because whatnot, variable time step method will do the job to make the game run as it does on 60 FPS. There might be some loss on computation speed, but I doubt it should be notable for the overall execution of your program. Maybe someone making a complex 3D or physics game with a lot of movement calculations can report how much variable time step method slows down his program.
Download the FB code compiled with the graphics file: time_based_movement_FB.zip
Download the QB64 code compiled with the graphics file: time_based_movement_QB64.zip
Really tired guys. See you in a month or so and don't hesistate to contribute with something this time. I could use a little help.
~ Lachie (firstname.lastname@example.org)