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