I'm trying to do a simple state machine but I'm doing something wrong in the assign.
I wanna assign "running" if a button is pushed from a list of values.
player = { lives = 3, current_state, list_states = {"running","jumping","falling"} } function _update() if btnp(❎) then player.current_state = player.list_states["running"] end end function _draw() cls(1) print(player.current_state) end |
This doesn't work:
player.current_state = player.list_states["running"]
This works but its not very useful because I don't see in the code which state I'm assigning:
player.current_state = player.list_states[1]
This also works, but I think it's also not very useful because the usefulness of the state machine is assigning a concrete value from a set of predefined values to avoid mistakes.
player.current_state = "running"
How can i do it? Or whats the usual approach to make states machines?
Thank you!



Just storing a string is the usual way.
Another way is to represent each state as a function that implements what the object does in that state, and storing one of the functions in the object when the state changes.



I typically just assign a string as dredds said. But if you wanted to use the list_states, I'd probably just add a comment in the code to make it clear:
-- set player state to running player.current_state = player.list_states[1] |
The reason plyaer.current_state = player.list_states["running"]
doesn't work is that "running" isn't used as a key in your table, just a value. If you want to use "running" as a key, you have to do something like this:
player={ lives=3, current_state, list_states={running="running",jumping="jumping",falling="falling"} } player.current_state = player.list_states["running"] -- or player.current_state = player.list_states.running |



@chermosi, If i understood you correctly, you want to be able to do
player.current_state = "running"
but have the game gracefully crash if you use an invalid value like
player.current_state = "runing"
This is doable but a bit tricky : there is no general metamethod in LUA to catch every assignation or access. Once a key is assigned a value, you can't control future read or write access to it.
There are two metamethods for read and write access to the value associated to a nonexistent key :
__index = function (table, key) |
for reads, and
__newindex = function (table,key,value) |
for writes.
By not having current_state in the table, you can catch every read and writes that use 'current_state' key and behave accordingly. You'll need an extra key ('_current_state') for example for the real storage of the state. You'll also have to handle accesses to other nonexistent keys by returning nil for reads, and creating the new elements with rawset(table,key,value) .
Tell me if you're interested in this solution, and if so, if you need help writing it.
[Please log in to post a comment]