Using your Xbox One controller in a UWP app

One of my original Xbox One controllers became useless a few weeks ago. It started to ‘walk away’ with my left stick. Whenever I released my thumb, it still generated a forward motion, not very handy if you are in the middle of a battlefield…

So I ordered a new one from the Microsoft Store but being a geek, I bought one with the Wireless Adapter for Windows.

02 adapter

This adapter makes it possible to use it on a Windows 10 device, like my laptop.

This is part 1 of a series of blogs about the Xbox One controller:

  • Part 1: Using your Xbox One controller in a UWP app
  • Part 2: Control your Arduino Rover using Firmata and Xbox One Controller

Here is it in the device manager:

03xbox

But again, being a geek *developer*, I was searching on the web on how to code against it in a UWP app. The internet was not really revealing much but finally, I came across the XInput information and the default available Windows.Gaming.Input namespace. There was no extra Nuget package needed.

I made this little test app to check out the inner workings of the GamePad class inside the namespace. First I added some XAML elements to show the data coming from the controller:

<StackPanel>
    <Button Name="btnConnect" 
            Content="Connect" 
            FontSize="20" 
            Click="btnConnect_Click" />
 
    <TextBlock Name="tbConnected" 
               Text="-" />
 
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Left Trigger" Margin="0,0,10,0" />
        <TextBlock Name="tbLeftTrigger" />
    </StackPanel>
 
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Right Trigger" Margin="0,0,10,0" />
        <TextBlock Name="tbRightTrigger" />
    </StackPanel>
 
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Lft Thumbstick X" Margin="0,0,10,0" />
        <TextBlock Name="tbLeftThumbstickX" />
    </StackPanel>
 
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Lft Thumbstick Y" Margin="0,0,10,0" />
        <TextBlock Name="tbLeftThumbstickY" />
    </StackPanel>
 
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Rgt Thumbstick X" Margin="0,0,10,0" />
        <TextBlock Name="tbRightThumbstickX" />
    </StackPanel>
 
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Rgt Thumbstick Y" Margin="0,0,10,0" />
        <TextBlock Name="tbRightThumbstickY" />
    </StackPanel>
 
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Buttons" Margin="0,0,10,0" />
        <TextBlock Name="tbButtons" />
    </StackPanel>
</StackPanel>

Then I added some events to register connecting or disconnecting the controller (GamePad) and to read data from the current controller:

public sealed partial class MainPage : Page
{
  private Gamepad _Gamepad = null;
 
  public MainPage()
  {
    this.InitializeComponent();
  }
 
  private async void btnConnect_Click(object sender, 
                                         RoutedEventArgs e)
  {
    Gamepad.GamepadAdded += Gamepad_GamepadAdded;
    Gamepad.GamepadRemoved += Gamepad_GamepadRemoved;
 
    while (true)
    {
      await Dispatcher.RunAsync(
                 CoreDispatcherPriority.Normal, () =>
      {
        if (_Gamepad == null)
        {
          return;
        }
 
        // Get the current state
        var reading = _Gamepad.GetCurrentReading();
 
        tbLeftTrigger.Text = 
          reading.LeftTrigger.ToString();
        tbRightTrigger.Text = 
          reading.RightTrigger.ToString();
        tbLeftThumbstickX.Text = 
          reading.LeftThumbstickX.ToString();
        tbLeftThumbstickY.Text = 
          reading.LeftThumbstickY.ToString();
        tbRightThumbstickX.Text = 
          reading.RightThumbstickX.ToString();
        tbRightThumbstickY.Text = 
           reading.RightThumbstickY.ToString();
        tbButtons.Text = string.Empty;
        tbButtons.Text += 
         (reading.Buttons & GamepadButtons.A) 
            == GamepadButtons.A ? "A " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.B)
            == GamepadButtons.B ? "B " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.X) 
            == GamepadButtons.X ? "X " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.Y) 
            == GamepadButtons.Y ? "Y " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.LeftShoulder) == 
            GamepadButtons.LeftShoulder 
              ? "LeftShoulder " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.RightShoulder) == 
            GamepadButtons.RightShoulder 
              ? "RightShoulder " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.LeftThumbstick) == 
            GamepadButtons.LeftThumbstick 
              ? "LeftThumbstick " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.RightThumbstick) ==            GamepadButtons.RightThumbstick 
              ? "RightThumbstick " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.DPadLeft) == 
            GamepadButtons.DPadLeft ? "DPadLeft " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.DPadRight) == 
            GamepadButtons.DPadRight ? "DPadRight " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.DPadUp) == 
            GamepadButtons.DPadUp ? "DPadUp " : "";
        tbButtons.Text += 
          (reading.Buttons & GamepadButtons.DPadDown) == 
            GamepadButtons.DPadDown ? "DPadDown " : "";
      });
 
      await Task.Delay(TimeSpan.FromMilliseconds(5));
    }
  }
 
  private async void Gamepad_GamepadRemoved(object sender, 
                                            Gamepad e)
  {
    _Gamepad = null;
 
    await Dispatcher.RunAsync(
                       CoreDispatcherPriority.Normal, () =>
    {
      tbConnected.Text = "Controller removed";
    });
  }
 
  private async void Gamepad_GamepadAdded(object sender,
                                          Gamepad e)
  {
    _Gamepad = e;
 
    await Dispatcher.RunAsync(
                 CoreDispatcherPriority.Normal, () =>
    {
      tbConnected.Text = "Controller added";
    });
  }
}

As you can see, I use a while loop to read the input, the controller is not exactly event driven…

And there it is, all the buttons and the position of the sticks are available for us.

01xbox

So now you can build your own game and use the controller as an input device.

Advertenties

Geef een reactie

Vul je gegevens in of klik op een icoon om in te loggen.

WordPress.com logo

Je reageert onder je WordPress.com account. Log uit / Bijwerken )

Twitter-afbeelding

Je reageert onder je Twitter account. Log uit / Bijwerken )

Facebook foto

Je reageert onder je Facebook account. Log uit / Bijwerken )

Google+ photo

Je reageert onder je Google+ account. Log uit / Bijwerken )

Verbinden met %s