DEV Community

BibleClinger
BibleClinger

Posted on

Mini Micro and The Game Loop

Sometimes the lack of threads in MiniScript makes programmers wonder how to do multiple things. The MiniScript wiki has a good example of how to do this very thing. I'd like to bring your attention to this particular block of code from that example:

lastTime = time
while not key.pressed("escape")
    now = time
    dt = now - lastTime
    lastTime = now
    updateCounter dt   // Update the counter
    ball.update dt     // Update the ball
    yield
end while
Enter fullscreen mode Exit fullscreen mode

The way singlethreaded games work is to employ a single loop just like this one, often called "the main loop" or "the game loop." In the very simplest implementation, you're supposed to be doing all of your game calculations for one frame exactly within the body of the loop, and then sleep for the rest of the frame.

In this example, we need to update both a counter and the ball for each frame. This is handled in the loop by the two lines with comments.

Engine class

The above loop is easy enough code to write, but it can be tedious to write it over and over again as boilerplate in a lot of programs. Also, sometimes you might have more complicated scenarios where you would like a bit more control over what gets updated without having to write all of that out again.

I wrote a class for this that I simply called Engine as part of my MiniScript library called bclib. It provides a mechanism to handle a game loop and provide updates to each object/function that it is given. It can also handle adding and removing from the update list during runtime.

The above code block can be replaced with the following:

import "bclib"

checkEsc = function(dt)
    if key.pressed("escape") then engine.quit
end function

engine = bclib.Engine.Create([@updateCounter, ball, @checkEsc])
engine.run
Enter fullscreen mode Exit fullscreen mode

Example Breakdown

Engine.Create accepts a list. The elements of the list are simply either standalone functions, or else (perhaps preferably) maps that have a tick or update function (searched for in that order). You essentially hand it your code to deal with keyboard input, graphics changes, physics input -- whatever you want your game to do.

In this case, we need two main updates to occur: the updateCounter function and the ball.update function. We pass a function reference directly to updateCounter, but we pass ball directly, since Engine will look for and find its update function. In order to also maintain the condition that the escape key will cause the program to exit, the function checkEsc is written here, and a function reference to it is passed in to Engine.Create as well.

engine.run is where the main loop happens. It blocks while it is running. When engine.quit is called, the engine ceases operations once that entire frame cycle has completed, and engine.run returns.

Other features

Engine also looks for an init function belonging to any update object. This allows for any object initialization that needs to be done. This function is entirely optional, and does not need to be provided. Similarly, it looks for an optional deinit function on any objects that are removed -- or that are still present after Engine.quit has been called.

For more information, please see the Engine wiki page at the github. As the time of this writing, it is still a work in progress, as the library is still being worked on.

Conclusion

In order to do multiple things at once in Mini Micro, programmers need a main loop. The Engine class in the bclib library provides the mechanism to maintain a main loop.

Top comments (0)