Styra Arduino med Gamepad (3 / 5 steg)
Steg 3: Att få INPUT från GAMEPAD
Nu, att vi vet hur att skicka information till Arduino, vi behöver bara lära sig att få input från XBOX gamepad.
I detta avsnitt kommer vi lära sig grunderna i XInput och skriva ett mycket enkelt program som visar nuvarande gamepad läge i konsolen utdata. Vi får också lära dig några viktiga aspekter av förbehandling indatavärden för att undvika problematiska thumbstick input spänner ("döda zoner").
GRUNDERNA
XInput API tillhandahåller de emot ljud från XBOX 360-handkontroller och innehåller en mängd verktyg ange controller effekterna (fars feedback), bearbeta ljud ingång/utgång för headset och göra andra saker.
XInput stöder upp till 4 controllers, men i vår situation endast controller #0 används som standard.
Vi kommer använda XInputGetState() -funktionen för att uppdatera det aktuella läget för gamepad. Det tar 2 parametrar: gamepad ID (som är 0 i de flesta fall) och pekaren till XInput staten variabel. Returvärdet för XInputGetState kan användas för att kontrollera tillgängligheten för gamepad. Värdet av ERR_SUCCESS innebär att gamepad är på, och XInput staten nu har sin nuvarande tillstånd.
XINPUT_STATE består av följande delar:
TypeDef struct _XINPUT_STATE {
DWORD-dwPacketNumber;
XINPUT_GAMEPAD Gamepad;
} XINPUT_STATE;
dwPacketNumber anger om gamepad staten har förändrats.
Gamepad är en datatyp, vilket motsvarar nuvarande gamepad staten, inklusive thumbstick positioner, trigger värden, D-knappen och knappen flaggor.
TypeDef struct _XINPUT_GAMEPAD {
ORDET wButtons;
BYTE bLeftTrigger;
BYTE bRightTrigger;
KORTA sThumbLX;
KORTA sThumbLY;
KORTA sThumbRX;
KORTA sThumbRY;
} XINPUT_GAMEPAD;
sThumbLX, sThumbLY, sThumbRX och sThumbRY är 16-bitars undertecknat heltal, som tar värden från −32, 768 till 32 767. Dessa motsvarar nuvarande thumbstick positioner.
bLeftTrigger och bRightTrigger ta värden i 0..255 sortiment.
wButtons representerar statligt av alla knappar på ett XBox controller, där varje bit motsvarar aktuell status för varje enskild knapp. Om vi vill kolla om på X-knappen trycktes vi behöver utföra följande operationer:
XINPUT_STATE gpState; Skapa staten variabel
MEMSET (& gpState,0,sizeof(XINPUT_STATE)); Tillstånd
DWORD-res = XInputGetState (0, & gpState); Få nya stat
IF(gpState.wButtons & 0x4000)
{
printf ("Xplosive kick! \n");
}
I följande lista visas alla knappar och deras motsvarande bitmaskar:
XINPUT_GAMEPAD_DPAD_UP 0X0001
XINPUT_GAMEPAD_DPAD_DOWN 0X0002
XINPUT_GAMEPAD_DPAD_LEFT 0X0004
XINPUT_GAMEPAD_DPAD_RIGHT 0X0008
XINPUT_GAMEPAD_START 0X0010
XINPUT_GAMEPAD_BACK 0X0020
XINPUT_GAMEPAD_LEFT_THUMB 0x0040 / / detta är thumbstick knappar
XINPUT_GAMEPAD_RIGHT_THUMB 0X0080
XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100 / / vänster stötfångare
XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200 / / höger stötfångare
XINPUT_GAMEPAD_A 0X1000
XINPUT_GAMEPAD_B 0X2000
XINPUT_GAMEPAD_X 0X4000
XINPUT_GAMEPAD_Y 0X8000
LÅT OSS ÖVA
På denna punkt har vi alla verktyg vi behöver för att skriva vårt första program med XInput. Det blir skrattretande enkla, men det hjälper för att förstå hur denna process fungerar och vilka delar av XInput vi behöver.
#include "stdafx.h"
#include < Windows.h >
#include < XInput.h >
#pragma kommentar (lib, "XInput.lib") / / krävs för linker
int _tmain (int argc, _TCHAR * argv[])
{
XINPUT_STATE gpState; Gamepad staten
int spelare = -1; Gamepad-ID
Polling alla 4 spelkontroller för att se vem som är vid liv
för (int jag = 0; jag < 4; i ++)
{
DWORD-res = XInputGetState (i, & gpState); Att få tillstånd
IF(res==ERROR_SUCCESS) / / om levande - print meddelande
{
printf ("Controller #%d är ON! \n", i + 1);
Player = i. Tilldela sista levande gamepad som aktiv
}
}
IF(Player<0) / / om spelare ==-1 alltså...
{
printf ("har inte hittat någon gamepads...\n");
}
annat
{
While(true)
{
system("CLS"); Tydlig skärm
MEMSET (& gpState,0,sizeof(XINPUT_STATE)); Tillstånd
DWORD-res = XInputGetState (0, & gpState); Få nya stat
printf("LX\tLY\tRX\tRY\tLTrig\tRTrig\tButtons\n"); Skriva ut huvudet
Thumbstick värden är dividerat med 256 för bättre konsistens
printf ("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
gpState.Gamepad.sThumbLX/256,
gpState.Gamepad.sThumbLY/256,
gpState.Gamepad.sThumbRX/256,
gpState.Gamepad.sThumbRY/256,
gpState.Gamepad.bLeftTrigger,
gpState.Gamepad.bRightTrigger,
gpState.Gamepad.wButtons);
}
}
system("PAUSE");
Return 0;
}
En gång du bygger lösningen och köra ditt program, kommer du att se utdata ändrar när du flyttar styrspakar eller tryckknappar på din gamepad. Vi skickar informationen till Arduino ombord i nästa avsnitt av denna handledning.
Just nu jag vill du ska uppmärksamma utdata, när du inte gör något. Värden av LX, RX, LY och RY är inte lika med 0, som vi förväntar oss att de. Detta sker för ett antal skäl, men det viktigaste är att vi är medvetna om detta fenomen!
Dessa svängningar och inkonsekvenser i värden kallas "döda zoner". Vi måste hitta lägsta marginell värdet som vi kan överväga att med styrspak faktiskt trycks i någon riktning för att bli av denna otäck anomali.
Så vi måste definiera en deadzone tröskel och jämför aktuella värden. Kolla in MSDN referens för mer information.
Under tiden använda denna exempelkod för att korrigera dessa värden:
flyta LX = gpState.Gamepad.sThumbLX; Få LX
flyta LY = gpState.Gamepad.sThumbLY; Få LY
storlek = sqrt(LX*LX+LY*LY); Beräkna radien av nuvarande position
IF(Magnitude < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) / / insida död zon?
{
Ställ allt till 0
LX = 0,0;
LY = 0,0;
}
Gör samma sak för RX och RY
Det finns också fördefinierade död zon värden för vänster och höger styrspakar och utlösare. Du kan använda dessa, eller definiera dina egna trösklar (i mitt fall ~ 6500 arbetat för vänster och höger sticka), men tänk på att dessa värden till stor del beror på hur beat-up din gamepad är!
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
YTTERLIGARE LÄSNING
Endast ytterligare medel jag ska nämna är den här en: XInput spel Controller API: er
Det har allt du behöver veta om XInput, inbegripet komplett och användbar programmering guide.
Det var allt för denna del. Nu, låt oss försöka att kombinera våra kunskaper i programmering gamepads och seriella anslutningar till kontroll Arduino distans! ... om du glömde där vi började...