Ako naprogramovať shmup pre Apple Watch
Návod na shmup pre Apple Watch: virtuálne rozlíšenie, ovládanie korunkou, kolízie obdĺžnikmi, pooling, levely ako tabuľka časov a generátor vĺn.

Shmup (shoot 'em up, strieľačka, v ktorej loď letí proti vlnám nepriateľov) na Apple Watch naráža na tri veci: malý displej, prst, ktorý zakryje polovicu hry, a rôzne veľkosti hodiniek. Riešia sa tromi rozhodnutiami: celá hra beží v pevnej mriežke 84 × 48 bodov, kolízie sa počítajú ručne obdĺžnikmi a levely sú tabuľky s časmi, nie kód. Loď sa ovláda korunkou Digital Crown a strieľa sama.
Postup ukazujeme na hre Space Impact Watch, remaku strieľačky Space Impact z telefónu Nokia 3310 z roku 2000, ktorá beží na hodinkách aj na iPhone a iPade. Príklady sú zo SpriteKitu, 2D herného frameworku od Apple, ale princípy platia pre každý shmup na malú obrazovku.
Pevné virtuálne rozlíšenie 84 × 48
Najprv sa rozhodnite, v akých jednotkách bude hra počítať. Ak použijete body obrazovky, svet bude na každej veľkosti hodiniek inak veľký. Lepšie je zvoliť malé virtuálne rozlíšenie a všetko počítať v ňom. V našej hre je to 84 × 48, presne ako mal displej Nokie 3310. Pozície, rýchlosti, veľkosti spritov aj dráhy nepriateľov sú v týchto jednotkách. Pri štarte scény sa raz vypočíta, koľko bodov obrazovky má jeden virtuálny pixel (šírka scény deleno 84), a všetko sa ním len vynásobí.

Čo tým získate:
- Rovnaký vzhľad na každom zariadení. Hra vyzerá rovnako na každej veľkosti hodiniek aj na iPade, mení sa len veľkosť bloku.
- Level dizajn v malých celých číslach. Nepriateľ letí vo výške 13, raketa zatáča v bode x = 20.
- Jednoduchú grafiku. Sprity sú jednofarebné a kreslené v desaťnásobnej veľkosti, jeden virtuálny pixel je v zdrojovom obrázku blok 10 × 10. Farbu dostanú až v hre. Na svetlých leveloch sú čierne na zelenom pozadí, na tmavých sa to otočí.
Ovládanie korunkou a automatická streľba
Na hodinkách prst zakryje polovicu hry, preto sa loď neovláda dotykom. Pohyb rieši Digital Crown: otočenie korunky posunie loď hore alebo dole. Pridajte nastavenie citlivosti a možnosť otočiť smer.
Streľba je automatická, v našej hre každých 0,4 sekundy, od štvrtého levelu každých 0,3. Displej slúži len na jedno gesto: potiahnutím doprava hráč použije jednu z troch špeciálnych zbraní.

Na hodinkách je vibrácia pri zásahu rovnako dôležitá ako animácia, malý výbuch na displeji si hráč ľahko nevšimne. Haptiku volajte cez jedno rozhranie (zásah, smrť nepriateľa, porazený boss), ktoré každá platforma vykoná po svojom: hodinky vibráciou, iPhone vlastným spôsobom. Verzia pre telefón nemá korunku, namiesto nej má tlačidlá na displeji, ktoré používajú rovnaké nastavenie citlivosti aj smeru.

Herná slučka v jednej scéne
Celá hra môže byť jedna scéna s jednou slučkou:
každý snímok:
posuň všetky objekty
skontroluj kolízie
podľa času v leveli pridaj nových nepriateľov
Veci pridávajte v poradí, v ktorom sa dajú čo najskôr testovať:
- Streľba a pohyb hráča. Bez nich sa nedá nič otestovať.
- Nepriatelia a kolízie. Prvému nepriateľovi stačí letieť rovno doľava a zomrieť po jednom zásahu.
- Vibrácie a animácie zásahu. Na malom displeji bez nich hráč nevie, že zasiahol.
- Pozadie a HUD. Životy, skóre, počet špeciálnych zbraní. Ak HUD na niektorom leveli prekáža, presuňte ho dole.
Na konci máte hrateľnú slučku so životmi, skóre, výbuchmi, pozadím a respawnom hráča. Ak hernú logiku držíte oddelene od vykresľovania a vstupu, môžu ju zdieľať verzie pre hodinky aj telefón.
Kolízie obdĺžnikmi namiesto fyzikálneho enginu
SpriteKit má fyzikálny engine a ponúka sa použiť ho aj na kolízie. Každý objekt dostane fyzikálne telo vytvorené z obrysu spritu, presnú detekciu kolízií a kategóriu (hráč, nepriateľ, strela, špeciálna zbraň) a engine sám hlási dvojice, ktoré sa dotkli. Apple v dokumentácii k fyzikálnym telám uvádza, že telá z alfa kanála textúry sú najpresnejšie a zároveň výpočtovo najdrahšie. V našej hre sme to skúsili a vrátili sme sa k ručnej kontrole.
Ručná kontrola je jedna funkcia, ktorá po sebe prejde dvojice skupín a porovná obdĺžniky:
pre každú dvojicu skupín:
(hráč a nepriatelia, hráč a strely, strely a nepriatelia, strely a strely)
pre každý objekt A z prvej skupiny a objekt B z druhej:
ak sa obdĺžnik A prekrýva s obdĺžnikom B:
vyrieš zásah

Výhody: poradie kontrol máte pod kontrolou a celé pravidlo „čo sa stane pri zásahu“ je na jednom mieste. Nepresnosť je malá, lebo na mriežke 84 × 48 sú sprity také drobné, že obdĺžnik a skutočný obrys sa líšia len o pár virtuálnych pixelov.
Pooling len tam, kde sa oplatí
Pooling znamená, že objekt po zániku nezmažete, len ho skryjete a nabudúce použijete znova. Je lákavé poolovať všetko vrátane výbuchov a power-upov. Má to však cenu: každá kolízia a každý update musí najprv overiť, či je objekt vôbec živý. Stačí jedna zabudnutá kontrola a skrytý nepriateľ zabije hráča alebo skrytá strela zostrelí raketu. Keď sme v našej hre pooling zo všetkého odstraňovali, mazali sme hlavne tieto kontroly.
Jednoduché pravidlo: poolujte to, čoho je veľa a vzniká to stále rovnako. Hráč si pri štarte vytvorí 21 striel a potom ich len recykluje. Nepriatelia a ich strely sa tiež znovu používajú, výbuchy a power-upy vznikajú a zanikajú normálne.
Levely ako tabuľka časov
Level nemusí byť kód, stačí zoznam záznamov. Každý záznam hovorí, čo sa objaví, v ktorej sekunde, v akej výške a ako sa pohybuje. Pohyb je zoznam bodov, cez ktoré nepriateľ letí rovnakou rýchlosťou. Voliteľne pribudnú časy výstrelov, výpad bossa alebo generátor menších nepriateľov.
každý snímok:
čas = teraz - začiatok levelu - čas v pauze
pre každý záznam v tabuľke levelu:
ak záznam ešte nebol použitý a čas > záznam.čas:
vytvor objekt podľa záznamu
označ záznam ako použitý

Takto zapísaný level sa ľahko ladí: posunúť vlnu o pol sekundy znamená zmeniť jedno číslo. Na časovej osi je vidno aj rytmus, o ktorý ide: krátka vlna, pauza, iný typ nepriateľa, power-up pred ťažším úsekom.

Nevýhodu cítiť pri väčších zmenách. Najhustejší level našej hry má 71 riadkov a taká tabuľka sa bez editora číta zle. Výhodnejšie je zapisovať levely ako vlny (skupina nepriateľov s jedným vzorom pohybu), nie ako jednotlivé lode.
Nekonečný režim z jedného pseudonáhodného čísla
Pre rebríček (v našej hre Game Center) potrebujete režim, ktorý nekončí. Ručne písanú tabuľku v ňom nahradí generátor, ktorý ju vyrába za behu. Vyrobí 20-ciferné pseudonáhodné číslo a jednotlivé dvojice číslic rozhodnú o jednej vlne:
číslo = ďalšie pseudonáhodné 20-ciferné číslo
typ = power-up, ak číslice 4 až 5 > 90, inak nepriateľ
sprite = číslice 1 až 2 modulo počet druhov nepriateľov
pauza pred vlnou = číslica 3 / 2 sekundy (aspoň 1)
výška = číslica 7, prepočítaná na výšku plochy
vzor pohybu = číslice 10 až 11 modulo 10
počet lodí vo vlne = číslica 17 / 2 + 1
rýchlosť = číslica 13 × (1 + poradie vlny / 10), v rozsahu 20 až 50
každá tridsiata vlna = boss, generovanie stojí, kým boss žije
Seed generátora (počiatočná hodnota) nechajte v hre pevný. Každý hráč potom dostane rovnaké poradie vĺn a skóre v rebríčku sa dá porovnávať.

Ako sa takýto režim vyvíja, ukazuje simulácia generátora mimo hry (300 vĺn, rovnaký seed ako v hre). Prvý boss príde po 29 vlnách, teda po 74 nepriateľoch a 3 power-upoch, zhruba po 130 sekundách. Prvých 30 vĺn letí minimálnou rýchlosťou 20, lebo jedna číslica je ešte menšia ako dolná hranica. Priemerná rýchlosť potom rastie na 28,5, 37,5 a 41, od 120. vlny je väčšina nepriateľov na maxime. Power-up je približne každá jedenásta vlna.

Slabina je, že generátor nepozná rytmus. Ručný level strieda tlak a oddych, generátor nie. Čiastočne to rieši pauza počas bossa a rast rýchlosti, ale ručne písané levely sa hrajú lepšie.
Limity tohto prístupu
- Žiadne automatické testy. Všetko sa overuje ručne v simulátore a na hodinkách.
- Globálny stav. Väčšina stavu hry sú globálne premenné jednej scény. Pre hru len na hodinky je to pohodlné, pri pridaní verzie pre iPhone už nie.
- Levely bez editora. Tabuľka časov sa dobre ladí po malých krokoch, pri väčších zmenách by si zaslúžila editor.
Ak robíte hru na hodinky alebo inú malú obrazovku a chcete s niečím pomôcť, napíšte nám. Ako generujeme hlavolamy v ďalšej našej aplikácii, sme opísali v článku o generátore sudoku.


