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
| Event | Happens | Carries |
|---|---|---|
thing.touched | When the cube starts to touch the thing | |
thing.untouched | When it stops touching it | |
level.beat | On every beat of the song | The beat's number |
level.step | At every step of the level, 48 times a beat | The seconds since the last step |
player.hurt | When the cube touches something that would kill it | |
input.keyDown, input.keyUp | When a key goes down, comes up | The key's name |
input.mouseDown, input.mouseUp | When a mouse button goes down, comes up | "left", "right" or "middle" |
input.wheel | When the mouse wheel turns | How far (up is more than 0) |
input.mouseMove | In every step in which the mouse moved the cube | How 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 25Your 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.