Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
XInput ermöglicht Windows-Anwendungen die Verarbeitung von Controllerinteraktionen (einschließlich Controller-Rumble-Effekten und Spracheingabe und -ausgabe).
Dieses Thema enthält eine kurze Übersicht über die Funktionen von XInput und das Einrichten in einer Anwendung. Sie enthält Folgendes:
Einführung in XInput
Anwendungen können die XInput-API verwenden, um mit Gaming-Controllern zu kommunizieren, wenn sie an einen Windows-PC angeschlossen sind (bis zu vier eindeutige Controller können gleichzeitig angeschlossen werden).
Mit dieser API kann jeder kompatible verbundene Controller nach seinem Zustand abgefragt werden, und Vibrationseffekte können festgelegt werden. Controller mit angeschlossenem Headset können auch nach Soundeingabe- und Ausgabegeräten abgefragt werden, die mit dem Headset für die Sprachverarbeitung verwendet werden können.
Controllerlayout
Kompatible Controller verfügen über zwei analoge Richtungssticks, jeweils mit einem digitalen Taster, zwei analogen Triggern, einem digitalen Steuerkreuz mit vier Richtungen und acht digitalen Tasten. Die Zustände dieser Eingaben werden in der XINPUT_GAMEPAD Struktur zurückgegeben, wenn die XInputGetState-Funktion aufgerufen wird.
Der Controller verfügt auch über zwei Vibrationsmotoren, um dem Benutzer Kraftrückmeldungseffekte zu liefern. Die Geschwindigkeiten dieser Motoren werden in der XINPUT_VIBRATION Struktur angegeben, die an die XInputSetState-Funktion übergeben wird, um Vibrationseffekte festzulegen.
Optional kann ein Headset an den Controller angeschlossen werden. Das Headset verfügt über ein Mikrofon für die Spracheingabe und einen Kopfhörer für die Soundausgabe. Sie können die XInputGetAudioDeviceIds oder die ältere XInputGetDSoundAudioDeviceGuids-Funktion aufrufen, um die Gerätebezeichner abzurufen, die den Geräten für das Mikrofon und den Kopfhörern entsprechen. Anschließend können Sie die Core Audio-APIs verwenden, um Spracheingaben zu empfangen und Die Soundausgabe zu senden.
Verwenden von XInput
Die Verwendung von XInput ist so einfach wie das Aufrufen der XInput-Funktionen nach Bedarf. Mit den XInput-Funktionen können Sie den Controllerzustand abrufen, Headset-Audio-IDs abrufen und Controller-Rumbleeffekte festlegen.
Mehrere Controller
Die XInput-API unterstützt jederzeit bis zu vier Controller, die verbunden sind. Die XInput-Funktionen erfordern alle einen dwUserIndex-Parameter , der übergeben wird, um den festzulegenden oder abgefragten Controller zu identifizieren. Diese ID befindet sich im Bereich von 0-3 und wird automatisch von XInput festgelegt. Die Nummer entspricht dem Port, an den der Controller angeschlossen ist, und kann nicht geändert werden.
Jeder Controller zeigt an, welche ID er verwendet, indem er einen Quadranten auf dem "Lichtring" in der Mitte des Controllers beleuchtet. Ein dwUserIndex-Wert von 0 entspricht dem oberen linken Quadranten; Die Nummerierung wird um den Ring im Uhrzeigersinn fortgesetzt.
Anwendungen sollten mehrere Controller unterstützen.
Abrufen des Controller-Status
Während der gesamten Dauer einer Anwendung erfolgt der Abruf des Zustands von einem Controller wahrscheinlich am häufigsten. Von Frame zu Frame in einer Spielanwendung sollte der Zustand abgerufen werden und Spielinformationen aktualisiert werden, um die Änderungen des Controllers widerzuspiegeln.
Verwenden Sie zum Abrufen des Zustands die XInputGetState-Funktion :
DWORD dwResult;
for (DWORD i=0; i< XUSER_MAX_COUNT; i++ )
{
XINPUT_STATE state;
ZeroMemory( &state, sizeof(XINPUT_STATE) );
// Simply get the state of the controller from XInput.
dwResult = XInputGetState( i, &state );
if( dwResult == ERROR_SUCCESS )
{
// Controller is connected
}
else
{
// Controller is not connected
}
}
Beachten Sie, dass der Rückgabewert von XInputGetState verwendet werden kann, um festzustellen, ob der Controller angeschlossen ist. Anwendungen sollten eine Struktur definieren, die interne Controllerinformationen enthält; Diese Informationen sollten mit den Ergebnissen von XInputGetState verglichen werden, um zu bestimmen, welche Änderungen, z. B. Tastendrücke oder analoge Controllerdelta, diesen Frame vorgenommen wurden. Im obigen Beispiel stellt g_Controllers eine solche Struktur dar.
Nachdem der Zustand in einer XINPUT_STATE-Struktur abgerufen wurde, können Sie ihn auf Änderungen überprüfen und bestimmte Informationen zum Controllerzustand abrufen.
Der dwPacketNumber-Member der XINPUT_STATE-Struktur kann verwendet werden, um zu überprüfen, ob sich der Zustand des Controllers seit dem letzten Aufruf von XInputGetState geändert hat. Wenn sich dwPacketNumber nicht zwischen zwei sequenziellen Aufrufen von XInputGetState ändert, wurde kein Zustand geändert. Wenn sich dies unterscheidet, sollte die Anwendung das Gamepad-Mitglied der XINPUT_STATE Struktur überprüfen, um detailliertere Zustandsinformationen zu erhalten.
Rufen Sie aus Leistungsgründen XInputGetState nicht für einen leeren Benutzerplatz in jedem Frame auf. Wir empfehlen, die Überprüfung auf neue Controller stattdessen zeitlich alle paar Sekunden zu verteilen.
Funkloch
Damit Benutzer über eine konsistente Spielerfahrung verfügen, muss Ihr Spiel die inaktive Zone richtig implementieren. Die Totzone bezieht sich auf Bewegungswerte, die vom Controller gemeldet werden, selbst wenn die analogen Ministicks unberührt und zentriert sind. Es gibt auch eine inaktive Zone für die 2 analogen Trigger.
Hinweis
Spiele, die XInput verwenden, die überhaupt keine inaktive Zone filtern, werden ein schlechtes Gameplay erleben. Bitte beachten Sie, dass einige Controller empfindlicher sind als andere, sodass die inaktive Zone von Einheit zu Einheit variieren kann. Es wird empfohlen, Ihre Spiele mit mehreren verschiedenen Controllern auf verschiedenen Systemen zu testen.
Anwendungen sollten "Totzonen" für analoge Eingaben (Trigger, Sticks) verwenden, um anzugeben, wann eine Bewegung am Stick oder Trigger ausreichend ausgeführt wurde, um als gültig angesehen zu werden.
Ihre Anwendung sollte nach inaktiven Zonen suchen und entsprechend reagieren, wie in diesem Beispiel:
XINPUT_STATE state = g_Controllers[i].state;
float LX = state.Gamepad.sThumbLX;
float LY = state.Gamepad.sThumbLY;
//determine how far the controller is pushed
float magnitude = sqrt(LX*LX + LY*LY);
//determine the direction the controller is pushed
float normalizedLX = LX / magnitude;
float normalizedLY = LY / magnitude;
float normalizedMagnitude = 0;
//check if the controller is outside a circular dead zone
if (magnitude > INPUT_DEADZONE)
{
//clip the magnitude at its expected maximum value
if (magnitude > 32767) magnitude = 32767;
//adjust magnitude relative to the end of the dead zone
magnitude -= INPUT_DEADZONE;
//optionally normalize the magnitude with respect to its expected range
//giving a magnitude value of 0.0 to 1.0
normalizedMagnitude = magnitude / (32767 - INPUT_DEADZONE);
}
else //if the controller is in the deadzone zero out the magnitude
{
magnitude = 0.0;
normalizedMagnitude = 0.0;
}
//repeat for right thumb stick
In diesem Beispiel wird der Richtungsvektor des Controllers berechnet und wie weit der Vektor des Controllers verschoben wurde. Dies ermöglicht die Durchsetzung einer kreisförmigen Totzone, indem einfach überprüft wird, ob die Stärke des Controllers größer als die Totzone ist. Darüber hinaus normalisiert der Code die Größe des Controllers, die dann mit einem spielspezifischen Faktor multipliziert werden kann, um die Position des Controllers in Einheiten zu konvertieren, die für das Spiel relevant sind.
Beachten Sie, dass Sie ihre eigenen inaktiven Zonen für die Sticks und Trigger (überall zwischen 0 und 65534) definieren können, oder Sie können die bereitgestellten Deadzones verwenden, die als XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE und XINPUT_GAMEPAD_TRIGGER_THRESHOLD in XInput.h definiert sind:
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
Nachdem der Inaktivbereich erzwungen wurde, kann es hilfreich sein, den resultierenden Bereich [0.0..1.0] Gleitkomma (wie im obigen Beispiel) zu skalieren und optional eine nicht lineare Transformation anzuwenden.
Mit Fahrspielen kann es beispielsweise hilfreich sein, das Ergebnis zu potenzieren, um ein besseres Fahrerlebnis beim Fahren der Autos mit einem Gamepad zu bieten. Das Potenzieren des Ergebnisses ermöglicht mehr Präzision in den unteren Bereichen, was wünschenswert ist, da Spieler normalerweise entweder sanfte Kraft anwenden, um subtile Bewegungen zu erzielen, oder starke Kraft in eine Richtung ausüben, um eine schnelle Reaktion zu erreichen.
Festlegen von Vibrationseffekten
Zusätzlich zum Abrufen des Zustands des Controllers können Sie auch Vibrationsdaten an den Controller senden, um das feedback zu ändern, das dem Benutzer des Controllers zur Verfügung gestellt wird. Der Controller enthält zwei Rumblemotoren, die unabhängig voneinander gesteuert werden können, indem Werte an die XInputSetState-Funktion übergeben werden.
Die Geschwindigkeit jedes Motors kann mithilfe eines WORD-Werts in der XINPUT_VIBRATION Struktur angegeben werden, die wie folgt an die XInputSetState-Funktion übergeben wird:
XINPUT_VIBRATION vibration;
ZeroMemory( &vibration, sizeof(XINPUT_VIBRATION) );
vibration.wLeftMotorSpeed = 32000; // use any value between 0-65535 here
vibration.wRightMotorSpeed = 16000; // use any value between 0-65535 here
XInputSetState( i, &vibration );
Beachten Sie, dass der rechte Motor der Hochfrequenzmotor ist, der linke Motor ist der Niederfrequenzmotor. Sie müssen nicht immer auf denselben Betrag festgelegt werden, wie sie unterschiedliche Effekte bieten.
Abrufen von Audiogerätekennungen
Das Headset für einen Controller verfügt über folgende Funktionen:
- Aufzeichnen von Sound mithilfe eines Mikrofons
- Wiedergeben von Sound mithilfe eines Kopfhörers
Verwenden Sie diesen Code, um die Gerätebezeichner für das Headset abzurufen:
WCHAR renderId[ 256 ] = {0};
WCHAR captureId[ 256 ] = {0};
UINT rcount = 256;
UINT ccount = 256;
XInputGetAudioDeviceIds( i, renderId, &rcount, captureId, &ccount );
Nachdem Sie die Geräte-IDs erhalten haben, können Sie die entsprechenden Schnittstellen erstellen. Wenn Sie z. B. XAudio 2.8 verwenden, verwenden Sie diesen Code, um eine Masterstimme für dieses Gerät zu erstellen:
IXAudio2* pXAudio2 = NULL;
HRESULT hr;
if ( FAILED(hr = XAudio2Create( &pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR ) ) )
return hr;
IXAudio2MasteringVoice* pMasterVoice = NULL;
if ( FAILED(hr = pXAudio2->CreateMasteringVoice( &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, XAUDIO2_DEFAULT_SAMPLERATE, 0, renderId, NULL, AudioCategory_Communications ) ) )
return hr;
Informationen zur Verwendung der CaptureId-Geräte-ID finden Sie unter Erfassen eines Datenstroms.
Abrufen von DirectSound-GUIDs (nur legacy DirectX SDK)
Das Headset, das an einen Controller angeschlossen werden kann, verfügt über zwei Funktionen: Es kann Sound mit einem Mikrofon aufzeichnen und sound mit einem Kopfhörer wiedergeben. In der XInput-API werden diese Funktionen über DirectSound mithilfe der IDirectSound8 - und IDirectSoundCapture8-Schnittstellen ausgeführt.
Um das Headsetmikrofon und den Kopfhörer ihren entsprechenden DirectSound-Schnittstellen zuzuordnen, müssen Sie die DirectSoundGUIDs für die Aufnahme- und Rendergeräte abrufen, indem Sie XInputGetDSoundAudioDeviceGuids aufrufen.
Hinweis
Die Verwendung des veralteten DirectSound wird nicht empfohlen und ist in Windows Store-Apps nicht verfügbar. Die Informationen in diesem Abschnitt gelten nur für die DirectX SDK-Version von XInput (XInput 1.3). Die Windows 8-Version von XInput (XInput 1.4) verwendet ausschließlich Windows Audio Session API (WASAPI)-Gerätebezeichner, die über XInputGetAudioDeviceIds abgerufen werden.
XInputGetDSoundAudioDeviceGuids( i, &dsRenderGuid, &dsCaptureGuid );
Nachdem Sie die GUIDs abgerufen haben, können Sie die entsprechenden Schnittstellen erstellen, indem Sie DirectSoundCreate8 und DirectSoundCaptureCreate8 wie folgt aufrufen:
// Create IDirectSound8 using the controller's render device
if( FAILED( hr = DirectSoundCreate8( &dsRenderGuid, &pDS, NULL ) ) )
return hr;
// Set coop level to DSSCL_PRIORITY
if( FAILED( hr = pDS->SetCooperativeLevel( hWnd, DSSCL_NORMAL ) ) )
return hr;
// Create IDirectSoundCapture using the controller's capture device
if( FAILED( hr = DirectSoundCaptureCreate8( &dsCaptureGuid, &pDSCapture, NULL ) ) )
return hr;