Page 1 of 2

[Library] st8.lua

Posted: Mon Mar 30, 2015 10:25 am
by s-ol
St8.lua
A tiny double-stacked state manging library for Lua/LÖVE

Concept
St8 keeps two Stacks of States:

Code: Select all

              Movement  `^` 
            Input State `Isecondary stack`
    Menu  -    Game     `I`  - Pause Menu Overlay 
    `--------------primary stack--------------->`
All States in the currently active Stack will run in parallel (i.e. receive events)

Usage
You can add and remove Stacks (elements on the primary stack) using `pause` and `resume`.
You can add and remove States (elements on the secondary stack) using `push` and `pop`.

All methods accept a variable number of arguments, these arguments will be passed on both to the last State/Stack and the new ones.
`init` and `pause` accept lists or single States as arguments.

Events
St8 covers all of LÖVE's callbacks (as of 0.9.2). Event callback methods receive one additional parameter (as the first one).
This is the return value of the State above the one receiving the event currently; For the topmost State it will always be `nil`.
The return value of the last State of the current Stack will be returned. This happens regardless of whether the LÖVE callback expects a return value and can be used to pass messages between States of a Stack.

View & Star on Github: https://github.com/S0lll0s/st8.lua

tbh I didn't even check if there already is a library with this concept (I'm on a bus and the network is really slow); but I did look for the name and it doesn't seem to be taken.

Feedback ofc appreciated!

Re: [Library] st8.lua

Posted: Mon Mar 30, 2015 1:28 pm
by zorg
S0lll0s wrote:All States in the currently active Stack will run in parallel (i.e. receive events)
Could you elaborate further? I'm not sure i'm seeing how it could run "in paralell".
S0lll0s wrote:You can add and remove Stacks (elements on the primary stack) using `pause` and `remove`.
"pause"? How does pause mean adding a stack? To me, currently, it seems like a not so good choice, but i may be wrong...
S0lll0s wrote:tbh I didn't even check if there already is a library with this concept
The only one to come to my mind would be vrld's HUMP gamestates, and that is somewhat different.
I'll check this out more from home.

Re: [Library] st8.lua

Posted: Mon Mar 30, 2015 4:03 pm
by rmcode
Looks good!
zorg wrote:Could you elaborate further? I'm not sure i'm seeing how it could run "in paralell".
Small example: Imagine you let the player open an inventory or some other menu. You can create a new state (yay for clean code) and push it onto the stack. Now you can render the game state below the menu behind a blur shader (for a cool effect). This way you could pause the actual gameplay but continue to update animations for an even cooler effect.

Or you could reuse the same moving background for multiple different menus.

P.S.: My ScreenManager allows stacking of different states too.

Re: [Library] st8.lua

Posted: Mon Mar 30, 2015 4:44 pm
by s-ol
rmcode got it, I typed this up before he wrote but couldn't post because of bus-internet. Still:
zorg wrote:
S0lll0s wrote:All States in the currently active Stack will run in parallel (i.e. receive events)
Could you elaborate further? I'm not sure i'm seeing how it could run "in paralell".
Basically this allows sub-states (see ASCII-drawing above). All of them receive all events in a selectable order (selectable per event type).

In my current project there is a "game" state that draws and updates the map, and then there are multiple states for different states during each round (its a turn-taking game); things like "move character", "choose attack" etc. While these run, the map still gets updated. Because the callbacks pass a parameter to each other, events can mask each other:

Code: Select all

local specific, general = st8.new(), st8.new()
function specific.keypressed(p, key)
  if key == " " then
    foo()
    return true
  end
end

function general.keypressed(p, key)
  if p then return p end -- p is the true from above
  if key == " " then
    bar()
    st8.push(specific)
  end
end

st8.init(general)
-- space now runs bar() once, then too() every time it is pressed
Note that this behavior is purely cooperative, St8 doesn't enforce anything about 'p'.
zorg wrote:
S0lll0s wrote:You can add and remove Stacks (elements on the primary stack) using `pause` and `remove`.
"pause"? How does pause mean adding a stack? To me, currently, it seems like a not so good choice, but i may be wrong...
The current stack is paused and instead the new one is activated. Afterwards you can resume execution of the paused one. Terminology is a bit confusing here, better ideas welcome :D

Re: [Library] st8.lua

