Skip to content

Conversation

Copy link

Copilot AI commented Oct 9, 2025

Overview

This PR completely overhauls Gamepad.js to provide a fully automated, production-ready gamepad library. All controllers now work automatically on first connection with zero user configuration required.

What Changed

🎮 Automatic Controller Detection

The library now automatically detects what type of controller is connected by analyzing the gamepad ID string. When a controller connects, it:

  • Identifies the controller type (Switch, Xbox, PlayStation, GameCube, or Generic)
  • Automatically applies the correct button and axis mapping
  • Dispatches a controllerConnected event with the detected type and mapping

Supported controllers include:

  • Nintendo Switch (Joy-Con, Pro Controller)
  • Xbox (360, One, Series X/S with XInput)
  • PlayStation (DualShock 3/4, DualSense/PS5)
  • GameCube (including Mayflash adapters)
  • Generic/Standard gamepads (fallback)
// Controllers are detected automatically on connection
window.addEventListener('controllerConnected', (e) => {
    console.log(`Detected: ${e.detail.controllerType}`);
    console.log('Button mapping:', e.detail.mapping);
});

📊 Complete Axis Mapping

All controller configurations now include comprehensive axis mapping with named constants:

axes: {
    LEFT_STICK_X: 0,
    LEFT_STICK_Y: 1,
    RIGHT_STICK_X: 2,
    RIGHT_STICK_Y: 3
}

Features include:

  • Configurable deadzone (default: 0.2) to ignore stick drift
  • Change detection threshold to prevent event spam
  • Separate axis event type with actual axis values

🎚️ Pressure-Sensitive Button Support

GameCube controllers (and other controllers with analog triggers) now properly expose pressure values:

window.addEventListener('controllerInput', (e) => {
    if (e.detail.type === 'button' && e.detail.pressure !== null) {
        console.log(`Pressure: ${e.detail.pressure.toFixed(2)}`);
    }
});

The system uses the button.value property to read pressure (0.0 to 1.0) for designated analog buttons.

⚡ Improved Event System with State Tracking

The previous implementation fired events continuously while buttons were held or axes were moved. The new system:

  • Tracks previous state for all buttons and axes
  • Only fires events when state actually changes
  • Prevents duplicate events and reduces CPU usage
  • Provides cleaner, more predictable behavior

Before:

// Fired continuously while button held
controllerButton: { controller: 5, action: "button", index: 0 }
controllerButton: { controller: 5, action: "button", index: 0 }
controllerButton: { controller: 5, action: "button", index: 0 }
...

After:

// Fires only on press and release
controllerInput: { type: "button", buttonIndex: 5, value: 1, ... }  // pressed
controllerInput: { type: "button", buttonIndex: 5, value: 0, ... }  // released

🧹 Fixed Array Cleanup on Disconnect

The connected_Gamepads array now properly removes trailing nulls when controllers disconnect:

document.addEventListener("gamepaddisconnected", function(e) {
    connected_Gamepads[e.gamepad.index] = null;
    gamepadStates[e.gamepad.index] = null;
    
    // Remove trailing nulls from both arrays
    while (connected_Gamepads.length > 0 && connected_Gamepads[connected_Gamepads.length - 1] === null) {
        connected_Gamepads.pop();
    }
    while (gamepadStates.length > 0 && gamepadStates[gamepadStates.length - 1] === null) {
        gamepadStates.pop();
    }
});

📚 Comprehensive Documentation

  • README.md - Completely rewritten with features, usage examples, and API documentation
  • example.html - New interactive demo page showing real-time events
  • IMPROVEMENTS.md - Technical documentation and migration guide

Screenshots

Interactive Example Page

Example page showing controller detection and event logging

The new example page demonstrates:

  • Real-time controller connection status
  • Automatic controller type detection
  • Color-coded event logging
  • Button press and axis movement tracking

GamepadAPI Test Page

Test page for debugging controller input

Breaking Changes

The event structure has been redesigned for better functionality:

Old API:

window.addEventListener('controllerButton', (e) => {
    console.log(e.detail.controller, e.detail.action, e.detail.index);
});

New API:

window.addEventListener('controllerInput', (e) => {
    if (e.detail.type === 'button') {
        console.log(`Button ${e.detail.buttonIndex}: ${e.detail.value}`);
    } else if (e.detail.type === 'axis') {
        console.log(`Axis ${e.detail.axisIndex}: ${e.detail.value}`);
    }
});

See IMPROVEMENTS.md for complete migration guide.

Note on Wii Remote Support

Wii Remote (Wiimote) support cannot be implemented in web browsers due to fundamental security restrictions. The Gamepad API only supports controllers recognized by the operating system as standard HID devices. Wiimotes use a proprietary Bluetooth protocol that browsers cannot access. This limitation is documented in the README with suggested workarounds (hardware adapters, Electron apps, etc.).

Testing

  • ✅ Controller detection validated with 10+ test cases
  • ✅ JavaScript syntax validation passed
  • ✅ Example pages load and function correctly
  • ✅ Event system verified with state tracking tests

Files Changed

  • gamepad.js - Core library (102 → 304 lines)
  • README.md - Complete documentation rewrite
  • example.html - New interactive demonstration page (160 lines)
  • IMPROVEMENTS.md - Technical documentation (195 lines)

Total: 669 insertions, 51 deletions


This PR resolves the issue by implementing all actionable features. The script is now production-ready with true plug-and-play functionality.

Original prompt

This section details on the original issue you should resolve

<issue_title>The Script is weakly built and missing features.</issue_title>
<issue_description>There are some features that I want to add, but either never included them, or never completely finished writing it in my code. Here are somethings I want to work on:

  • Add a feature that figures out what controller you are using, and pairs it with the proper button mapping.
  • Add Axis mapping and axis detection.
  • Add a feature I've only ever seen with Nintendo Gamecube controllers that allow you to use pressure buttons.
  • Look for a better way to detect Button presses and Axis detection.
  • In the event listener that listens for gamepad disconnections, make the example on the bottom of it's code actually work with connected_Gamepads if it removes the trailing nulls from arr.
  • If it is even possible in Javascript, add a feature that enables temporary Wii Remote (Wiimote for short) connections for the browser. I want to try to get this to work on Apple Computers since Apple changed their security settings that ends up blocking Wiimote connections.</issue_description>

<agent_instructions>Try to complete this so everything is automated so anyone can just connect their controller so it works on the first connection.</agent_instructions>

Comments on the Issue (you are @copilot in this section)

Fixes #2


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits October 9, 2025 20:53
…port, and improved event system

Co-authored-by: SuperGamer001 <183024988+SuperGamer001@users.noreply.github.com>
Co-authored-by: SuperGamer001 <183024988+SuperGamer001@users.noreply.github.com>
Co-authored-by: SuperGamer001 <183024988+SuperGamer001@users.noreply.github.com>
Copilot AI changed the title [WIP] Enhance gamepad controller features and mappings Implement automatic controller detection, axis mapping, pressure buttons, and improved event system Oct 9, 2025
Copilot AI requested a review from SuperGamer001 October 9, 2025 21:00
Copilot finished work on behalf of SuperGamer001 October 9, 2025 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The Script is weakly built and missing features.

2 participants