demo · v147 · gamepad · input

Game Input Recorder

Record, visualise, and replay gamepad input sessions. Use the simulation buttons to trigger button and axis events without a physical gamepad. Compare polling vs event-driven input counts over 5 seconds.

Connect a gamepad and press any button, or use the simulation buttons below to inject synthetic events. The recorder captures every input with its timestamp. Playback replays with matching timing. Chrome 147+ uses rawgamepadinputchange; older browsers fall back to requestAnimationFrame polling.
idle

Simulate gamepad input (no physical gamepad needed):

Input timeline (each tick = one recorded event)
total events: 0  |  duration: 0s  |  events/sec: 0  |  mode:

Compare: polling vs event-driven (5 second run)

Both approaches run simultaneously for 5 seconds. Polling fires every rAF frame (max 60/sec). Event-driven fires only on actual input changes.

rAF polling calls
0
0 callbacks
event-driven callbacks
0
0 events

recording model

const recording = [];
const startTime  = performance.now();

// Chrome 147: event fires immediately on hardware input
window.addEventListener('rawgamepadinputchange', e => {
  recording.push({
    t:       performance.now() - startTime,
    type:    'rawgamepadinputchange',
    buttons: e.gamepad.buttons.map(b => ({ pressed: b.pressed, value: b.value })),
    axes:    Array.from(e.gamepad.axes),
  });
});

// Playback: replay with original timing
for (const evt of recording) {
  setTimeout(() => applyState(evt), evt.t);
}

see also

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