SHARE
TWEET

LOVE2d state-system

Snusmumriken Jul 2nd, 2016 (edited) 216 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2.     states v0.8
  3.     (c) by Tommy (aka Snusmumriken)
  4.     If you see it, you will go to jail.
  5.  
  6.  Usage:
  7.  --initialisation state-system
  8.  state = require 'states'
  9.  state:init() -- define love.update/love.draw with state mashine
  10.  
  11.  --initialisation table for state #1
  12.  local stateA = {}
  13.  function stateA:init()
  14.     self.x, self.y = 0, 0
  15.     self.t = 0
  16.  end
  17.  function stateA:load(x, y)
  18.     self.x = x or self.x
  19.     self.y = y or self.y
  20.  end
  21.  function stateA:update(dt)
  22.     self.t = self.t + dt * 10
  23.  end
  24.  function stateA:draw()
  25.     if love.keyboard.isDown('2') then self.State:set('B') end
  26.     love.graphics.rectangle('line', self.x + math.sin(self.t) * 100, self.y)
  27.  end
  28.  
  29.  --initialisation table for state #2
  30.  local stateB = {}
  31.  function stateB:init(text)
  32.     self.text = text or 'no text'
  33.  end
  34.  
  35.  function stateB:load()
  36.     self.rect = {10, 20, 40, 30}
  37.     self.bool = false
  38.  end
  39.  
  40.  function stateB:keypressed(key, unicode, isrepeat)
  41.     if key == ' ' then self.bool = not self.bool end
  42.     if key == '1' then self.State:set('A') end
  43.  end
  44.  
  45.  function stateB:draw()
  46.     love.graphics.print(self.text)
  47.     if self.bool then
  48.      love.graphics.setColor(100, 200, 100)
  49.     else
  50.      love.graphics.setColor(200, 100, 100)
  51.     end
  52.     love.graphics.rectangle('line', unpack(self.rect))
  53.    
  54.  end
  55.  
  56.     -- attaching states:
  57.     state:new('A', stateA)
  58.     state:new('B', stateB, 'Hello from state B!')
  59.     state:set('A', 100, 300)
  60.  
  61. ]]
  62.  
  63. local type = type
  64. local love = require'love'
  65.  
  66. if not love then error('This lib only for LOVE2D framework. download it here: https://love2d.org', 2) end
  67.  
  68. local function err(v, str, ...)
  69.     if not v then error(str:format(...), 3) end
  70. end
  71.  
  72. local callbacks = {'update', 'draw'}
  73.  
  74. --track love.handlers of current version of LOVE2d
  75. for k, _ in pairs(love.handlers) do
  76.     callbacks[#callbacks + 1] = tostring(k)
  77. end
  78.  
  79. --Initialise state defaults
  80. local function state(t, name, global)
  81.     local s = t or {}
  82.     s.State = global
  83.     s.Name  = name
  84.     s.Break = {}
  85.     return s
  86. end
  87.  
  88. --State manager
  89. local states = {}
  90.  
  91. function states:__new()
  92.     self.state = {} --state list
  93.     self.stack = {} --current stack
  94.     self.debug = true
  95.     self.__index = self
  96.     return self
  97. end
  98.  
  99. --Self and additional love callback initialisation
  100. --(load/update/draw/keypressed/keyreleased etc)
  101. function states:init()
  102.     for _, k in ipairs(callbacks) do
  103.         --initialisation self methods like self:update(dt)
  104.         self[k] = function(self, ...)
  105.             local startStackPosition = 1
  106.            
  107.             -- roll back and find first callback-overrider state
  108.             for i = #self.stack, 1, -1 do
  109.                 local v = self.stack[i]
  110.                 if v.Break and v.Break[k] then
  111.                     startStackPosition = i
  112.                     break
  113.                 end
  114.             end
  115.            
  116.             -- call callbacks from all states in stack, start from first overrider
  117.             for i = startStackPosition, #self.stack do
  118.                 local s = self.stack[i]
  119.                 if type(s[k]) == 'function' then
  120.                     s[k](s, ...)
  121.                 end
  122.             end
  123.         end
  124.        
  125.         --optional addition methods for love, if not defined
  126.         if not love[k] then
  127.             love[k] = function(...)
  128.                 self[k](self, ...)
  129.             end
  130.         end
  131.     end
  132.     return self
  133. end
  134.  
  135. function states:new(n, t, ...)
  136.     err(type(n) == 'string', 'Arg#1: State name expected, got "%s"',  type(n))
  137.     err(type(t) == 'table',  'Arg#2: State table expected, got "%s"', type(t))
  138.    
  139.     local st = state(t, n, self)
  140.    
  141.     self.state[n] = st
  142.     if type(st.init) == 'function' then
  143.         st:init(...)
  144.     end
  145.     return s
  146. end
  147.  
  148. function states:set(name, ...)
  149.     err(type(name) == 'string', 'Arg#1: State name expected, got: "%s"', type(name))
  150.    
  151.     local s = self.state[name]
  152.     err(s,'Arg#1: Name of defined state required, got: "%s"', tostring(name))
  153.    
  154.     if self.debug then love.window.setTitle(name) end
  155.     for i = #self.stack, 1, -1 do
  156.         local s = self.stack[i]
  157.         if type(s.unload) == 'function' then
  158.             s:unload()
  159.         end
  160.     end
  161.     self.stack = {s}
  162.     if type(s.load) == 'function' then
  163.         s:load(...)
  164.     end
  165. end
  166.  
  167. -- override_table is table with callback-keys, if key [keypressed] == true then after that state this callback brakes
  168. function states:push(name, ...)
  169.     local s = self.state[name]
  170.     err(s, 'Arg#1: Name of defined state required, got: "%s"', type(name))
  171.    
  172.     self.stack[#self.stack + 1] = s
  173.     if type(s.load) == 'function' then
  174.         s:load(...)
  175.     end
  176. end
  177.  
  178. function states:pop(...)
  179.     err(#self.stack > 0, 'More pops then pushes')
  180.     local s = table.remove(self.stack)
  181.     if type(s.unload) == 'function' then
  182.         s:unload(...)
  183.     end
  184. end
  185.  
  186. function states:getStack(name)
  187.     return self.stack
  188. end
  189.  
  190. return states:__new()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top