Page 1 of 1

I want to make my own gamestate library.

Posted: Fri Oct 05, 2012 6:55 pm
by Tesselode
I want to have a gamestate library that works like this:

Code: Select all

state = gamestate.new()

function state:load()
end

function state:update(dt)
end
The problem is I'm not sure how to link the gamestate functions to the love callbacks. I know it has something to do with metatables, but how exactly do you detect when a callback function is called?

Re: I want to make my own gamestate library.

Posted: Fri Oct 05, 2012 7:19 pm
by SudoCode
You could probably get a good idea by looking through the existing gamestate libs. hump, maybe.

Re: I want to make my own gamestate library.

Posted: Fri Oct 05, 2012 7:50 pm
by Inny
The trick to "States" is the "StateMachine" that drives the states. In short, you have to have the lua callbacks call into the state machine. Here's a short example:

Code: Select all

GameState = {}
function GameState:update(dt) end

Statemachine = { current=GameState }
function Statemachine:update(dt)
  self.current:update(dt)
end

function love.update(dt)
  Statemachine:update(dt)
end
In my own personal projects, I like having the StateMachine be a stack/queue combination, meaning that I can ready a state that will start on the next update cycle, and then the states can send updates via the statemachine to each other. In practice, it means I can still have the GameState draw, even though the OptionsMenuState is at the top of the stack.

Re: I want to make my own gamestate library.

Posted: Fri Oct 05, 2012 7:54 pm
by IMP1
The way I do it is this:

In another file, have your state:

Code: Select all

local state = {}
state.__index = state

function state.load()
    local this = {}
    setmetatable(this, state)
    -- this is the basic table that represents the state
    -- so initial values for properties of the state would be set here
    return this
end

function state:update(dt)
    -- update state here
end

function state:draw()
    -- draw state here
end

-- any other functions

return state
And in your main.love you'd have this:

Code: Select all

gamestate = require("path.to.your.state")
function love.load()
    state = gamestate.new()
end
-- etc. with update.

Re: I want to make my own gamestate library.

Posted: Fri Oct 05, 2012 8:05 pm
by Tesselode
So far all of the suggestions require that you manually call functions for the current state in each callback. Is there a way I can automatically have it do:

Code: Select all

function love.load()
  current_state.load(dt)
end

function love.update(dt)
  current_state.update(dt)
end

etc...
I know hump.gamestate does this with the registerEvents function, I'm just not sure how.

Edit: If I am reading the hump.gamestate code correctly, this is where all the magic happens:

Code: Select all

for _, f in ipairs(callbacks) do
  love[f] = function(...) GS[f](...) end
end

Re: I want to make my own gamestate library.

Posted: Fri Oct 05, 2012 11:26 pm
by Kadoba
Basically it's just a shortcut for exactly what you were doing.

Code: Select all

function love.load()
  current_state.load(dt)
end

function love.update(dt)
  current_state.update(dt)
end

function love.draw()
  current_state.draw()
end

-- Same as above
local callbacks = {"load", "update", "draw"}
for k,v in pairs(calllbacks) do
   love[v] = function(...)
      if current_state[v] then current_state[v](...) end
   end
end

Re: I want to make my own gamestate library.

Posted: Fri Oct 05, 2012 11:26 pm
by Inny
It's more or less the norm to expect love.update call your library's update function. Love has no way to automatically register an event handler other than overwriting love.update.

For fun, you could have a function, or table with a __call or __index metatable, that does some basic routing of messages.

Code: Select all

Statemachine = setmetatable({}, {
  __index = function(self, message)
    if not self[message] then
      self[message] = function(...)
        current_state[message](...)
      end
    end
    return self[message]
  end
})
With this, it'll automatically generate the update, draw, keypressed, and so on event handlers as you need them. But I consider it a toy rather than something to base a library on.