Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az XInput lehetővé teszi a Windows-alkalmazások számára a vezérlők interakcióinak feldolgozását (beleértve a vezérlő dübörgő effektusait, a hangbemenetet és a kimenetet).
Ez a témakör rövid áttekintést nyújt az XInput képességeiről és az alkalmazásokban való beállításáról. A következőket tartalmazza:
- XInput bemutatása
- XInput használata
- Kapcsolódó témakörök
Bevezetés az XInput használatába
Az alkalmazások az XInput API-val kommunikálhatnak a játékvezérlőkkel, ha windowsos PC-hez vannak csatlakoztatva (egyszerre legfeljebb négy egyedi vezérlő csatlakoztatható).
Ezzel az API-val bármely kompatibilis csatlakoztatott vezérlő lekérdezhető az állapotához, és rezgési hatások állíthatók be. A fejhallgatóval csatlakoztatott vezérlők lekérdezhetők hangbemeneti és kimeneti eszközök esetében is, amelyek a fejhallgatóval hangfeldolgozáshoz használhatók.
Vezérlő elrendezése
A kompatibilis vezérlők két analóg iránytűvel rendelkeznek, amelyek mindegyike digitális gombbal, két analóg triggerrel, egy négy irányból álló digitális iránypanellel és nyolc digitális gombbal rendelkezik. Az egyes bemenetek állapotát a rendszer a XINPUT_GAMEPAD struktúrában adja vissza, amikor meghívja az XInputGetState függvényt.
A vezérlő két rezgésmotorral is rendelkezik, amelyek visszajelzési hatásokat biztosítanak a felhasználónak. Ezeknek a motoroknak a sebessége a XINPUT_VIBRATION szerkezetben van megadva, amelyet a XInputSetState függvénynek a rezgési hatások beállításához adnak át.
Opcionálisan fejhallgató is csatlakoztatható a vezérlőhöz. A fejhallgató mikrofonnal rendelkezik a hangbemenethez, és egy fejhallgatót a hangkimenethez. Meghívhatja a XInputGetAudioDeviceIds vagy a régi XInputGetDSoundAudioDeviceGuids függvényt, hogy lekérje a mikrofon és a fejhallgató eszközazonosítókat. Ezután a Core Audio API-kkal fogadhat hangbemenetet, és hangkimenetet küldhet.
Az XInput használata
Az XInput használata olyan egyszerű, mint az XInput függvények igény szerinti meghívása. Az XInput függvényekkel lekérheti a vezérlő állapotát, lekérheti a fejhallgató hangazonosítóit, és beállíthatja a vezérlő dübörgő effektusait.
Több vezérlő
Az XInput API legfeljebb négy, bármikor csatlakoztatott vezérlőt támogat. Az XInput függvényekhez egy dwUserIndex paraméter szükséges, amely a beállított vagy lekérdezett vezérlő azonosításához van átadva. Ez az azonosító a 0-3 közötti tartományban fog szerepelni, és az XInput automatikusan fogja beállítani. A szám annak a portnak felel meg, amelybe a vezérlő csatlakoztatva van, és nem módosítható.
Minden vezérlő megjeleníti a használt azonosítót úgy, hogy a vezérlő közepén található "fénygyűrűn" meggyújt egy negyedet. A dwUserIndex értéke 0, amely a bal felső negyednek felel meg; a számozás az óramutató járásával megegyező sorrendben halad a gyűrű körül.
Az alkalmazásoknak több vezérlőt kell támogatniuk.
Vezérlő állapotának lekérése
Az alkalmazás teljes időtartama alatt az állapot vezérlőtől való lekérése valószínűleg a leggyakrabban történik. A játékalkalmazásban a kerettől a keretig le kell kérni az állapotot, és frissíteni kell a játékinformációkat a vezérlő változásainak megfelelően.
Az állapot lekéréséhez használja az XInputGetState függvényt:
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
}
}
Vegye figyelembe, hogy a XInputGetState visszatérési értéke alapján megállapítható, hogy a vezérlő csatlakoztatva van-e. Az alkalmazásoknak olyan struktúrát kell meghatározniuk, amely a belső vezérlő információinak tárolására szolgál; ezeket az információkat össze kell hasonlítani XInputGetState eredményeivel annak megállapításához, hogy milyen változások történtek abban a képkockában, például gombnyomások vagy analóg vezérlők változásai. A fenti példában g_Controllers egy ilyen struktúrát jelöl.
Miután lekérte az állapotot egy XINPUT_STATE struktúrában, ellenőrizheti a módosításokat, és konkrét információkat kaphat a vezérlő állapotáról.
A XINPUT_STATE struktúrájának dwPacketNumber tagja segítségével ellenőrizheti, hogy a vezérlő állapota megváltozott-e az XInputGetStatelegutóbbi hívása óta. Ha dwPacketNumber nem változik a XInputGetStatekét egymást követő hívása között, akkor az állapot nem változott. Ha eltér, akkor az alkalmazásnak ellenőriznie kell a Gamepad tagját a XINPUT_STATE struktúrában, hogy részletesebb állapotinformációkat kapjon.
Teljesítménybeli okokból ne hívja meg XInputGetState egy "üres" felhasználói helyhez minden egyes keretben. Javasoljuk, hogy inkább ossza el az új vezérlők ellenőrzését néhány másodpercenként.
Holt zóna
Annak érdekében, hogy a felhasználók egységes játékélményt biztosíthassanak, a játéknak megfelelően kell implementálnia a holt zónát. A holt zóna azokat a "mozgás" értékeket jelenti, amelyeket a vezérlő jelent, még akkor is, ha az analóg hüvelykujjtárcsák érintetlenek és középen állnak. Van egy holt zóna is a 2 analóg eseményindítóhoz.
Jegyzet
Az XInputot használó játékok, amelyek egyáltalán nem szűrik a holt zónát, gyenge játékmenetet fognak tapasztalni. Vegye figyelembe, hogy egyes vezérlők érzékenyebbek másoknál, ezért a holt zóna egységenként eltérő lehet. Javasoljuk, hogy tesztelje a játékokat több különböző vezérlővel különböző rendszereken.
Az alkalmazásoknak "holt zónákat" kell használniuk analóg bemeneteken (triggereken, botokon) annak jelzésére, hogy mikor történt megfelelő mozgás a boton vagy a triggeren ahhoz, hogy érvényesnek minősüljenek.
Az alkalmazásnak ellenőriznie kell a holt zónákat, és megfelelően kell válaszolnia, ahogyan ebben a példában is látható:
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
Ez a példa kiszámítja a vezérlő irányvektorát és azt, hogy milyen messzire tolódott el a vezérlő a vektor mentén. Ez lehetővé teszi a körkörös holtzóna érvényesítését azáltal, hogy egyszerűen ellenőrzi, hogy a vezérlő nagysága nagyobb-e, mint a holtzóna értéke. Emellett a kód normalizálja a vezérlő nagyságát, amelyet aztán meg lehet szorozni egy játékspecifikus tényezővel, hogy a vezérlő pozícióját a játék szempontjából releváns egységekké alakítsa.
Vegye figyelembe, hogy meghatározhat saját holtzónákat a botokhoz és a ravaszokhoz (0-65534 tartományban), vagy használhatja az XInput.h-ben definiált, XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE, XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE és XINPUT_GAMEPAD_TRIGGER_THRESHOLD értékeket.
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
A holtzónák kényszerítése után hasznos lehet az eredményül kapott [0.0...1.0] lebegőpontos tartomány skálázása (a fenti példához hasonlóan), és opcionálisan nem lineáris transzformáció alkalmazása.
Például autóversenyzős játékoknál hasznos lehet az eredményt köbre emelni, hogy a gamepaddel történő autóirányítás természetesebb érzetet adjon, mivel ez nagyobb pontosságot biztosít az alacsonyabb tartományokban, ami előnyös, hiszen a játékosok jellemzően либо enyhe nyomást fejtenek ki a finom mozgásokhoz, либо teljesen kitérítik az irányítót egy irányba a gyors reakció érdekében.
Rezgési effektusok beállítása
A vezérlő állapotának lekérése mellett rezgési adatokat is küldhet a vezérlőnek, hogy megváltoztassa a vezérlő felhasználójának küldött visszajelzést. A vezérlő két dübörgő motort tartalmaz, amelyek egymástól függetlenül vezérelhetők úgy, hogy értékeket adnak át az XInputSetState függvénynek.
Az egyes motorok sebessége a XINPUT_VIBRATION szerkezetben lévő WORD-értékkel határozható meg, amelyet az XInputSetStatefüggvénynek a következőképpen ad át:
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 );
Vegye figyelembe, hogy a jobb motor a nagyfrekvenciás motor, a bal oldali motor az alacsony frekvenciájú motor. Ezeket nem mindig kell ugyanarra az összegre beállítani, mivel különböző hatásokat biztosítanak.
Hangeszköz-azonosítók lekérése
A vezérlő headsetje a következő funkciókkal rendelkezik:
- Hang rögzítése mikrofonnal
- Hangvisszajátszás fejhallgatóval
Ezzel a kóddal szerezheti be a headset eszközazonosítóit:
WCHAR renderId[ 256 ] = {0};
WCHAR captureId[ 256 ] = {0};
UINT rcount = 256;
UINT ccount = 256;
XInputGetAudioDeviceIds( i, renderId, &rcount, captureId, &ccount );
Az eszközazonosítók beszerzése után létrehozhatja a megfelelő interfészeket. Ha például az XAudio 2.8-at használja, ezzel a kóddal hozhat létre mesterhangot az eszközhöz:
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;
További információ a captureId eszközazonosító használatáról: Stream-rögzítése.
DirectSound GUID-k lekérése (csak örökölt DirectX SDK esetén)
A vezérlőhöz csatlakoztatható fejhallgató két funkcióval rendelkezik: mikrofonnal rögzíthet hangot, fejhallgatóval pedig visszajátszhatja a hangot. Az XInput API-ban ezeket a függvényeket DirectSound, az IDirectSound8 és IDirectSoundCapture8 interfészek használatával hajtja végre.
Ha a mikrofonos fejhallgatót és a fejhallgatót a megfelelő DirectSound interfészekkel szeretné társítani, a rögzítéshez és a rendereléshez szükséges DirectSoundGUID-eket az XInputGetDSoundAudioDeviceGuidsmeghívásával kell beszereznie.
Jegyzet
Az örökölt DirectSound használata nem ajánlott, és nem érhető el a Windows Áruházbeli alkalmazásokban. Az ebben a szakaszban található információk csak az XInput (XInput 1.3) DirectX SDK-verziójára vonatkoznak. Az XInput (XInput 1.4) Windows 8 verziója kizárólag a Windows Audio Session API (WASAPI) eszközazonosítóit használja, amelyek a XInputGetAudioDeviceIdskeresztül érhetők el.
XInputGetDSoundAudioDeviceGuids( i, &dsRenderGuid, &dsCaptureGuid );
Miután lekérte a grafikus felhasználói felületeket, a DirectSoundCreate8 és a DirectSoundCaptureCreate8 meghívásával a következő módon hozhatja létre a megfelelő interfészeket:
// 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;