GAMEPAD_MAPPING.md 4.2 KB

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

// 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

// Configurable debounce time (default: 50ms)
const mapper = new GamepadMapper({ debounceTime: 30 });

// Prevents multiple rapid button events from hardware bounce

Event-Driven API

// 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

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

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