IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

3. diel - Nepriatelia a ich pohyb vo SpriteKit

V predchádzajúcej lekcii, Pozadia, ovládanie hráča a časticové efekty vo SpriteKit , sme vytvorili pozadie, pridali loď hráča vrátane ovládania a celé to okorenili pomocou časticových efektov. Teraz je čas pridať hordy pohybujúcich sa nepriateľov.

Vlna nepriateľov

Vlny nepriateľov sa budú ľahko hýbať, aby bola hra živšie a hráč nemal tak jednoduché triafanie protivníkov. V prvom rade teda musíme vymyslieť, ako najlepšie vlnu nepriateľov vytvoriť. Určite nechceme nepriateľov pozicový manuálne a pre každého z treba ôsmich vymýšľať súradnice.

Najlepšie bude vytvoriť si pomocnú funkciu na vytvorenie celej nepriateľské vlny s využitím trošku tej náhody. Niečo podobné sa nám bude hodiť aj v prípade, že budeme chcieť zvýšiť obtiažnosť a pridať ďalšie nepriateľov.

Textúry nepriateľov

Ešte, než začneme, pretiahnite si do Assets.xcassets obrázky nepriateľov. Ja použil tie tri z prvej lekcie a volajú sa enemyBlack1, enemyBlack2 a enemyBlack3:

Obrázok nepriateľa 1 - Tvorba iOS hier vo Swift Obrázok nepriateľa 2 - Tvorba iOS hier vo Swift Obrázok nepriateľa 3 - Tvorba iOS hier vo Swift

Pokiaľ máte iné názvy alebo iný počet obrázkov, je s tým nutné počítať, až budeme vytvárať SKSpriteNode objekty.

SKNode

Pretože budeme chcieť so všetkými nepriateľmi hýbať, nepridáme je priamo do našej scény, ale vytvoríme si inštanciu SKNode, ktorú využijeme ako kotvu. Vďaka tomu môžeme potom rozhýbať túto jednu SKNode a tým sa budú hýbať všetci nepriatelia súbežne.

Ako prvý si teda vytvoríme inštanciu na úrovni našej GameScene triedy:

let enemyAnchor = SKNode()

Nastavenie kotvy

Opäť si vytvoríme pomocnú metódu setupEnemyAnchor() a nezabudneme ju zavolať v didMove(). Zatiaľ len pridá enemyAnchor do scény a nastaví pozíciu:

func setupEnemyAnchor() {
        enemyAnchor.position = CGPoint(x: 0, y: size.height - 200)
        addChild(enemyAnchor)
}

Generovanie vĺn

To bolo jednoduché, teraz potrebujeme kód pre generovanie vĺn nepriateľov. To už bude zložitejšie. Začneme vytvorením metódy createEnemyWave(). Zatiaľ bude brať ako parameter enemyCount typu Int, teda koľko nepriateľov chceme vytvoriť.

Teraz potrebujeme vymyslieť, ako nepriateľov pekne rovnomerne rozmiestniť vedľa seba. Po nejakom tom experimentovanie som došiel síce k celkom obsiahle metóde, na druhú stranu ale obsahuje minimum "magických čísel" a je celkom flexibilná. Kód nižšie teda všetok patrí postupne do metódy createEnemyWave().

Prototyp

Ako prvý si vytvoríme prototyp protivníka a pre ľahšie pozicovanie upravíme jeho anchorPoint:

let enemyTemplate = SKSpriteNode(imageNamed: "enemyBlack1")
enemyTemplate.anchorPoint = CGPoint(x: 0, y: 0.5)

Samozrejme si za "enemyBlack1" doplňte názov vášho obrázka pre nepriateľov. Neskôr urobíme náhodný výber, aby sme mali aj nejakú tú variabilitu.

Výpočty

Ďalej si pre výpočet uložíme šírku nepriateľa, šírku všetkých vo vlne a tiež konštantu pre rozostup medzi nimi:

let enemySize = enemyTemplate.size.width
let enemiesSize = enemySize * CGFloat(enemyCount)
let enemySpacing: CGFloat = 15

Už máme prípravy skoro hotové. Ešte potrebujeme zostávajúce šírku, aby sme mohli vypočítať správne odsadenie a nepriateľov zarovnať. Proste od šírky celej scény odrátame sumu šírok nepriateľov a medzier medzi nimi (medzier je o jednu menej). A rovno si pripravíme premennú xOffset pre výpočet súradnice, tá udáva koľko je vľavo pred vlnou nepriateľov voľného miesta:

let remainingSpace = size.width - enemiesSize - CGFloat(enemyCount - 1) * enemySpacing
let xOffset = remainingSpace / 2

Cyklus

