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
:
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:
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:
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