Programování flash her – 7 – Ovládání pomocí kláves

24.1.2014 by: Aimia

Od Kristiána jsem dostal dotaz, jak na ovládání flash her. V tomto díle popíši jak pracovat s klávesnicí, které se hodí pro akční hry. Tj. kdy potřebujeme, ať raketka letí vlevo když držíme tlačítko vlevo a zastaví když jej pustíme… Na konci článku najdete zdrojáky ke stažení.

Ještě trošku odbočím. Základní způsob jak ovládat hru myší a klávesami jsem uvedl v předchozím článku http://blog.aimia.cz/2012/12/programovani-flash-her-4-herni-smycka/. Stáhněte si příklad a projděte si ho, ať máte alespoň představu.

Trocha teorie
Abychom mohli detekovat ve flashi stisk klávesy, musíme přidat listener na událost KeyboardEvent.KEY_DOWN (stisk klávesy). Tahle událost se volá, když je stisknuta jakákoliv klávesa. K ovládání hry by to mohlo stačit, ale potřebujeme, abychom ovládání hráče/raketky apod. řešili v herní smyčce(pohyb, akce apod. budeme přepočítávat podle uběhlého času(elapsedtime), aby hra běžela stejně i na pomalejších počítačích).

Takže potřebujeme přidat ještě listener na událost KeyboardEvent.KEY_UP. Ta se volá při uvolnění tlačítka.

stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUp);

Pozn.: KeyboardEvent události můžete detekovat přímo na stage, nebo i na jednotlivých objektech(Display Object). Dejte si ale pozor na chybu, že přiradíte listener přímo objektu(třeba vaší raketce), ale ona v průběhu hry ztratí focus(např. hráč klikne jinde), a události chodit přestanou.

Pole kláves
Pro uložení stisklých kláves potřebujeme pole. Použiji typ pole Dictionary, je na to nejvhodnější. Dictionary je pole, které má klíč a hodnotu. Klíč je identifikátor pole(může to být číslo i řetězec). Výhodou je že toto pole se tvoří dynamicky, nemusíte znát na začátku jeho velikost, můžete přidávat prvky donekonečna. Při stisku jakékoliv klávesy použijeme jako klíč kód klávesy(keyEvent.keyCode).

private var keys:Dictionary;            // pole vsech moznych klaves

Teď máme vše připravené. Přidáme funkce, které budou řešit stisk KEY_UP a KEY_DOWN.

// Vola se pri povoleni stisku klavesy
private function keyUp(event:KeyboardEvent):void {
   keys[event.keyCode]    = false;    //     Klavesa pustena, nastavím na false
}
 
// Vola se pri stlaceni klavesy
private function keyDown(event:KeyboardEvent):void {
   keys[event.keyCode]    = true;        // Klavesa stisknuta, nastavím na true
}

KeyboardEvent obsahuje různé informace o stisklé/puštěné klávese. Pro nás je důležitý keyCode, což je kód klávesy. Všechny kódy které můžete použít najdete ve třídě Keyboard.

V kódu vidíte co se stane. Když držím např. klávesu LEFT, nastavím na keys[Keyboard.LEFT] = true (teda v tomto případě  event.keycode má hodnotu Keyboard.LEFT) Pokud klávesu pustím, nastaví se keys[Keyboard.LEFT] = false;

Zpracování stisklých kláves
Poslední věc co budeme dělat, je zpracování kláves. Teď máme v poli stisklé klávesy s hodnotou true, ostatní v poli buď nejsou nebo jsou false.

Přidáme metodu processInput, která se volá v herní smyčce a nedělá nic jiného, než že projde všechny klávesy, kterými chceme hru ovládat a zjišťuje jestli nejsou true. Pokud jsou true(stisklé), provede nějakou akci. Používáme elapsedTime, takže hra poběží konzistentně i na slabších strojích.

private function processInput(elapsedTime:Number):void {
   var step:Number = 100 * elapsedTime;    // posun přepočítávám podle uběhnutého času, aby bylo chování stejné při různém fps. 100 jsem si určil rychlost
   if (keys[Keyboard.LEFT])        // pokud je klavesa true(stiskla), proved akci
      shape.x -= step;
   if (keys[Keyboard.RIGHT])
      shape.x += step;
   if (keys[Keyboard.UP])
      shape.y -= step;
   if (keys[Keyboard.DOWN])
      shape.y += step;
   if (keys[Keyboard.SPACE])
     trace("Strelba nebo tak neco!")
}

 

Zdrojové kódy
KeyboardInput.zip zdrojáky ke stažení.

Jiné chování kláves
Poslední věc co chci zmínit – tento způsob je výborný pro akční hry. Nehodí se ale např. na tlačítka – pokud chcete do hry přidat tlačítko, které je ovládané i stiskem klávesy, stalo by se to že by se stisk tlačítka zavolal několikrát(podle doby držení klávesy hráčem). Proto je na tlačítka lepší použít vlastní KEY_UP listener addEventListener(KeyboardEvent.KEY_UP, keyUp); takže se událost zavolá až při uvolnění klávesy.

Dá se to řešit i s použitím kódu z tohoto tutoriálu, ale museli byste si do nějaké proměnné uložit, že už bylo tlačítko stisklé a tuto proměnnou vynulovat až když hráč klávesu uvolní.

Filed under: Nezařazené

Comments

6 komentářů to “Programování flash her – 7 – Ovládání pomocí kláves”
  1. Kristián napsal:

    Ahoj, moc díky za pěkný článek, snad jsem ho pochopil správně teďka ho půjdu vyzkoušet :). Ještě jednou moc díky :).

  2. reptile napsal:

    Parada. Inak mam otazku. Ked nacitam obrazok png ako triedu bitmap tak nefunguje shape.scaleX a podobne. Funguje iba posuv. A este jednu otazku. Ked mam hru, kde je objekt ktory, ked zasiahnem ma zmiznut, je lepsie pouzit remove child, alebo iba shape.visible=false?

    • Aimia napsal:

      Pokud je objekt přidaný ve scéně, flash jej každý frame prochází(i když jej nevykreslí, nějaký čas to sežere). Proto je lepší removeChild. Visible=false použij pokud chceš objekt znovu použít(třeba se narodí stejný typ nepřítele, ale jinde atd.)

  3. ReptileSVK napsal:

    [Embed(source = „D:/flash/obrazok.png“)]

    /* trieda, ktora obaluje embedovany obrazok */
    public static var pic2:Class;

    /* pretypovanie triedy do bitovej mapy */
    private var jahoda:Bitmap = new pic2();

    jahoda.scaleX=0,5; funguje. Som sa predtym pomylil, ale nefunguje pridanie listeneru, proste ho ingoruje.
    tu je listener: jahoda.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
    klikam na to jak sialeny a bez efektu. Ako keby tie listenery fungovali iba na Sprite, nie Bitmap.

    • Aimia napsal:

      Bitmap nedědí InteractiveObject(http://help.adobe.com/cs_CZ/FlashPlatform/reference/actionscript/3/flash/display/InteractiveObject.html), proto nereaguje na myš. Můžeš použít workaround – Vytvoř sprite a do něj vloř bitmapu, přidej listener na tento sprite.
      Takže něco takového:
      var spr:Sprite = new Sprite();
      spr.addChild(bitmap);
      spr.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      Někdy se i stane u oobjektů, že nefunguje myš. Může to být proto, že nad ním je jiný objekt, který událost zachytí(to používám např. pro dialogové okna – pod dialog vložím poloprůsvitnou černou plochu, která nepustí událost myši na objekty pod ní)

Leave a Reply