Teraz sa môžeme presunúť k cyklu, ktorý vytvorí nepriateľov, nastaví im korektné pozíciu a pridá ich do scény za pomoci enemyAnchor:

for i in 0 ..< enemyCount {
}

Nasledujúci kód teda bude súčasťou cyklu. Najskôr urobíme kópiu z enemyTemplate:

let newEnemy = enemyTemplate.copy() as! SKSpriteNode

as! je tu v poriadku, pretože presne vieme, s akým objektom máme čo do činenia, takže sa pretypovanie určite povedie.

Zostáva finálny výpočet súradnice x daného nepriateľa a jej nastavenia:

let xPosition = xOffset + CGFloat(i) * (enemySize + enemySpacing)
newEnemy.position = CGPoint(x: xPosition, y: 50)

O korektné odsadenie sa vo výpočte stará xOffset a potom za pomoci i a veľkosti nepriateľa spoločne s medzerou získame finálny súradnici. Pre y je zatiaľ dočasná hodnota pre prvú vlnu nepriateľov.

Pridanie nového nepriateľa do vlny

Teraz už len stačí pridať pomocou addChild() nepriateľa našej kotve enemyAnchor:

enemyAnchor.addChild(newEnemy)

A metódu zavolať v didMove()

createEnemyWave(enemyCount: 5)

Môžeme sa presvedčiť, ako vyzerá výsledok:

Generovanie nepriateľov v iOS hre v SpriteKit a Swift - Tvorba iOS hier vo Swift

Ak máte obrázky nepriateľov, ktoré sú natočené dopredu ako loď hráča, bude nutné ich otočiť. Môžete to urobiť rovno s pomocou SpriteKit a to nastavením vlastnosti zRotation na .pi, čo obrázok otočí o 180 °. Tu to ale bude problém, pretože sme zmenili anchorPoint kvôli ľahšiemu pozicovanie a podľa neho sa bude SKSpriteNode tiež otáčať. Lepšie bude teda vykonať otočenie v grafickom editore.

Rozhýbanie s pomocou SKAction

Teraz si predstavíme prakticky nepostrádateľnou triedu SKAction, ktorá nám pomôže hru rozpohybovať. Je koncipovaná ako také stavebné bloky, keď každý robí jednu malú vec a môžeme ich reťaziť za sebou alebo spúšťať spoločne.

My zatiaľ SKAction použijeme na to, aby sa nepriatelia začali hýbať. Pretože máme pripravený enemyAnchor, tak nie je potrebné ich rozhýbava jednotlivo.

StartEnemyMovement ()

Vytvoríme si metódu startEnemyMovement() a rovno ju zavoláme v didMove(). Nasleduje implementácie tejto metódy.

Najskôr vytvoríme akciu pre pohyb doprava:

let moveRight = SKAction.moveBy(x: 35, y: 0, duration: 0.5)

Kde som vzal čísla? Odhad a experimentovanie, čo vyzerá v tejto situácii najlepšie. Pohyb doľava bude ešte jednoduchšie, pretože jednoducho otočíme túto akciu:

let moveLeft = moveRight.reversed()

Teraz z týchto akcií vytvoríme sekvenciu, čo je opäť typ SKAction. Je to vlastne taký zoznam, ktorý nám dovolí skladať akcie za seba:

let moveSequence = SKAction.sequence([moveRight, moveLeft, moveLeft, moveRight])

moveLeft je dvakrát za sebou, pretože prvá akcia vráti objekt do pôvodnej polohy a druhá ho už posunie doľava.

Čo ďalej? SKAction môžeme "spúšťať" na akékoľvek SKNode. Takže na enemyAnchor spustíme SKAction.forever, ktorá bude neustále opakovať našu sekvenciu pohybu:

enemyAnchor.run(SKAction.repeatForever(moveSequence))

A naši nepriatelia sa hýbu:

Pohyb nepriateľov vo SpriteKit v iOS hre - Tvorba iOS hier vo Swift

Môžete opäť vyskúšať a prípadne si skúsiť navrhnúť vlastné pohybovú sekvenciu. Trebárs zapojením súradnice y. V budúcej lekcii, Strieľanie rakiet a ďalšie časticové efekty vo SpriteKit , sa budeme venovať streľbe hráča.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 10x (143.54 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Swift

 

Predchádzajúci článok
Pozadia, ovládanie hráča a časticové efekty vo SpriteKit
Všetky články v sekcii
Tvorba iOS hier vo Swift
Preskočiť článok
(neodporúčame)
Strieľanie rakiet a ďalšie časticové efekty vo SpriteKit
Článok pre vás napísal Filip Němeček
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Autor se věnuje vývoji iOS aplikací (občas macOS)
Aktivity