Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
XInput gör det möjligt för Windows-program att bearbeta kontrollantinteraktioner (inklusive kontrollantens mullrande effekter och röstinmatning och utdata).
Det här avsnittet innehåller en kort översikt över funktionerna i XInput och hur du konfigurerar det i ett program. Den innehåller följande:
Introduktion till XInput
Program kan använda XInput-API:et för att kommunicera med spelkontrollanter när de är anslutna till en Windows-dator (upp till fyra unika styrenheter kan anslutas samtidigt).
Med det här API:et kan alla kompatibla anslutna styrenheter efterfrågas för dess tillstånd och vibrationseffekter kan anges. Styrenheter som har headsetet anslutet kan också frågas efter ljudinmatnings- och utdataenheter som kan användas med headsetet för röstbearbetning.
Layout för kontrollant
Kompatibla styrenheter har två analoga riktningspinnar, var och en med en digital knapp, två analoga utlösare, en digital riktningsplatta med fyra riktningar och åtta digitala knappar. Tillstånden för var och en av dessa indata returneras i XINPUT_GAMEPAD-strukturen när funktionen XInputGetState anropas.
Styrenheten har också två vibrationsmotorer för att ge kraftåterkopplingseffekter till användaren. Hastigheterna för dessa motorer anges i den XINPUT_VIBRATION struktur som skickas till funktionen XInputSetState för att ange vibrationseffekter.
Du kan också ansluta ett headset till styrenheten. Headsetet har en mikrofon för röstinmatning och en hörlur för ljudutdata. Du kan anropa funktionen XInputGetAudioDeviceIds eller äldre XInputGetDSoundAudioDeviceGuids för att hämta enhetsidentifierarna som motsvarar enheterna för mikrofonen och hörlurarna. Du kan sedan använda api:erna Core Audio för att ta emot röstindata och skicka ljudutdata.
Använda XInput
Att använda XInput är så enkelt som att anropa XInput-funktionerna efter behov. Med hjälp av XInput-funktionerna kan du hämta styrenhetstillstånd, hämta ljud-ID:n för headsetet och ställa in kontrollantens mullrande effekter.
Flera styrenheter
XInput-API:et stöder upp till fyra anslutna styrenheter när som helst. XInput-funktionerna kräver alla en dwUserIndex parameter som skickas in för att identifiera den kontrollant som anges eller efterfrågas. Det här ID:t ligger inom intervallet 0–3 och anges automatiskt av XInput. Talet motsvarar den port som styrenheten är ansluten till och inte kan ändras.
Varje styrenhet visar vilket ID den använder genom att tända en kvadrant på "ljusringen" i mitten av styrenheten. Ett dwUserIndex värde av 0 motsvarar kvadranten överst till vänster, numreringen fortsätter runt ringen i medsols ordning.
Program bör ha stöd för flera kontrollanter.
Hämta kontrollanttillstånd
Under hela programmets gång kommer hämtning av tillstånd från en kontroll förmodligen att göras oftast. Från ruta till ruta i ett spelsystem ska tillstånd hämtas och spelinformation uppdateras för att återspegla kontrollerförändringarna.
Om du vill hämta tillstånd använder du funktionen XInputGetState:
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
}
}
Observera att returvärdet för XInputGetState kan användas för att avgöra om kontrollanten är ansluten. Program bör definiera en struktur för att lagra intern kontrollantinformation. Den här informationen bör jämföras med resultatet av XInputGetState- för att avgöra vilka ändringar, till exempel knapptryckningar eller analoga kontrollantdelta, som har gjorts i ramen. I exemplet ovan representerar g_Controllers en sådan struktur.
När tillståndet har hämtats i en XINPUT_STATE struktur kan du kontrollera om det finns ändringar och få specifik information om kontrollanttillståndet.
dwPacketNumber medlem i XINPUT_STATE-strukturen kan användas för att kontrollera om kontrollantens tillstånd har ändrats sedan det senaste anropet till XInputGetState. Om dwPacketNumber inte ändras mellan två sekventiella anrop till XInputGetStatehar det inte skett någon ändring i tillståndet. Om det skiljer sig bör programmet kontrollera Gamepad medlem i XINPUT_STATE-strukturen för att få mer detaljerad tillståndsinformation.
Av prestandaskäl bör du undvika att anropa XInputGetState- för en "tom" användarplats varje bildruta. Vi rekommenderar att du istället utför kontroller för nya styrenheter med några sekunders mellanrum.
Död zon
För att användarna ska kunna ha en konsekvent spelupplevelse måste ditt spel implementera döda zoner korrekt. Den döda zonen är "rörelsevärden" som rapporteras av styrenheten även när de analoga tumpinnarna är orörda och centrerade. Det finns också en död zon för de två analoga utlösarna.
Not
Spel som använder XInput som inte filtrerar död zon alls kommer att uppleva dåligt spel. Observera att vissa styrenheter är känsligare än andra, vilket innebär att den döda zonen kan variera från enhet till enhet. Vi rekommenderar att du testar dina spel med flera olika styrenheter på olika system.
Program bör använda "döda zoner" på analoga indata (utlösare, pinnar) för att indikera när en förflyttning har gjorts tillräckligt på pinnen eller utlösaren för att anses giltig.
Ditt program bör söka efter döda zoner och svara på lämpligt sätt, som i det här exemplet:
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
Det här exemplet beräknar styrenhetens riktningsvektor och hur långt längs vektorn som styrenheten har blivit skjuten. Detta gör det möjligt att tillämpa en cirkulär dödzon genom att enkelt kontrollera om kontrollerns storlek är större än dödzonens värde. Dessutom normaliserar koden kontrollantens storlek som sedan kan multipliceras med en spelspecifik faktor för att konvertera kontrollantens position till enheter som är relevanta för spelet.
Observera att du kan definiera dina egna döda zoner för pinnar och utlösare (var som helst från 0–65534) eller använda de angivna döda zonerna som definierats som XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE och XINPUT_GAMEPAD_TRIGGER_THRESHOLD i XInput.h:
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
När dödzonen har verkställts kan det vara användbart att skala det resulterande intervallet [0.0..1.0] i flyttalformat (som i exemplet ovan) och eventuellt en icke-linjär transformering.
Till exempel, med körspel, kan det vara bra att kubera resultatet för att ge en bättre känsla när man kör bilar med hjälp av en spelplatta, eftersom att kubera resultatet ger dig mer precision i de lägre intervallen, vilket är önskvärt, eftersom spelare vanligtvis antingen använder mjuk kraft för att få subtil rörelse eller använder hård kraft hela vägen i en riktning för att få snabb respons.
Ställa in vibrationseffekter
Förutom att få kontrollantens tillstånd kan du även skicka vibrationsdata till kontrollanten för att ändra feedbacken som ges till användaren av kontrollanten. Styrenheten innehåller två mullermotorer som kan styras oberoende av varandra genom att skicka värden till funktionen XInputSetState.
Hastigheten för varje motor kan anges med hjälp av ett WORD-värde i den XINPUT_VIBRATION struktur som skickas till funktionen XInputSetState enligt följande:
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 );
Observera att den högra motorn är högfrekvent motor, den vänstra motorn är den lågfrekventa motorn. De behöver inte alltid anges till samma mängd, eftersom de ger olika effekter.
Hämta identifierare för ljudenheter
Headsetet för en styrenhet har följande funktioner:
- Spela in ljud med en mikrofon
- Spela upp ljud med en hörlur
Använd den här koden för att hämta enhetsidentifierarna för headsetet:
WCHAR renderId[ 256 ] = {0};
WCHAR captureId[ 256 ] = {0};
UINT rcount = 256;
UINT ccount = 256;
XInputGetAudioDeviceIds( i, renderId, &rcount, captureId, &ccount );
När du har hämtat enhetsidentifierarna kan du skapa lämpliga gränssnitt. Om du till exempel använder XAudio 2.8 använder du den här koden för att skapa en huvudröst för den här enheten:
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;
Information om hur du använder captureId-enhetsidentifieraren finns i Captureing a Stream.
Hämta DirectSound-GUID:er (endast äldre DirectX SDK)
Headsetet som kan anslutas till en styrenhet har två funktioner: det kan spela in ljud med hjälp av en mikrofon, och det kan spela upp ljud med hjälp av en hörlur. I XInput-API:et utförs dessa funktioner via DirectSound-, med hjälp av gränssnitten IDirectSound8 och IDirectSoundCapture8.
Om du vill associera headsetets mikrofon och hörlurar med lämpliga DirectSound- gränssnitt måste du hämta DirectSoundGUID:erna för inspelnings- och återgivningsenheter genom att anropa XInputGetDSoundAudioDeviceGuids.
Not
Användning av äldre DirectSound- rekommenderas inte och är inte tillgängligt i Windows Store-appar. Informationen i det här avsnittet gäller endast DirectX SDK-versionen av XInput (XInput 1.3). Windows 8-versionen av XInput (XInput 1.4) använder endast Enhetsidentifierare för Windows Audio Session API (WASAPI) som hämtas via XInputGetAudioDeviceIds.
XInputGetDSoundAudioDeviceGuids( i, &dsRenderGuid, &dsCaptureGuid );
När du har hämtat GUID:erna kan du skapa lämpliga gränssnitt genom att anropa DirectSoundCreate8 och DirectSoundCaptureCreate8 så här:
// 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;