# Game State Management using Lua

I want to be able to (only) define game states using Lua script, but I'm not sure how I should do it. Here's what I have in mind currently:

For each state, I will create a .lua file that contains a class (table) that has the same name as the file name. Each table must have a set of event handlers: onEnter (called when the state is entered), onUpdate (called every frame) and onExit (called when exiting the state). So if I want to have a MainMenuState, I will have a file called "MainMenuState.lua" which will contain something like this:

MainMenuState = {}

end

end

end


Defined states will be exposed to the game engine via a singleton StateManager class. StateManager will have a function that registers a state under a unique name:

void registerState(string stateName, string fileName);


State registration will be done in script by placing the registration codes inside an init script that is called once after the game engine is initialized:

--init.lua
--Register all the states needed by the game
StateManager:registerState("SplashScreen", "SplashScreen.lua")
StateManager:registerState("InGameState", "InGameState.lua")
-- etc etc


StateManager will also keep track of which state is currently active and also handle state transitions:

//cpp
void changeState(string state);

--lua

• may ask what is your problem? every thing looks just fine. I can only add OnRender event to your state system to make it more complete. – Ali1S232 Sep 17 '11 at 12:38
• There's no problem (yet). This is my first time using scripting for a project, and I'm just wondering if my hypothetical approach is good enough. – Fishcake Sep 18 '11 at 10:46

It's not entirely clear what you're asking, but there's nothing inherently "wrong" with the way you are structuring your state machine. As long as it fits the task at hand, any implementation can be considered "correct".

One change I would suggest making is to allow the states themselves to be instanced, so that you can store state in your instance. This can be as simple as:

SplashScreen = {}
local instance = setmetatable({}, SplashScreen)

SplashScreen.createInstance = function(...)
local instance = setmetatable({}, SplashScreen)
instance.endTime = 5.0 -- set instance data
return instance
end

function SplashScreen:update(elapsedTime)
if elapsedTime > self.endTime then -- use instance data
end
end


Note that, due to the setmetatable call, instance tracks all of your state's functions; so your 'current state' is really just an instance ref in your StateManager:

function StateManager:changeState(stateName, ...)
local stateTable = --[[ get state from file ]]
local instance = stateTable.createInstance(...)

self.currentState = instance
end

function StateManager:call(funcName, ...)
local fn = self.currentState[funcName]
fn(self.currentState, ...)
end


I preferred to use numbers with my state systems. It's not the best way but it works great for me.

state = 1
while true do
if state==1 then
if 1=1 then
state=2
end
end
if state==2 then
if 2=2 then
state=1
end
end
end


works for me :)

• This is a horrible horrible way of dealing with states, don't do it people! – Derek Jan 10 '12 at 7:36
• Why is it 2xhorrible? – Richard Sparrow Jan 10 '12 at 14:39
• @RichardSparrow Because you always need to know what each number means. If anyone else were to work on the code, or if you were to go back to try to fix a bug a few weeks or months after writing it, if state==1 would be a mystery – yoozer8 Feb 9 '12 at 3:05