Luawe the Wayfarer Engine's scripting language All pages

Events

An event is something that happens: the cube touches a thing, a beat of the song comes, a key goes down. Instead of asking over and over whether it has happened yet, a script says what should be done when it does.

Two ways to use an event

Connect a function to it. Every time the event happens, the function runs, as a task of its own:

local coin = things.find("coin")

coin.touched:connect(function()
    sound.play("@coin")
    coin.visible = false
end)

Or wait for it. The script pauses on that line until the event happens, once:

local button = things.find("button")
button.touched:wait()
print("the button was pressed")

Connect is for "whenever this happens". Wait is for "then, after this has happened", and it keeps a script that tells a story in the order it is read.

Many events carry values with them, which the connected function gets as its parameters, and which wait gives back:

input.keyDown:connect(function(key)
    print("pressed " .. key)
end)

local beat = level.beat:wait()
print("the next beat was number " .. beat)

The game's events

EventHappensCarries
thing.touchedWhen the cube starts to touch the thing
thing.untouchedWhen it stops touching it
level.beatOn every beat of the songThe beat's number
level.stepAt every step of the level, 48 times a beatThe seconds since the last step
player.hurtWhen the cube touches something that would kill it
input.keyDown, input.keyUpWhen a key goes down, comes upThe key's name
input.mouseDown, input.mouseUpWhen a mouse button goes down, comes up"left", "right" or "middle"
input.wheelWhen the mouse wheel turnsHow far (up is more than 0)
input.mouseMoveIn every step in which the mouse moved the cubeHow far it went: across and down, in tiles

And thing:tween(...) gives back an event that happens when the glide has arrived.

Taking a connection off again

connect gives back a connection. Disconnect it and the function is not called any more:

local taps = 0
local link

link = input.keyDown:connect(function(key)
    if key ~= "space" then
        return
    end
    taps += 1
    if taps == 3 then
        link:disconnect() -- three were enough
        print("three taps")
    end
end)

link.connected tells whether it is still on. For "the next time only" there is once, which takes itself off after one call:

player.hurt:once(function()
    print("first blood")
end)

Events of your own

signal.new() makes an event. It has the same connect, once and wait as the game's events, and one thing more: fire, which makes it happen, with whatever values you give it.

local scored = signal.new()

scored:connect(function(points)
    print("scored " .. points)
end)

scored:fire(10)
scored:fire(25)
wait()

It prints

scored 10
scored 25

Your own events are how the parts of a bigger script stay apart. One part says "a point was scored" and knows nothing of who listens; another part updates the text, a third plays a sound. They are also how scripts talk to each other.

A script that waits for events is not finished

A script whose last line has been reached is done. But the functions it connected stay connected, and its tasks keep running, for as long as the level is played. A script can therefore be nothing but a few connect lines:

level.beat:connect(function(beat)
    if beat % 8 == 0 then
        camera:effect("pulse", 0.4, 0.3)
    end
end)

Next: scripts working together.