# input_device.ludic — the raw device layer from #50, on top of the action maps # and record/replay of #7. Beyond one key per frame, gameplay can read: # # * multiple simultaneous held keys — Input.key_down / key_pressed / key_released # * analog axes and vectors derived from keys — Input.axis / Input.vector # * the mouse — Input.mouse_x/y, mouse_dx/dy, mouse_down, wheel # * gamepads and touch — Input.pad_button/pad_axis, Input.touch_count/touch_x # # The held set is fed by the platform when windowed, and on every target by the # Input.press / Input.set_* injection (the same idea as Godot's action_press — # what a replay, an AI, or the network feeds). Everything is integer and # deterministic, and Input.record / replay snapshot the whole per-frame state, so # a recorded run reproduces exactly. Driven headless by injection, a full run: # bin/ludic examples/library/input_device.ludic -> 1 1 0 1 0 1 71 -71 5 1 3 1 2 1 0 0 1 program InputDevice { function bi(b: bool) -> int { if b { return 1 }; return 0 } function r(f: fixed) -> int { return Math.round(f) } entry { # --- multiple simultaneous held keys, with clean edges ------------------- Input.press('a') # hold left AND jump at once Input.press(' ') Input.poll() print(bi(Input.key_down('a'))) # 1 print(bi(Input.key_down(' '))) # 1 print(bi(Input.key_down('d'))) # 0 — not held print(bi(Input.key_pressed('a'))) # 1 — went down this frame Input.poll() print(bi(Input.key_pressed('a'))) # 0 — held, not a fresh press Input.release('a') Input.poll() print(bi(Input.key_released('a'))) # 1 — went up this frame # --- analog axis + a normalized 2D vector from four keys ----------------- Input.release(' ') Input.press('d') # right Input.press('w') # and up -> a diagonal Input.poll() let v = Input.vector('a', 'd', 'w', 's') print(r(Vector.x(v) * 100)) # 71 — 0.7071, normalized so diagonals aren't faster print(r(Vector.y(v) * 100)) # -71 # --- mouse: position, per-frame delta, buttons, wheel -------------------- Input.set_mouse(10, 20, 1, 3) # x, y, button-mask (left), wheel delta Input.poll() Input.set_mouse(15, 20, 1, 0) Input.poll() print(Input.mouse_dx()) # 5 — moved 10 -> 15 print(bi(Input.mouse_down(0))) # 1 — left button Input.set_mouse(15, 20, 0, 3) Input.poll() print(Input.wheel()) # 3 # --- gamepad + touch (injected; a native binding feeds the same state) --- Input.set_pad(0, true, 1, 1.0, 0.0, 0.0, 0.0) # pad 0: button 0 down, left stick x = 1.0 print(r(Input.pad_axis(0, 0))) # 1 Input.set_touch(0, 100, 200, true) Input.set_touch(1, 50, 60, true) print(Input.touch_count()) # 2 # --- full-state record / replay: the held set replays exactly ------------ Input.record() Input.press('a'); Input.release('d'); Input.release('w') Input.poll() # recorded frame 0: only 'a' held Input.release('a'); Input.press('d') Input.poll() # recorded frame 1: only 'd' held Input.replay() Input.poll() # replay frame 0 print(bi(Input.key_down('a'))) # 1 print(bi(Input.key_down('d'))) # 0 Input.poll() # replay frame 1 print(bi(Input.key_down('a'))) # 0 print(bi(Input.key_down('d'))) # 1 } }