agentleFS
wolffewolffe/three.js-skills/skills/character/character-input/SKILL.md

character-input

Skill4 starsChanged 15 days agoMITView on GitHub

Keyboard actions and pointer look for a character controller in the browser: rebindable action map, edge-triggered presses, drag or pointer-lock look deltas, right-button turn, wheel steps. Use when wiring WASD/jump/crouch/sprint and mouse look into any Three.js scene. Ships character-input.js.

The file

Files
SKILL.md

Character input

Target: browser DOM events; no framework. scripts/character-input.js exports createCharacterInput(canvas, opts) and defaultActions().

Actions, not keys

Code asks for actions (moveForward, jump, crouch, sprint, interact...), never key codes. The action map is a plain mutable object of action → [KeyboardEvent.code]; rebind by assigning input.actions.jump = ['KeyJ']. Defaults:

ActionCodes
moveForward / moveBack / moveLeft / moveRightW A S D and the arrows
jumpSpace
sprintShiftLeft, ShiftRight
crouchKeyC
interact / useKeyE
secondary / carryKeyF
tertiary / stowKeyG

getMove() returns { x, z } in −1/0/1 (x right, z back, so forward is −z, matching camera space). It is a shared object; read it before the next call.

Held versus pressed

  • isAction(name) is true while any bound key is down.
  • wasPressed(name) is true for exactly one frame after the key went down, ignoring auto-repeat. Jump, interact and view toggles use this.

Presses are cleared at the end of the frame, not when read, so several systems can see the same press. Call input.endFrame() after all updates in your loop (or pass an onLateUpdate hook in opts if the host loop has one).

Look

Two modes, switchable at runtime with setLookMode('drag' | 'capture'):

  • drag: left button held and dragged on the canvas moves the look. Works everywhere, including iframes and embedded previews.
  • capture: pointer lock on click; raw movementX/Y. Can be refused by the browser; the request is made with .catch and nothing waits on it. Esc releases.

consumeMouseDelta() returns { dx, dy } in pixels accumulated since the last call and zeroes it. Consume exactly once per frame in the camera update.

The right button gives a separate consumeTurnDelta() for rotating a held object or similar, so it never fights the look.

consumeWheel() returns the signed count of wheel notches since the last call (zoom steps).

Hygiene

  • Keys typed in inputs, textareas, selects and contenteditable elements are ignored.
  • Space and the arrows call preventDefault so the page does not scroll.
  • blur resets everything held, so a key does not stay down after alt-tab.
  • The context menu is suppressed on the canvas (right button is a control).
  • dispose() removes every listener.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.