DXInput v DelphiX aneb jak nadefinovat klávesy do her - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



C/C++

DXInput v DelphiX aneb jak nadefinovat klávesy do her

18. září 2001, 00.00 | V každé správné hře je potřeba zajistit interakci mezi uživatelem a hráčem, k tomu nám poslouží komponenta DXInput. Podívejme se, jak se s ní pracuje.

V seriálech o DelphiX jsme se doposud setkávali s tématy zabývající se grafikou. Ale v každé naší hře potřebujeme zajistit i dokonalou interakci mezi uživatelem a hrou. O to se postará DirectInput a pan Hori (autor DelphiX) to vyřešil po svém komponentou DXInput, jak jinak výborně.

V tomto článku se především budeme zabývat ovládáním klávesnice. Správně ošetřená počítačová hra by měla obsahovat mimo jiné i možnost předdefinování kláves.

Nejdříve bych stručně shrnul možnosti komponenty DXInput...

Komponenta je rozdělena do tří částí, jedna část se věnuje klávesnici, druhá myši a třetí joysticku. Jejich funkce a vlastnosti zapouzdřují třídy TKeyboard, TMouse, TJoystick a jsou odvozeny od univerzální nadřazené třídy TCustomInput.
Pro komunikaci se vstupním zařízením využijeme několik základních vlastností:

Enabled - povolíme nebo zakážeme čtení z rozhraní DirectInput
ActiveOnly - komponenta je aktivní, pracuje pouze, když je aktivní aplikace.
States - velmi důležitá vlastnost, signalizuje stavy zařízení. vlastnost nabývá hodnot isUp, isDown, isLeft, isRight, isButton1, ......., isButton32.
ButtonCount - počet tlačítek daného zařízení
Buttons - vrací, které tlačítka jsou stisknuty (myslíme tím tlačítka na myši, joysticku atd.)
BindInputStates - true chceme-li číst pomocí States ze všech zařízení (myš, klávesnice, joystick)

States je velmi univerzální vlastnost, pomocí níž můžeme zjistit, co bylo zadáno z libovolného zařízení (klávesnice, myši nebo joysticku).

Takže se podívejme, jak tyto znalosti zužitkovat. Uvažujme nějaký libovolný projekt využívající DelphiX, máme komponenty DXDraw, DXTimer a přidáme DXInput. V určitém časovém intervalu budeme sledovat, jaké podněty ze vstupních zařízení přichází. To v časovači zajistíme v události OnTimer


DXInput1->Update();

Tím zjistíme aktuální stav na zařízení. Dostaneme aktuální polohy zařízení. Dále potřebujeme zjistit, co se vlastně stalo:

if (DXInput1->States.Contains(isLeft) == true) // test na pohyb doleva

Využíváme vlastnost States (jde o množinu, proto porovnáváme přes Contains), zjišťujeme, zda-li nebyla stisknuta levá šipka, nebylo posunuto myší doleva a nebo páka joysticku nešla doleva. Nic víc již v podstatě nepotřebujeme vědět, je to jednoduché a spolehlivé.

Jenže nastane situace, kdy potřebujeme využít konkrétní zařízení a to už musíme využít vlastnosti Keyboard, Mouse nebo Joystick. Takže když chceme zjistit, jestli pouze šla myš doleva napíšeme místo výše uvedeného textu následující kód:

if (DXInput1->Mouse->States.Contains(isLeft) == true)

Rozeberme si stručně jednotlivé zařízení.

Mouse

Zde máme kromě již zmíněných vlastností ještě k dispozici hodnoty X, Y, Z. Říkají nám, o kolik se myš od posledního momentu posunula v souřadnicích X, Y a nebo Z.

Pohyb šipky po obrazovce pomocí myši zajistíme:

int mx, my; // globální čítače
. . . .
 mx = mx + DXInput1->Mouse->X; 
 my = my + DXInput1->Mouse->Y; 

Polohu kurzoru měníme od předchozí o DXInput1->Mouse->X v souřadnici X, resp. DXInput1->Mouse->Y v souřadnici Y. Když DXInput1->Mouse->X je záporná, pokud pohybujeme myší doleva a kladná při pohybu doprava. To anologicky platí i pro DXInput1->Mouse->Y. Když se myší nepohybuje jsou obě dvě hodnoty nulové.

Joystick

Stejnou konstrukci použijeme i při čtení z joysticku:

int jx, jy; // globální čítače
 . . . .
 jx = jx + DXInput1->Joystick->X; 
 jy = jy + DXInput1->Joystick->Y;

