All games need a game loop. It is the guts of your game and where all of the action happens, so it is important that it is controlled well and that it doesn’t get out of hand. I like to keep things super organised and prefer to only have one game loop happening in my game. So for this, I always use a singleton class. So whilst developing my game with Lua & the Corona SDK I endeavored to maintain this architecture within my game. The GameController class that I created is used to control all of the timings and enterFrame animations. It needs to be callable from anywhere within my game and I need to be able to add callback functions to the game loop and remove them for that case. Using a singleton is perfect as it means that I know that only one GameController is in use and if I need to add an enterFrame loop within one of my levels – in fact I usually use them in all of them – I just make a call to the GameController’s addCallback method to add a method from my level to the GameController’s loop.
-
GameController.getInstance().addCallback(levelOneLoop, 'levelOneLoop')
The two parameters for the addCallback method are the actual method to be added as a callback and a name for the method as a String. This string is used to add the method to a table with a reference value, it also helps when removing the game from the loop, by calling the removeCallbackByName method, which removes the method from the main game loop.
-
GameController.getInstance().removeCallbackByName('levelOneLoop')
The GameController also contains a method called beginGame, which is called to begin the game, as well as pause, stop & resume methods to control the loop at anytime.
Anyway, here is the class in its entirity:
-
local _instance, callbacks = nil, {}
-
-
function GameController.getInstance()
-
if not _instance then
-
_instance = GameController
-
end
-
-
local function gameLoop()
-
for i, callback in pairs(callbacks) do
-
if callback ~= nil then
-
callbacks[i]()
-
end
-
end
-
end
-
-
_instance.getCallbacks = function()
-
return callbacks
-
end
-
-
_instance.removeCallbackByName = function(name)
-
callbacks[name] = nil
-
end
-
-
_instance.addCallback = function(callback, name)
-
callbacks[name] = callback
-
end
-
-
_instance.clearAllCallbacks = function()
-
callbacks = {};
-
end
-
-
_instance.stop = function()
-
Runtime:removeEventListener("enterFrame", gameLoop)
-
end
-
-
_instance.pause = function()
-
_instance.stop();
-
end
-
-
_instance.resume = function()
-
_instance.beginGame();
-
end
-
-
_instance.beginGame = function()
-
Runtime:addEventListener("enterFrame", gameLoop)
-
end
-
-
_instance.main = function()
-
_instance.beginGame()
-
end
-
-
return _instance
-
end
-
-
function GameController:new()
-
assert(nil, 'GameController is a singleton and cannot be instantiated - use getInstance() instead')
-
end
Happy coding.

