Programování her v Delphi – díl 5.: DirectInput

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

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?

DirectInput v DelphiX

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í.

Klávesnice

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.

Myš

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.

Joystick

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.

ForceFeedBack

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ů.

Diskuze (3) Další článek: Toshiba má barevný displej nové generace

Témata článku: , , , , , , , , , , , , , , , ,