Friday, May 15, 2020

Love2D - Simple event stacks with Lua

Love2D and its 3D/VR companion LOVR are great. I won't blab about how awesome they are - though having an entirely open framework means certain things must be built from scratch. One such thing is an event handling system.

Engines like Unity use a class inheritance to handle this. Every object in a scene is a GameObject, which has an inherited update method to process itself every frame.

It's possible to do this without much trouble by architecting all of your game entities in a similarly OOP way, but this isn't always intuitive, and can cause unnecessary headache and overhead if your game isn't overly complex, or you want more manual control over your event stacks.

Here's a super simple event stack example using anonymous functions and an event stack table (named 'queue'):

table.insert(queue, function() <code> end)

The most frequent use would likely be to add a global wait in between code blocks:

table.insert(queue, function() wait = 1 end)

This also makes calling functions with parameters and so forth very simple:

table.insert(queue, function() 
        sfx:play()
        ComplexFunction(a, 'b', { c = 0 }) 
    end)

Then in update:

love.update(TimeDelta)
    if wait > 0 then
        wait = wait - TimeDelta
        love.draw() -- Continue to draw, but don't process stack
        return
    end
    if #queue > 0 then
        if type(queue[1])=='function' then
            local f = queue[1]
            table.remove(queue, 1)
            f()
        end
    end
end

This code is the basis for most of the animation in my game, or when there needs to be a timed wait e.g. to suspend input tracked by variable named inputEnabled for one second:

function q(o) table.insert(queue, o) end
function setinput(tf) inputEnabled = tf end
q(function() setinput(false) end)
q(function() wait = 1 end)
q(function() setinput(true) end)

Lua allows lots of room for freedom in styling your code however you wish.