Posted: Mon Mar 30, 2015 5:49 pm
by zorg
rmcode wrote:Small example: Imagine you let the player open an inventory or some other menu. You can create a new state (yay for clean code) and push it onto the stack. Now you can render the game state below the menu behind a blur shader (for a cool effect). This way you could pause the actual gameplay but continue to update animations for an even cooler effect.
This i do with hump.gs already, though that state manager is more limited than this it seems; but there, i just needed to refer to the state below the current, and call the callbacks of that from the current (topmost) state.
I'm guessing one could do more than just that with this library.
S0lll0s wrote:Basically this allows sub-states (...) All of them receive all events in a selectable order (selectable per event type).
So it's not really paralell, but more like definable-serial? Also, you do this by the "p" parameter in your example? I'd imagine one could do convoluted logic pathways with that like that...

Anyway, i'll try to bend my head around it, maybe i'll get how it works sooner or later :3

Btw, the ASCII drawing on your github made more sense than what's in this thread, at least to me :crazy:

Re: [Library] st8.lua

Posted: Mon Mar 30, 2015 6:44 pm
by Jasoco
This is basically what I do in my own projects. I have a main stack and each state can have its own sub stack if it needs to. And each state can optionally choose to pause both their update and draw callbacks individually. Of course I write it myself. It really is a great idea. Makes doing dialogs and other things so much easier. Each state has a focus and blur callback and I can have the state continue to update in the background but check to make sure it's actually focused in order to do certain things or forego certain things when it's in the background.

I even wrote it so I can unload one state and swap it with another, like for example, unload the title state and switch to the game state, the game state which would then include its own stack for each of the separate game states (Level, map, cutscene) and the main game state would store all the global game related data like score and lives and other stuff so I'm not constantly transferring it between states.

And each state can send arguments into newly pushed states which can then return arguments back into the previous states focus callback. (Like returning whether the user selected Yes or No in a dialog, etc...)

Everyone should use state stack managers in their game. It just makes things so much easier. Combined with animation, tweening and timer libraries and you can do some really good stuff super easily. (At the risk of going off topic I apologize in advance for showing off what I had planned on making a whole topic for months ago. Sorry I'll be ruining the funny visual jokes I sprinkled in.)


Everything is a new state. The inventory is a state. When a confirmation dialog pops up it's another state over that. Everything is a state if it needs to take focus from something else temporarily.

I put way too much work into that inventory system. And it's still not complete.

The reason I named him Jon Snow is because I was going to have it when he first started the game with no spells it would say "Jon Snow knows nothing" in the spells list.

Re: [Library] st8.lua

Posted: Tue Mar 31, 2015 6:19 am
by ivan
Hey, I have something similar in my code,
although I have to point out someting about stacks in general:
when you represent "sub-stacks" as tables then you have
a structure that looks more like a 'tree' rather than a stack.
Tree-like example:

Code: Select all

{
  {
    splash_animation,
    play_sound
  },
  start_game
}
What I mean is, sub-stacks could easily be implemented by
pushing each sub-item on the stack followed by the number of items.
Flat stack example:

Code: Select all

{
  splash_animation,
  play_sound,
  2, -- last two elements are a "sub-stack"
  start_game
}
To pop the sub-stack you can just do something like:

Code: Select all

function pop_substack()
  -- pop the top
  local top = table.remove(stack)
  -- is it a sub-stack?
  if type(top) == "number" then
    -- pop N items
    for i = 1, top do
      pop_substack()
    end
  end
end

Re: [Library] st8.lua

Posted: Tue Mar 31, 2015 9:51 am
by s-ol
ivan wrote:Hey, I have something similar in my code,
although I have to point out someting about stacks in general:
when you represent "sub-stacks" as tables then you have
a structure that looks more like a 'tree' rather than a stack.
-snip-
Well, it is kinda like a tree, but it has a fixed depth, which makes it very much unlike a tree :D
There only is one primary Stack and it only contains secondary Stacks who in turn only contain Leaves (States).

And why would I come up with such a complicated and weird way to store a tree? I even doubt that it's faster than nesting tables.

Re: [Library] st8.lua

Posted: Tue Mar 31, 2015 11:18 am
by Doctory
@Jasoco (too lazy to quote)
that is so cooool
im gonna go make a small rpg now

Re: [Library] st8.lua

Posted: Tue Mar 31, 2015 7:50 pm
by T-Bone
I don't want to get too off-topic here, but Jasoco, you really need to make a complete game. Your talents are mind-blowing.