Moai Main Event Loop

The previous Moai example I posted before only setup a scene, but it didn’t have a main game loop.  The main loop can be important if you want to try to do something at a regular interval, like polling for input or advancing some game logic.  Here’s a basic example you can add to the bottom:

gameOver = false

local mainLoop = ()

mainLoop:run (
  function ()
    while not gameOver do
      -- Do processing here
      coroutine.yield ()
    print("Game Over!")

The loop here uses the Lua concept of a coroutine, which is something used to run multiple tasks at once. It doesn’t actually use real threads, so you don’t need to worry about all those multithreading concerns you usually have to deal with in other languages. On the other hand, since it is all actually happening in one thread, you’re not going to benefit from multiple processors either. To use a coroutine, you define a function which has “coroutine.yield()” called in it. When the function is run by a coroutine, it will go until it hits the “yield()” call, and then return. The next time the coroutine calls the function, it will pick up where it left off, and then continue until it hits another “yield()” call. By having a bunch of coroutines lined up, and then running them one after the other, you have something that is similar to running a bunch of threads at the same time.

In this example, the first I do is declare the global variable “gameOver”, which is a bool we will use to signal that the game is over and the program should terminate. Next we create an instance of MOAICoroutine, and pass a new function into it’s run() function. This is what Moai will use to run every simulation step. All we have to make sure we do is call “couroutine.yield()” at the end of every step, and then call “os.exit()” once we are all done.  In the while loop, before you “yield()” call, you should do all your game logic.

An alternative to this could be to use callbacks to respond to certain user events like mouse clicks or key presses.  However, as your program becomes more complicated and has different game states (start menu, gameplay, pause menu), I think it becomes a little harder to track of who should be responding to these callbacks.  The game loop is also closer to the setup I’ve seen in some other frameworks, so it should be a little easier to port later if you go that way.

Leave a Reply