Repository navigation
feat: gamepad input - #12
Merged
Merged
Conversation
g.PadDown(b PadButton) reports a button held on any connected gamepad with a standard layout (Xbox, PlayStation, Switch Pro, Steam Deck and most others, by position). The constants cover the whole layout: PadA, PadB, PadX, PadY, PadLB, PadRB, PadLT and PadRT (triggers pulled), PadBack, PadStart, PadLStick, PadRStick, and the d-pad PadUp, PadDown, PadLeft, PadRight. g.PadAxis(a PadAxis) reads PadLeftX, PadLeftY, PadRightX or PadRightY, raw -1..1 with Y growing downward and no dead zone; with several pads, the one pushed furthest answers. g.PadConnected() lets a game switch its on-screen prompts. PadButton and PadAxis alias Ebitengine's standard layout types, the same way Key aliases ebiten.Key, so there is no translation table. Pads without a standard mapping are ignored. The device reads are swappable package variables, like the pointer ones, so tests fake controllers. Agents hold pad buttons with Action.Pad and push the left stick with Action.StickX/StickY (clamped to -1..1, NaN centers); over MCP, act takes "pad" (button names A, B, ..., Start, Up, Down, Left, Right) and "stickX"/"stickY", and unknown names error with the valid list. An agent's pad connects with the first action that uses it and stays connected for the run, so prompts do not flicker. Headless play never reads real controllers. Windowed MCP merges the agent's pad with the real ones. Horde proves it: the d-pad or the left stick walks (analog speed past a 0.2 dead zone), Start pauses and resumes, A resumes and B gives up in the pause overlay, A starts AGAIN after a loss, and the menu labels switch to pad prompts while a pad is connected.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
g.PadDown(b PadButton) bool: is a button held on any connected gamepad with a standard layout?g.PadAxis(a PadAxis) float64: a stick axis, raw -1..1, Y down, no dead zone; with several pads the one pushed furthest answers.g.PadConnected() bool: is a standard-layout gamepad connected? For switching on-screen prompts.PadA,PadB,PadX,PadY,PadLB,PadRB,PadLT,PadRT,PadBack,PadStart,PadLStick,PadRStick,PadUp,PadDown,PadLeft,PadRight; axesPadLeftX,PadLeftY,PadRightX,PadRightY.Action.Pad []PadButton,Action.StickX,Action.StickY; MCP act gainspad(button names),stickX,stickY.Design
Key.PadButton = ebiten.StandardGamepadButtonandPadAxis = ebiten.StandardGamepadAxis, exactly howKey = ebiten.Keyworks: no translation table, and the constants read like the rest of the input API (engine.PadAnext toengine.Esc).PadConnected. A pad without one has no known button meaning, so reading it would be guesswork. Buttons map by position:PadAis the bottom face button (Cross on PlayStation, B on Nintendo).PadDownORs every standard pad;PadAxistakes the value with the largest magnitude, so a second idle controller (or a slightly drifting one) never cancels the one in use. Local multiplayer with per-pad reads is left for later; nothing here blocks adding it.PadLT/PadRTreport "pulled" by the standard layout's threshold. The standard layout itself models triggers as buttons; analog trigger values can be added later as more axes without breaking anything. Kept out to keep the surface small.hero.Move(x*speed, y*speed)just works.AppendGamepadIDs,IsStandardGamepadLayoutAvailable,IsStandardGamepadButtonPressed,StandardGamepadAxisValue) are swappable package vars, like PR feat: held pointer and window focus: MouseDown and Focused #6's pointer ones. The ID list reuses one slice, so reading pads allocates nothing per frame.Action.Padholds buttons for the frame;StickX/StickYset the left stick, clamped to -1..1 (NaN centers). Agents get only the left stick, mirroring how they get one pointer; aiming stays with keys or the mouse. The agent's pad "connects" on the first action that uses it and stays connected for the run (Headlessstarts a new run with none): a game that shows pad prompts, or pauses on pad disconnect, must not flicker as the agent lets go of the stick. Headless play never reads real controllers (it uses injected input only), so without pad actions there is no pad. Windowed MCP (mixedInput) ORs agent and real buttons, and the agent's stick answers while pushed, else the real pads.pad: ["A", "Start", ...](the constant names withoutPad) andstickX/stickY; unknown names error listing the valid ones, like keys. The act argument parsing moved intog.actArgsso it is unit tested.Proof
pad_test.go: fake controllers (a non-standard pad is ignored; a button held on either of two pads counts; axes take the pad pushed furthest and stay raw, 0.04 stays 0.04);mixedInputmerges agent and real pads; headless Step with pad actions (no pad before first use, stick clamped, NaN centered, connected for the rest of the run, fresh onHeadless, and real hardware held down never leaks into headless);actArgsparsespad/stickX/stickYand errors on unknown or non-string names; the help text lists exactly the accepted names.examples/horde: d-pad or left stick walks (analog speed past a 0.2 radial dead zone), Start pauses and resumes, in the pause overlay A resumes and B gives up, A starts AGAIN on game over, and the labels switch to "A RESUME" / "B GIVE UP" / "A AGAIN" while a pad is connected. The key edge detector now takes any "held" func so keys and pad buttons share it.COLLIDER_AGENT=mcp):stickX: 1for 60 frames moves the hero 210 px (full speed);pad: ["Start"]opens the pause overlay with "A RESUME" / "B GIVE UP";Acloses it;StartthenBgoes to game over showing "A AGAIN";Arestarts;pad: ["Jump"]errors listing the names.