V dnešním díle si ukážeme, jak pracovat DirectInput, tj. číst data z různých polohovacích zařízení – klávesnice, myši, joysticku apod.
DirectInput vám umožní rychlejší čtení dat z polohovacích zařízení díky přímé komunikaci s hardwarem, respektive s jejich ovladači. Díky této technice můžete snadno a rychle zjišťovat, třeba jaké klávesy na klávesnici jsou stisknuty, monitorovat pohyb myši nebo joysticku. Oproti používání API funkcí je tento postup přes DirectInput samozřejmě daleko rychlejší. Tak jak na to?
K obsluze DirectInput slouží jedna komponenta z palety DelphiX – DXInput, která obsluhuje rozhraní na DirectInput a 3 základní polohovací zařízení: klávesnice, myš, joystick. Každá tato třída (TKeyboard, TMouse, TJoystick) je odvozena z třídy TCustomInput. Je to abstraktní třída a budou nás u ní zajímat tyto vlastnosti:
Enabled - zapne či vypne čtení informací z daného zařízení.
ActiveOnly - tato vlastnost má podobný význam jako TDXTimer.ActiveOnly, tj. specifikuje, zda se mají přejímat informace o polohovacím zařízení, i když je aplikace v pozadí.
States - tato proměnná reprezentuje stavy zařízení. Je typu TDXInputStates, který má takovouto deklaraci:
type TDXInputState = set of (isUp, isDown, isLeft, isRight, isButton1, isButton2, ... , isButton31, isButton32);
Jedná se tedy o množinu, pomocí které můžete zjistit, zda je u zařízení stisknuto tlačítko 1-32, nebo zda se pohnulo nahoru, doprava atd. Neboli příkaz
if isButton1 in DXInput1.Mouse.States then ...
vám zjistí, je-li stisknuto první tlačítko myši.
Buttons - nepřímo čte informace z vlastnosti States; rozdíl je pouze v přístupu:
if DXInput1.Mouse.Buttons[1] then ...
Tento příkaz taktéž zjistí, jestli je stisknuto první tlačítko myši.
BindInputStates - pokud nastavíte na true, tak se vlastnosti States ze všech zařízení registrovaných u TDXInput přenesou do vlastnosti TDXInput.States. Neboli: pokud se myš nebo joystick posunou nahoru, bude v množině TDXInput.States přítomno isUp.
Ještě nás bude zajímat jediná metoda - Update. Jejím zavoláním aktualizujete data o zařízení (poloha, tlačítka). Taktéž můžete volat Update u TDXInputu, čímž aktualizujete všechna registrovaná zařízení.
Jak jsem se již zmínil, k přístupu k informacím o klávesnici slouží vlastnost Keyboard u komponenty DXInput. V podstatě je zde jedna nová vlastnost, a sice Keys. Přistupuje se k ní stejně jako k vlastnosti Buttons. Jako index zadáte ASCII kód znaku, u kterého chcete zjistit, zda je příslušná klávesa stisknuta. Příklad: mějme statický text s názvem TLAC. Tento kód nám vypíše všechny stisknuté klávesy:
TLAC.Caption:=``;
for i:=0 to 255 do
if DXInput1.Keyboard.Keys[i] then TLAC.Caption:=TLAC.Caption+IntToStr(i)+`,`;
Pokud vás mate, jaký je rozdíl mezi Keys a Buttons, odpověď zní: Vlastností Buttons rozuměj vybraná tlačítka, která jsou nazvána isButton1, isButton2 atd. isButton1 je například Enter u klávesnice, tlačítko 1 u Joysticku a levé tlačítko u myši. Vlastnost Keys je k dispozici pouze u klávesnice a určuje, je-li stisknuta jakákoliv (téměř) klávesa na klávesnici (A,B,Esc,Enter,F1,Tab atd.).
Při používání klávesnice přes DirectInput jistě narazíte na jeden drobný problém: těžko se programují textové vstupy, které známe například jako TEdit z VCL. Například musíte ošetřit stisk klávesy Shift a některého písmena, abyste zjistili, jestli je písmeno velké nebo malé. Nebo si musíte sami napsat obsluhu při stisknutí klávesy Alt+ASCII kód znaku.
K myši budeme přistupovat přes vlastnost Mouse. Nalezneme zde tři nové vlastnosti: X,Y a Z, které udávají změnu vůči té které ose od posledního volání metody Update. Není co víc dodat. Ve třetím díle tohoto seriálu jsem ukazoval, jak zobrazit kurzor v DelphiX. K získání informací o myši jsem použil API funkci GetCursorPos. Teď si ukážeme, jak předělat čtení informací o myši na DirectInput. Toto byl původní kód:
var
p:TPoint;
begin
GetCursorPos(p);
dec(p.x,Form1.Left);
dec(p.y,Form1.Top);
end;
Co musíme změnit: proměnnou p musíme nadeklarovat jako globální, protože v ní budeme evidovat pozici kurzoru. Zbylý kód nahradíme tímto:
p.x:=p.x+DXInput1.Mouse.X;
p.y:=p.y+DXInput1.Mouse.Y;
Nebo tímto, chceme-li používat jako polohovací zařízení joystick:
p.x:=p.x+DXInput1.Joystick.X;
p.y:=p.y+DXInput1.Joystick.Y;
Spusťte takto upravený příklad a uvidíte, že poběží o něco rychleji. Má to ovšem jeden drobný háček. Pokud běží aplikace ve full-screen režimu, není problém, ale běží-li aplikace v okně kurzor, nemusí být synchronní (stejnou pozici na obrazovce) s windowsím kurzorem a to vám může způsobit problém při kliknutí mimo okno: aplikace se deaktivuje a přepne se na jiné okno.
Vlastnost Joystick je o dost rozsáhlejší než Mouse a Keyboard. Nejdůležitější proměnné X, Y a Z udávají polohu Joysticku. Další důležité vlastnosti jsou RangeX, RangeY, RangeZ, DeadZoneX, DeadZoneY a DeadZoneZ. K vysvětlení použiji tento obrázek:
Taktéž v bledě modrém to platí pro RangeZ a DeadZoneZ. Takže, proměnné Range.. určují maximální rozsah, v jakém se budou hodnoty při pohybování joystickem pohybovat. (od -Range.. do +Range..) Hodnoty DeadZone.. udávají "mrtvé zóny", tj. procentuální část z rozsahu joysticku, ve kterém budou hodnoty nulové. Při akcích, kdy záleží na přesnosti, takto můžete eliminovat třesení ruky a nechtěnému posunu v jiné ose, než chce uživatel.
Nezapomeňte ale na správné nastavení vašeho herního zařízení (kalibrace). Vyvoláte ho v nabídce Start->Nastavení->Ovládací panely->Možnosti her. Příklad na použití myši, joysticku a klávesnice si můžete stáhnout zde. Další příklad je v ukázkách k DelphiX v adresáři Samples\Input\Basic.
Bohužel nejsem vlastníkem jakéhokoliv zařízení podporujícího ForceFeedBack, a tak tuto část popíšu jen teoreticky ve zkratce. TCustomInput definuje vlastnost ForceFeedBack, která zapíná a vypíná používání této vymoženosti, a vlastnost Effects, s jejíž pomocí si můžete nadefinovat svoje vlastní efekty. Při zvolené události můžete efekt spustit
DXInput1.Joystick.Effects[0].Stop;
nebo zastavit
DXInput1.Joystick.Effects[0].Start;
Taktéž můžete nahrát uložený efekt (některé naleznete v adresáři DelphiX\FFEffects a mají příponu .ffe):
DXInput1.Joystick.Effects[0].LoadFromFile(`cesta k souboru ffe`);
Příklady na použití ForceFeedBacku naleznete v samplech DelphiX v adresáři Input\FFCondition a FFMachineGun.
Názornou ukázku dnes probíraných funkcí najdete v tomto souboru.
To by bylo pro dnešek vše. Příště si probereme použití komponenty SpriteEngine sestavenou k obsluze spritů – animovaných objektů.