summaryrefslogtreecommitdiff
path: root/template/lib/gamestate.lua
blob: d42fd22d6b652992f7e54472c54203c932475889 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
--[[
GameState - State management for ReiLua-Enhanced
Inspired by hump.gamestate for Love2D
Adapted for ReiLua-Enhanced by providing similar API

Usage:
  local GameState = require("lib.gamestate")
  local menu = {}
  local game = {}
  
  function menu:enter() end
  function menu:update(dt) end
  function menu:draw() end
  
  GameState.registerEvents()
  GameState.switch(menu)
]]

local GameState = {}

-- Current state
local current = nil

-- Stack of states for push/pop functionality
local stack = {}

-- Helper function to call state function if it exists
local function call(state, func, ...)
  if state and state[func] then
    return state[func](state, ...)
  end
end

-- Switch to a new state
function GameState.switch(to, ...)
  if current then
    call(current, 'leave')
  end
  
  local pre = current
  current = to
  
  return call(current, 'enter', pre, ...)
end

-- Push current state to stack and switch to new state
function GameState.push(to, ...)
  if current then
    table.insert(stack, current)
  end
  return GameState.switch(to, ...)
end

-- Pop state from stack and return to it
function GameState.pop(...)
  if #stack < 1 then
    return
  end
  
  local pre = current
  current = table.remove(stack)
  
  if pre then
    call(pre, 'leave')
  end
  
  return call(current, 'resume', pre, ...)
end

-- Get current state
function GameState.current()
  return current
end

-- Register callbacks to RL framework
function GameState.registerEvents()
  -- Override RL callbacks to forward to current state
  local RL_init = RL.init
  local RL_update = RL.update
  local RL_draw = RL.draw
  local RL_event = RL.event
  local RL_exit = RL.exit
  
  RL.init = function()
    if RL_init then RL_init() end
    call(current, 'init')
  end
  
  RL.update = function(dt)
    if RL_update then RL_update(dt) end
    call(current, 'update', dt)
  end
  
  RL.draw = function()
    if RL_draw then RL_draw() end
    call(current, 'draw')
  end
  
  RL.event = function(event)
    if RL_event then RL_event(event) end
    call(current, 'event', event)
  end
  
  RL.exit = function()
    if RL_exit then RL_exit() end
    call(current, 'exit')
  end
end

-- State callbacks that can be implemented:
-- state:enter(previous, ...) - Called when entering state
-- state:leave() - Called when leaving state
-- state:resume(previous, ...) - Called when returning to state via pop()
-- state:init() - Called once at game start if state is initial
-- state:update(dt) - Called every frame
-- state:draw() - Called every frame for rendering
-- state:event(event) - Called on input events
-- state:exit() - Called when game exits

return GameState