Skip to content

Add per-axis deadzone configuration API #72

@lunarcloud

Description

@lunarcloud

Feature Request

Allow developers to set deadzone values for each player/axis at runtime, rather than baking them into AxisAsButton definitions.

Current Limitation

Deadzones are hardcoded in axis definitions:

// src/axis-as-button.js
constructor (direction, axisNum, max = 1, deadZone = 0.25) {
    // ❌ Deadzone is set at model definition time
    this.deadZone = direction === '+' ? deadZone : -deadZone
}

Users cannot adjust sensitivity per-player or at runtime.

Proposed API

// Get player
const player = gameInput.getPlayer(0)

// Set deadzone for entire stick
player.setDeadzone('leftStick', 0.15)

// Set deadzone for individual axis
player.setDeadzone('leftStick.x', 0.2)
player.setDeadzone('leftStick.y', 0.1)

// Get current deadzone
const dz = player.getDeadzone('leftStick')  // Returns 0.15

// Reset to default
player.resetDeadzone('leftStick')

Advanced Options

// Different deadzone shapes
player.setDeadzone('leftStick', {
    threshold: 0.15,
    shape: 'radial'  // or 'axial', 'cross'
})

// Per-player defaults
gameInput.setDefaultDeadzone(0.2)  // All players, all axes

// Save/load user preferences
const prefs = player.getDeadzonePreferences()
localStorage.setItem('deadzones', JSON.stringify(prefs))

Implementation Approach

  1. Add deadzone property to GameInputPlayer
  2. Store per-axis overrides in player state
  3. Apply runtime deadzones in update loop
  4. Maintain backward compatibility with model-defined deadzones

Use Cases

  • Accessibility: Users with motor impairments need custom deadzones
  • Worn controllers: Older controllers with stick drift need larger deadzones
  • Precision gaming: Competitive players want minimal deadzones
  • Per-game settings: Different games need different sensitivities

Example: Settings Menu

// In-game deadzone calibration
function showDeadzoneSettings(playerIndex) {
    const player = gameInput.getPlayer(playerIndex)
    
    slider.oninput = (e) => {
        const value = e.target.value / 100  // 0.0 to 1.0
        player.setDeadzone('leftStick', value)
        updatePreview()
    }
}

Backward Compatibility

  • Default to model-defined deadzones if not overridden
  • Runtime overrides are optional
  • No breaking changes to existing API

Metadata

Metadata

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions