Veduta

Input

The console has a D-pad, A, B, Select, Cancel and Home. A game sees the first eight; Home always returns to the console's menu and never reaches 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 Backspacenone
HomeCtrl+QHome, or Select

A gamepad's Select leaves the game, as Home does, and its Start is the game's menu. A gamepad has no Cancel, so a menu should close with Select (Start on the pad) or B as well.

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 v2 (Lua games, release candidates). 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/.