Gamepad per UWP


Hätte ich ein wenig mehr Recherchiert, dann hätte ich gleich eine UWP Anwendung geschrieben. Mit Visual Studio kann man schon seit Windows 8.1 UWP Anwendungen schreiben, die für PC, Tablet und Windows Phone funktionieren. Klar, Windows Phone ist vielleicht nicht mehr interessant, aber man kann das Smartphone immer noch zum Basteln verwenden.

Suche nach bestehenden Lösungen
Vor einigen Wochen suchte ich eine Lösung, wie man andere GameController einlesen kann und stieß auf einen anderen Blog Namens "Sander van de Velde", der über die Klasse Gamepad in UWP Anwendung schrieb. Kurz gelesen und gleich probiert und siehe da, es geht. Man kann sogar mit dem Xbox Controller die eigene Anwendung Teilweise sogar Bedienen. Egal ob auf PC, Tablet oder Raspberry Pi. 


Für den Einstieg
Als Beispiel wird ein Punkt auf der Anwendung bewegt. Der Aufbau zeigt, welche Grundlegende Programmcodezeilen Notwendig sind, um die Eingabe vom Xbox Controller zu nutzen.

Gamepad erkennen
Wenn der Xbox Controller mit dem Ziel Gerät verbunden wird, dann wird das GamepadAdded Event gesendet. Das gleiche gilt auch wenn der Controller getrennt wird (GamepadRemoved). Hinweis: MainViewModel habe ich nicht aufgeführt (siehe ggf. Github).

 // ist eigentlich bei einem so kleinen Beispiel nicht Notwendig ein ViewModel zu verwenden 
 private MainViewModel _viewModel = new MainViewModel();  
 // Ermöglicht eine Schleife Asynchron zum Haupteil der Anwendung auszuführen.  
 private Task _run;  
 // Hauptklasse für das einlesen des Xbox Controllers.  
 private Gamepad _gamePad;  
 // Wird nur für den zufälligen Farbwechsel verwendet.  
 private Random _random = new Random();  
 public MainPage()  
 {  
   this.InitializeComponent();  
   this.DataContext = this._viewModel;  
   Gamepad.GamepadAdded += this.Gamepad_GamepadAdded;  
   Gamepad.GamepadRemoved += this.Gamepad_GamepadRemoved;  
   this.MovingPoint.Fill = new SolidColorBrush(Colors.Black);  
 }  
 // Wenn der Xbox Controller getrennt wird.  
 private void Gamepad_GamepadRemoved(object sender, Gamepad e) => this._gamePad = null;  
 // Wird ausgeführt, wenn ein Xbox Controller verbunden wurde.  
 private void Gamepad_GamepadAdded(object sender, Gamepad e)  
 {  
   this._gamePad = e;  
   // … Ab hier kann der Controller ausgelesen werden.  
 }  

Gamepad einlesen und Eingabe Werte verwenden
Das Auslesen gibt ein Typ von GamepadReading zurück. Dieser enthält alle Eingaben, die zu diesen Zeitpunkt des Auslesen getätigt wurden.
Die UI und das Auslesen befinden sich in zwei Ebenen und laufen somit Asynchrone zu einander. Damit die umgerechneten Werten an die UI Elemente zugewiesen werden können, wird der Dispatcher verwendet.

 // Liest die den Xbox Controller aus. Für den Vorgang wird eine Schleife verwendet.  
 private async void ReadingGamepad()  
 {  
   while (true)  
   {  
     if(this._gamePad == null) { break; }  
     // Aktuelle Eingabe erfassen.  
     GamepadReading gp = this._gamePad.GetCurrentReading();  
     // UI und der Task laufen in verschiedenen Ebenen.   
     // Daher muss über den Dispatcher die Eingabe Daten   
     // und die Daten aus dem ViewModel Bindung Async behandelt werden.  
     await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () =>  
     {  
       // Linken Stick einlesen  
       var left = gp.LeftThumbstickX;  
       var top = gp.LeftThumbstickY * -1;  
       // Abstand zum Rand  
       var distanceToBorder = 30;  
       // Eingabe zu einer Position auf der Anwendung umrechnen.  
       var halfLeft = (this.ActualWidth - (distanceToBorder * 2)) / 2d;  
       left = halfLeft + (left * halfLeft);  
       var halfTop = (this.ActualHeight - distanceToBorder * 2) / 2d;  
       top = halfTop + (top * halfTop);  
       // verhindern, dass der Punkt den Rand nicht erreicht.  
       if (left < distanceToBorder) { left = distanceToBorder; }  
       if (left > this.ActualWidth) { left = this.ActualWidth; }  
       if (top < distanceToBorder) { top = distanceToBorder; }  
       if (top > this.ActualHeight - distanceToBorder) { top = this.ActualHeight - distanceToBorder; }  
       // Position als Text Ausgeben mit bis zu zwei Stellen hinter dem Komma.  
       this._viewModel.TextPosition = $"LEFT: {left:N2}, TOP: {top:N2}";  
       // leider kein Binding, daher die simple zuweisung der Ziel Position und Farbe  
       this.MovingPoint.Margin = new Thickness(left, top, 0, 0);  
       // Farbe wechseln  
       if (gp.Buttons == GamepadButtons.A)  
       {  
         // verkürzte die schreibweise  
         byte f() => (byte)this._random.Next(0, 255);  
         this.MovingPoint.Fill = new SolidColorBrush(Color.FromArgb(255, f(), f(), f()));  
       }  
     });  
     // 2 Millisekunden interval  
     await Task.Delay(2);  
   }  
 }  

Fazit
Das war alles. Und dazu war keine zusätzliche GameEngine Notwendig, um die Eingabedaten vom Xbox Controller zu lesen. Auf dem PC und Tablet funktioniert dies auch Kabellos. Nur mit dem Raspberry Pi 2 und 3 konnte ich die Verbindung nur mit einem USB Micro herstellen. Auf Windows Phone (Lumia 930) ließ sich die Anwendung starten, aber es konnte keine Bluetooth Verbindung hergestellt werden.

Kommentare

Beliebte Posts aus diesem Blog

Arduino Control (Teil 5) - PWM Signal einlesen

RC Fahrtenregler für Lego Kettenfahrzeug

Angular auf dem Raspberry Pi