Tutorials - AderitoSilva/XInputium GitHub Wiki

This page contains tutorials about how to implement common functionality related to gamepads on your application, using XInputium. Because different game or application frameworks use different means for performing the same tasks, the tutorials in this page will assume a generic fictional application framework, instead of using specific existing frameworks, unless specified otherwise.

How to determine if a device is connected

There are several ways to determine if a gamepad is currently connected to the system. When you're already using an XGamepad instance in your application, you can use its IsConnected property to determine if the underlying device is connected.

XGamepad gamepad = new();
gamepad.Update();  // You would usually be calling this on every frame.
Debug.WriteLine($"Is gamepad connected: {gamepad.IsConnected}");

Similarly, if you're using an XInputDevice instance, you can use its IsConnected property.

XInputDevice device = new(XInputUserIndex.One);
device.Update();  // You would usually be calling this on every frame.
Debug.WriteLine($"Is device connected: {device.IsConnected}");

The simplest way, when you're not using XGamepad or XInputDevice instances, is to use one of the XInputDevice's static methods:

Debug.WriteLine($"Is device connected: {XInputDevice.IsDeviceConnected(XInputUserIndex.One)}");

You can also enumerate through the user indexes of the devices that are currently connected to the system, by using XInputDevice.GetConnectedDeviceIndexes() static method:

foreach (var userIndex in XInputDevice.GetConnectedDeviceIndexes())
{
    Debug.WriteLine($"Device {userIndex} is connected.");
}

If you're using an XInputDeviceManager instance in your project, you can use it to get the connected devices, like so:

XInputDeviceManager deviceManager = new();
deviceManager.Update();  // You would usually call this on every frame.

foreach (var device in deviceManager.ConnectedDevices)
{
    Debug.WriteLine($"Device {device.UserIndex} is connected.");
}

// You could also access each device independently:
// ... = deviceManager.UserOne.IsConnected;
// ... = deviceManager.UserTwo.IsConnected;
// ... = deviceManager.UserThree.IsConnected;
// ... = deviceManager.UserFour.IsConnected;

How to switch to another connected device, when the current device gets disconnected

TODO

How to switch to a device when it gets any user input activity

TODO

How to get the current input state of a device

TODO

How to perform an action when a button is pressed

TODO

How to perform an action when a button is released

TODO

How to perform an action after a button is held for a certain duration

TODO

How to perform an action when a button is tapped or another when the button is held

TODO

How to make a game character jump higher depending on how long a button is held

A common ability game characters have in many games is the ability to jump. It is pretty common to make these jumps dynamic, by allowing the user to tap a button to make a short jump, or holding the button for longer to make a higher jump. In the following example, we will see how one could implement this functionality in a game. There are several ways for doing this, but we will use the versatility of ActivationInputEvent to achieve it.

using System;
using System.Diagnostics;
using XInputium;
using XInputium.ModifierFunctions;
using XInputium.XInput;

namespace MyNamespace;
public class MyGameOrApplication
{

    private readonly XGamepad _gamepad;
    private XButtons _jumpButton = XButtons.A;  // The jump button.
    private float _maxJumpHoldTime = 750;  // Button hold time for the highest jump, in milliseconds.

    public MyGameOrApplication()
    {
        _gamepad = new();  // This uses the first connected device it finds.

        // Register a dynamic event that fires when the button is released or when the 
        // button is held for the `_maxJumpHoldTime`, whatever happens first.
        _gamepad.RegisterActivationInputEvent(
            () => _gamepad.Buttons.IsPressed(_jumpButton),
            TimeSpan.Zero, TimeSpan.Zero,
            TimeSpan.FromMilliseconds(_maxJumpHoldTime),
            ActivationInputEventTriggerMode.OnDeactivation,
            (s, e) =>
            {
                // Determine the jump force, using the duration of the hold.
                float jumpForce = (float)e.PreviousStateDuration.TotalMilliseconds / _maxJumpHoldTime;
                // Make the jump force non-linear, so pressing the button shortly will not jump
                // with a too low force. Optionally, we could also set a minimum jump force.
                jumpForce = NonLinearFunctions.QuadraticEaseOut(jumpForce);
                // Call our method that will make the game character jump.
                Jump(jumpForce);
            });
    }

    // This method is hypothetically called by the game/application framework on every frame render.
    protected void OnRender()
    {
        // Call this on every game/application frame.
        _gamepad.Update();  // Input events will be triggered now.
    }

    // Make the character jump, with a force within the 0-1 range.
    public void Jump(float force)
    {
        // Your jump code here.
        Debug.WriteLine($"Jump! (force: {force:P0})");
    }

}

On our example above, if the user holds A button for less than 750 milliseconds, a fraction of the max jump force is used to jump. Once that time has passed, if the user is still holding the button, the character jumps anyway, with the maximum jump force. The jump force depends on how long the user holds the button, and that time affects the jump force non-linearly.

How to make an action start repeating while a button is held

TODO

How to perform an action when two buttons are pressed simultaneously

TODO

How to perform an action when any button is pressed

Games with press any button screens are very common. To determine if any digital button is pressed, you simply need to subscribe to XGamepad.ButtonPressed event. The following example, shows how you could subscribe to that event.

XGamepad _gamepad = new();
_gamepad.ButtonPressed += (s, e) => Debug.WriteLine("Some button was pressed.");

Note that the left and right triggers are not buttons and will not fire the ButtonPressed event. To also handle the triggers as digital buttons, you can add the following code:

_gamepad.LeftTrigger.ToDigitalButton(0.5f).Pressed +=
    (s, e) => Debug.WriteLine("Some button was pressed.");
_gamepad.RightTrigger.ToDigitalButton(0.5f).Pressed +=
    (s, e) => Debug.WriteLine("Some button was pressed.");

Alternatively, you could also use ActivationInputEvent to achieve the same result as the previous two examples:

XGamepad _gamepad = new();
_gamepad.RegisterActivationInputEvent(
    () => _gamepad.Buttons.IsAnyButtonPressed
    || _gamepad.LeftTrigger.Value >= 0.5f || _gamepad.RightTrigger.Value >= 0.5f,
    ActivationInputEventTriggerMode.OnActivation,
    (s, e) => Debug.WriteLine("Some button was pressed."));

How to perform an action when a joystick or trigger moves

TODO

How to perform an action that depends on how fast a joystick or trigger moves

TODO

How to make a game character walk or run according to a joystick's position

TODO

How to make a joystick or a trigger more sensitive

TODO

How to make a joystick smoother

TODO

How to set up a dead-zone for a joystick or a trigger

TODO

How to use a joystick as a digital directional pad

TODO

How to make the left and right triggers behave as buttons

TODO

How to make a gamepad vibrate

TODO

How to enable/disable vibration in my game/application

TODO

How to disable input when my game/application loses focus

TODO

How to perform an action when or while a specific condition is met

TODO