## Yet another state system

HDPLocust
Citizen
Posts: 52
Joined: Thu Feb 19, 2015 10:56 pm
Location: Ru
Contact:

### Yet another state system

Here simple state-system, working like average state automaton.
States can be required from files, returns a table with the methods.
Each state has its own local field, which does not affect the global variables and other states.
Example:

Code: Select all

state = require 'gamestate'

function menu:load(x, y)	--method calls every gamestate:set('statename', ...), can be called with any arguments
--'self' is local namespase for that state
self.x = x or 10
self.y = y or 20
end

function menu:unload()	--method is called when this state is replaced by another, using gamestate:set('statename', ...).
self.x, self.y = nil, nil
end

if key == 'return' then state:set('game') end
end

end

game = {}
self.x = 10
self.y = 20
end

function game:keypressed(key)
if key == 'return' then state:set('menu', math.random(300), math.random(200)) end
end

function game:draw()
love.graphics.print('state: game', self.x, self.y)
end

state:new('game', game)

--if love[callbackname] is defined, is required to use state:[callbackname] method.
function love.keypressed(key)
if key == 'escape' then love.event.quit() end
state:keypressed(key)
end

Full list of callbacks here: https://love2d.org/wiki/love.

Easy example attached.
Upd: autotracker handlers.
Attachments
states.love
Last edited by HDPLocust on Sat Jul 02, 2016 4:39 pm, edited 1 time in total.
Science and violence

HDPLocust
Citizen
Posts: 52
Joined: Thu Feb 19, 2015 10:56 pm
Location: Ru
Contact:

### Re: Yet another state system

I use it for easy separate states to list of files and control every state without using global strings.

Next features in development - stack of states and multiple states in one time.
Science and violence

cval
Citizen
Posts: 58
Joined: Sun Apr 20, 2014 2:15 pm
Location: Ukraine

### Re: Yet another state system

The thing that kinda worries me with libraries and helpers that are appearing lately and that rely on, process or affect engine callbacks in any way, is that when people implement "keypressed" callback (for example), they sometimes forget about the fact that this function actually accepts and passes three arguments, according to wiki:

Code: Select all

love.keypressed( key, scancode, isrepeat )
"Scancode" appeared in 0.10 and whereas it's not really mandatory to write your library functions exactly like that (and if you aim for compatibility with older versions - not necessary at all), people who use it later in their project may experience bugs that sometimes aren't easy to track. You know, because their code may expect those omitted arguments and process it somehow to change state of their program flow.

Just wanted to point that out (=
Kinda personal preference actually, but it cost me a few hours of headache once just because i had to change similar piece of code in my project for it to work as intended.

zorg
Party member
Posts: 2668
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

### Re: Yet another state system

Calling functions the following way will ensure that a lib designer has no responsibility for any changes in passed arguments:

Code: Select all

a_function(...)
-- example:
function love.keypressed(...)
currentState.keypressed(...)
end
-- where currentState has a function like this, though param names don't really matter all that much:
state.keypressed(key, scancode, isrepeat)

Granted this won't work if the function is not defined in the state, but that's another bag of tricks to deal with
(currentState.keypressed and currentState.keypressed(...) is one solution, but one could or it with an empty function too)
i do prefer hump gamestates myself though.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

HDPLocust
Citizen
Posts: 52
Joined: Thu Feb 19, 2015 10:56 pm
Location: Ru
Contact:

### Re: Yet another state system

zorg wrote:Granted this won't work if the function is not defined in the state, but that's another bag of tricks to deal with
(currentState.keypressed and currentState.keypressed(...) is one solution, but one could or it with an empty function too)
cval wrote: "Scancode" appeared in 0.10 and whereas it's not really mandatory to write your library functions exactly like that (and if you aim for compatibility with older versions - not necessary at all), people who use it later in their project may experience bugs that sometimes aren't easy to track. You know, because their code may expect those omitted arguments and process it somehow to change state of their program flow.
I use function generation from list of callbacknames, and this tricks too.
Any callback called with multiple arguments, passes through "...", like original callbacks.

Code: Select all

--This simplifies the addition of new callbacks with a totally any arguments.
local callbacks = {
'keypressed', 'keyreleased', 'textinput', 'textedited',
'mousepressed', 'mousereleased', 'mousefocus', 'mousemoved', 'wheelmoved',
'touchpressed', 'touchreleased', 'touchmoved',
'directorydropped', 'filedropped',
'quit', 'lowmemory',
'focus', 'visible',
'update', 'draw',
'joystickpressed', 'joystickreleased', 'joystickremoved'
}
--Self and additional love callback initialisation
function states:init()
for _, k in ipairs(callbacks) do
--initialisation self methods like self:update(dt)
self[k] = function(self, ...)
if self.current[k] and type(self.current[k]) == 'function' then
--passed "self" and any number of arguments, with any names and etc.
self.current[k](self.current, ...)
end
end
--optional addition methods for love, if not defined
if not love[k] then
love[k] = function(...)
self[k](self, ...)
end
end
end
return self
end

function anystate:keypressed(key, scancode, isRepeat) {code} end - works fine too.
In love 0.10. Indeed, in another version, they will not be passed arguments "scancode" and "isrepeat".
Heh.

I can't say that "the designer no responsibility".
Rather, it is the possibility of using the library on all versions of love.

Yea, callbacknames forbidden for use:

Code: Select all

--Function returns new state like object
local function state(t)
return setmetatable({}, {
--table with methods
__index = t,
--forbidding reserved names
__newindex = function(self, key, value)
--checking if key is not named like any callback in list
if not isReserved(key) then
rawset(self, key, value)
else
error('Trying to modify reserved callback "'..key..'"', 2)
end
end
}
)
end

I'm sorry, I do not use github, and therefore the source code on pastebin.
http://pastebin.com/9rgH4BAj
Science and violence

cval
Citizen
Posts: 58
Joined: Sun Apr 20, 2014 2:15 pm
Location: Ukraine

### Re: Yet another state system

If you really want to cover all callbacks (like, all of them that are defined in love.handlers) you can fill your callback names table with following code on table init. (i.e. you don't need to fill table manually)

Code: Select all

local i = 1
for k,v in pairs(love.handlers) do
print(k,v) -- this one just prints them
callbacks[i] = tostring(k)
i = i+1
end
This way your lib will automatically track if there is a new callback/handler in upcoming updates.

HDPLocust
Citizen
Posts: 52
Joined: Thu Feb 19, 2015 10:56 pm
Location: Ru
Contact:

### Re: Yet another state system

cval wrote:If you really want to cover all callbacks (like, all of them that are defined in love.handlers) you can fill your callback names table with following code on table init.

Code: Select all

for k,v in pairs(love.handlers) do
print(k,v) -- this one just prints them
table.insert(callbacks, tostring(k))
end

This way your lib will automatically track if there is a new callback/handler in upcoming updates.
Wow, nice!
I use it, thanks :3

Love handler no update/draw callbacks,
but they just can be added manually, and the rest of the track automatically.
Science and violence

cval
Citizen
Posts: 58
Joined: Sun Apr 20, 2014 2:15 pm
Location: Ukraine

### Re: Yet another state system

HDPLocust wrote:
Love handler no update/draw callbacks,
It is because of how love.run works by default, you can see that if update/draw it is defined by user, it will be called, otherwise it is skipped in run loop.

HDPLocust
Citizen
Posts: 52
Joined: Thu Feb 19, 2015 10:56 pm
Location: Ru
Contact:

### Re: Yet another state system

cval wrote:
HDPLocust wrote:
Love handler no update/draw callbacks,
It is because of how love.run works by default, you can see that if update/draw it is defined by user, it will be called, otherwise it is skipped in run loop.
Every user i know, uses update and draw :3
Is no require to uses love.graphics.present and structuring code.
Hm, restrictions.
Science and violence

HDPLocust
Citizen
Posts: 52
Joined: Thu Feb 19, 2015 10:56 pm
Location: Ru
Contact:

### Re: Yet another state system

So. Now it have state-stack with overriding. I need to make the doc.
Science and violence

### Who is online

Users browsing this forum: No registered users and 5 guests