Veduta

Input

The console has a D-pad, A, B, Select, Cancel and Home. A game sees the first eight; Home is the console's and never reaches the game: pressed, it opens the console's overlay (clock, friends, chat) while the game keeps running; held for a second, it leaves the game.

ButtonName in Lua and scenariosMeant for
D-pad"up", "down", "left", "right"moving, choosing
A"a"the main action, confirm
B"b"the second action (jump, run, shoot)
Select"select"the game's menu, pause
Cancel"cancel"back, close a menu

Reading buttons

FunctionTrue when
input.down(b)the button is held this tick
input.pressed(b)it went down this tick
input.released(b)it went up this tick
input.dpad()returns x, y: x is −1 (left), 0 or 1 (right), y is −1 (down), 0 or 1 (up)
input.repeated(b [, delay [, rate]])it went down this tick, then again every rate seconds (0.1) once held for delay (0.3): a cursor
input.held(b)returns how long it has been held, in seconds (0 when up): a charge
kinds.ship = {
  update = function(e)
    local dx, dy = input.dpad()
    e:move(dx * 6 * engine.dt, dy * 6 * engine.dt, 0)
    if input.pressed("a") then
      scene.spawn{kind = "shot", model = "quad", material = "shot",
        position = {e.x, e.y + 0.5, 1}, scale = {0.2, 0.4, 1}, tags = {"shot"}}
    end
    e.state.charging = input.down("b")
  end,
}

Use pressed for actions that happen once per press (jump, shoot, confirm) and down for actions that last while the button is held (run, charge). Opposite D-pad directions held together cancel out; a diagonal is (±1, ±1), so normalise it if diagonal movement must not be faster.

kinds.archer = {
  update = function(e)
    if input.released("b") then
      trace("shot", {power = e.state.charge})       -- the charge of the last tick held
    end
    e.state.charge = math.min(input.held("b"), 1)  -- 0 to 1 over a second held
  end,
}

Input is read once per tick. A button pressed and released within one tick still shows in pressed and released, but not in down.

On the PC

The simulator maps the console's buttons to the keyboard, and any gamepad works too:

ConsoleKeyboardGamepad
D-padarrows, or W A S DD-pad (or the stick, on a pad whose D-pad is not four buttons)
ASpace or ZA
BX or ShiftB
SelectEnter or TabStart
CancelEscape or BackspaceSelect
HomeHome (Ctrl+Q leaves at once)Home, or Select and Start together

A gamepad's Start is the game's menu and its Select is Cancel; a pad with no Home button has Home on Select and Start pressed together. In the simulator there is no overlay, so Home leaves the game.

ui.menu is a menu that reads the buttons itself: up and down move the cursor (repeating when held, through input.repeated), skipping disabled items, A chooses, B or Cancel cancels.

local menu = ui.menu{"RESUME", "RESTART", "QUIT", title = "PAUSED"}

screen.add("pause", {
  update = function()
    local i, item = menu:update()
    if i == 1 or item == "cancel" or input.pressed("select") then
      screen.pop()
    elseif i == 2 then
      screen.pop()
      scene.load(scene.name())
    elseif i == 3 then
      screen.go("title")
    end
  end,
  draw = function() menu:draw() end,
})

function game.update()
  if input.pressed("select") then screen.push("pause") end
end

A screen pushed over the game stops its kinds, bodies and timers until it is popped: the game pauses behind the menu without a check in every kind. See Game Toolkit.

Dialogs take the buttons

While a ui.dialog is open, while scene.load(name, {fade = ...}) fades, and on the tick a dialog closes, every input function reads as nothing (false, 0): A that closes a dialog does not also make the hero jump. ui.busy() tells when this is so.

In tests

Scenarios press and release the same button names at given ticks (see Testing). Home cannot be pressed by a scenario, since no game ever sees it.

Veduta (Lua games). This wiki is built from wiki/ in the engine's repository, where its examples are tested, and published with every engine release on https://veduta.roomve.it/docs/.