Sekce Joystick je mnohem obsáhlejší, najdeme zde kromě X, Y, Z i RangeX, RangeY a RangeZ. To znamená rozsah, ve kterém se s joystickem můžeme pohybovat. DeadZone (DeadZoneX, DeadZoneY a DeadZoneZ) je velmi výbornou vlastností, jak eliminovat stařecký třas v ruce. Tím docílíme, že do určité hodnoty vychýlení v daném směru nedojde k žádnému pohybu.

Klávesnice

Konečně jsme se prokousali k dnešnímu tématu, které jsem předeslal v nadpisu. Hráči hrající hry, které mi programátoři vytvoříme, jsou nevyzpytatelní a rozmlsaní. Jeden se chce pohybovat ve hře pomocí kurzorových šipek, druhý ne. Ten má rád zase písmenka. Někdo rád střílí shiftem, jiný zase přes ctrl. Programátor aby se zbláznil.
Naštěstí máme v DelphiX více způsobů, jak se z daným problémem elegantně vyrovnat.

Velice jednoduchý způsob, který vám nabízím je využití vlastnosti Keys. Jedná se o pole, které představuje všechny klávesy, co lze stisknout. Každá klávesa má svůj kód (index), no a když je příslušné tlačítko stisknuto má políčko v Keys hodnotu true. Následující kód vše objasňuje:

if (DXInput1->Keyboard->Keys['k'] == true) // testujeme, jestli nebylo stisknuto K.

Mi potřebujeme ve hře použít pro libovolnou akci libovolnou klávesu. Vytvoříme si proměnou nebo pole, kam si uložíme kódy kláves, pro určité akce.

char klavesy[6] = {37, 39, 38, 40, 17, 18}; // kódy kláves

Do pole jsem si uložil kódy kláves, pro akce: pohyb doleva, pohyb doprava, pohyb nahoru, pohyb dolu, střelba1, střelba2. V poli jsou zdánlivě uložena nesmyslná čísla, jsou to kódy kláves: levá šipka, pravá šipka, šipka nahoru, šipka dolu, ctrl a alt. Tyto čísla si běžně nepamatujeme, vyčteme je v příkladu, který jsem si pro vás připravil na konci článku.

Takže pokud, chcete uživateli dát tu možnost, aby si sám nastavil klávesy pro hru, udělejte mu speciální krásné menu, kde si vybere akci a přiřadí ji klávesu, vše podle vlastních představ.
Kterou klávesu uživatel stiskl, posléze otestujeme následujícím způsobem:

   int k;
   for (k = 0; k < 256; k++) {
      if (DXInput1->Keyboard->Keys[k] == true)   {
        klavesa = true;
        Label1->Caption = k; // vypíše stisknutou klávesu do labelu
        break;
      }
   }

   klavesy[0] = k; // pro pohyb vlevo, jsme nadefinovali klávesu

Teď již můžeme spustit samotnou hru (první level) a testovat jednotlivé akce a to jde udělat dvěma způsoby:

1. pomocí vlastnosti Keys[]

Testujeme zda nebyla stlačena některá z nadefinovaných kláves:

// pohyb doleva
               if (DXInput1->Keyboard->Keys[klavesy[0]] == true) {
. . . akce . . .
}

2. pomocí vlastnosti KeyAssigns[]

Vlastnost KeyAssigns[] přímo slouží k předdefinování kláves. A mi můžeme přiřadit libovolné klávesy pro libovolnou akci (isLeft, isButton1 .... atd).
Před spuštěním hry (prvního levelu) předdefinujete klávesy pro akce isLeft, isRight, isUp, isDown, isButton1 a isButton2.

    *DXInput1->Keyboard->KeyAssigns[isLeft] = klavesy[0];
    *DXInput1->Keyboard->KeyAssigns[isRight] = klavesy[1];
    *DXInput1->Keyboard->KeyAssigns[isUp] = klavesy[2];
    *DXInput1->Keyboard->KeyAssigns[isDown] = klavesy[3];
    *DXInput1->Keyboard->KeyAssigns[isButton1] = klavesy[4];
    *DXInput1->Keyboard->KeyAssigns[isButton2] = klavesy[5];

Nyní už ve hře stačí zjišťovat stisknuté klávesy podle toho, jak jsem vám popsal na začátku článku.

if (DXInput1->States.Contains(isLeft) == true) {

. . . akce . . .

}

No a na závěr si vyzkoušejte malý demonstrační příklad na předdefinování kláves.

Zdroják si stáhněte ZDE

 

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: