-
Notifications
You must be signed in to change notification settings - Fork 0
Input
Every input source in texastoast has the same two methods, poll() and
is_pressed(), so a game can swap keyboard for hardware without changing.
poll() returns an InputState — eight booleans and two derived axes:
state = keyboard.poll()
state.up, state.down, state.left, state.right
state.a, state.b, state.start, state.select
state.dx # -1.0, 0.0 or 1.0
state.dy # -1.0, 0.0 or 1.0
state.is_any_direction()Opposite directions cancel: holding left and right gives dx == 0.0.
dx/dy are raw axis reads and are not normalized — a diagonal has
magnitude 1.41, not 1. Entity.move normalizes for you. If you integrate
position yourself, do it too:
import math
dx, dy = state.dx, state.dy
mag = math.hypot(dx, dy)
if mag > 1.0:
dx, dy = dx / mag, dy / mag
x += dx * speed * dt
y += dy * speed * dtfrom texastoast import KeyboardInput
keyboard = KeyboardInput(game.root)
game.on_close(keyboard.destroy) # release the bindings on exit| Button | Keys |
|---|---|
| up / down / left / right | Arrow keys, WASD |
| a | Z, Enter |
| b | X, Backspace |
| start | Escape, P |
| select | Shift |
KeyboardInput binds on construction and tracks state until told otherwise. It
is a state source, not an event source: poll() tells you what is held right
now. For one-shot actions — confirming a menu, advancing dialogue — bind a key
event instead, because polling will fire on every frame the key is down:
def on_key(event):
if event.keysym in ("z", "Return"):
dialogue.dismiss()
game.bind_key("<Key>", on_key)destroy() removes every binding and clears the state. It is idempotent.
Prefers hardware when it is actually responding, and falls back to the keyboard otherwise:
from texastoast.input.magma_hub import CompositeInput, MagmaHubInput
controls = CompositeInput(keyboard, MagmaHubInput(hub))
state = controls.poll()
controls.active_source # "magma_hub", "keyboard" or "none"Either argument may be None. With neither, poll() returns an idle state
rather than raising.
The fallback is decided per call by hub.connected, so unplugging the hardware
returns control to the keyboard on the next poll — provided something is
polling the hub, since connected reflects the last poll's outcome. A
HubPoller keeps that true without the
game having to poll on its own thread.
In 0.1.x a hub on a dead or mock bus reported itself connected, so
CompositeInputlatched onto it and keyboard input stopped working altogether. See Magma Hub and I2C.
Added in 0.4.0. InputRecorder wraps any source and writes every change to a
.ttrec file; ReplayInput plays one back as a source in its own right.
from texastoast import InputRecorder, ReplayInput
recorder = InputRecorder(controls, "session.ttrec")
recorder.start()
game.on_close(recorder.stop)
replay = ReplayInput("session.ttrec")
replay.advance(dt) # deterministic manual clock, for tests
replay.poll() # -> InputStateBecause the recorder is transparent — it delegates poll() and is_pressed()
to the source it wraps — you can leave it in the chain and the game behaves
exactly as before.
See Hardware Dev Kit for the file format and for replaying a session through the full I2C stack.
Anything with poll() and is_pressed() works — there is no base class to
inherit. InputSource in texastoast.input.abstract is a typing.Protocol
you can use for type checking:
from texastoast import InputState
class AutopilotInput:
"""Walks right for two seconds, then stops."""
def __init__(self):
self._t = 0.0
self._state = InputState()
def tick(self, dt):
self._t += dt
self._state = InputState(right=self._t < 2.0)
def poll(self):
return self._state
def is_pressed(self, button):
return getattr(self._state, button, False)Two sources ship with the engine and are worth reaching for before writing your
own: ReplayInput above, and MagmaHubInput wrapping a
HubPoller.
For multi-controller games, PlayerManager (0.5.0) assigns sources to seats
with join-by-press and hotplug handling — and each Player is itself an
InputSource, so everything on this page applies to a seat unchanged. See
Players and Multi-Controller.
texastoast · PyPI · Apache-2.0