# GamepadMapper - Advanced Gamepad Input Handling ## Overview The GamepadMapper class provides a comprehensive solution to address the shortcomings of the vanilla Web Gamepad API, including: - **Stick Drift Compensation**: Configurable deadzones with proper scaling - **Button Debouncing**: Prevents multiple rapid button press events - **Controller Mapping**: Standardized button/axis names across different controller types - **Event-Driven API**: Replaces inefficient polling with proper event handling - **Analog Trigger Support**: Handles controllers that map triggers to buttons vs axes - **Vibration Feedback**: Haptic feedback support where available ## Supported Controllers - **Xbox Controllers** (Xbox One, Xbox Series X/S, Xbox 360) - **PlayStation Controllers** (DualShock 4, DualSense) - **Nintendo Switch Pro Controller** - **Generic controllers** using standard mapping ## Key Features ### Deadzone Handling ```javascript // Configurable deadzone (default: 0.1) const mapper = new GamepadMapper({ deadzone: 0.15 }); // Values below deadzone threshold return 0 // Values above are scaled to maintain full 0-1 range ``` ### Button Debouncing ```javascript // Configurable debounce time (default: 50ms) const mapper = new GamepadMapper({ debounceTime: 30 }); // Prevents multiple rapid button events from hardware bounce ``` ### Event-Driven API ```javascript // Listen for button events mapper.on('buttondown', (data) => { console.log(`Button ${data.button} pressed on gamepad ${data.gamepadIndex}`); }); mapper.on('buttonup', (data) => { console.log(`Button ${data.button} released on gamepad ${data.gamepadIndex}`); }); // Listen for analog stick/trigger changes mapper.on('axischange', (data) => { console.log(`Axis ${data.axis}: ${data.value} (raw: ${data.rawValue})`); }); ``` ### Standardized Button Names | Xbox | PlayStation | Nintendo | Standard Name | | ---- | ----------- | -------- | ------------- | | A | X (Cross) | B | A | | B | Circle | A | B | | X | Square | Y | X | | Y | Triangle | X | Y | | LB | L1 | L | LB | | RB | R1 | R | RB | | LT | L2 | ZL | LT | | RT | R2 | ZR | RT | ### Standardized Axis Names - `LEFT_STICK_X` / `LEFT_STICK_Y` - `RIGHT_STICK_X` / `RIGHT_STICK_Y` - `LEFT_TRIGGER` / `RIGHT_TRIGGER` (for analog triggers) ## Usage Example ```javascript import { GamepadMapper } from './gamepad-mapper.js'; const gamepadMapper = new GamepadMapper({ deadzone: 0.15, // 15% deadzone debounceTime: 30, // 30ms debounce enableVibration: true // Enable haptic feedback }); // Handle button presses gamepadMapper.on('buttondown', (data) => { if (data.button === 'A') { // Play note, trigger action, etc. gamepadMapper.vibrate(data.gamepadIndex, 100, 0.3, 0.1); } }); // Handle analog input gamepadMapper.on('axischange', (data) => { if (data.axis === 'LEFT_STICK_X') { // Update frequency, position, etc. updateFrequency(data.value); } }); ``` ## Configuration Options ```javascript const options = { deadzone: 0.1, // Stick deadzone (0-1) debounceTime: 50, // Button debounce time (ms) pollRate: 60, // Polling rate (fps) enableVibration: false // Enable vibration support }; ``` ## Benefits Over Vanilla API 1. **No Stick Drift**: Automatic deadzone compensation eliminates unwanted input 2. **Clean Button Events**: Debouncing prevents multiple rapid button presses 3. **Consistent Mapping**: Same button names work across all controller types 4. **Better Performance**: Event-driven approach reduces CPU usage 5. **Enhanced Features**: Vibration support and analog trigger detection 6. **Easier Integration**: Simple event-based API vs complex polling logic ## Implementation Notes - Automatically detects controller type on connection - Handles analog triggers mapped to either buttons or axes - Scales deadzone-compensated values to maintain full range - Cleans up resources properly on disconnect - Supports multiple simultaneous controllers