Lekce 8 - Další částicové efekty ve SpriteKit
V minulé lekci, Dokončení kolizí ve SpriteKit, jsme zprovoznili kolize při střílení.
Hra již obstojně funguje, ale stále je to takové suché, nemyslíte? Skvělá příležitost přidat si částicové efekty exploze a laseru.
Efekt exploze
Začneme efektem exploze.
Vytvoření efektu
Vytvoříme tedy nový soubor pojmenovaný Explosion.sks
a jako
šablonu vybereme opět oheň.
Nejdůležitější je zde nastavení pro Emitter, kde zvolíme Birthrate
900
a Maximum 300
. Tím zajistíme, že se velmi
rychle zobrazí 300
částic a další již nebudou vytvořeny.
Designer v Xcode přehrává preview pořád dokola, při použití ale uvidíme
pouze jeden výbuch.
Dále jsem nastavil Lifetime na 0.4
, aby částice rychle
zmizely. Position Range 10
pro X a Y. Nastavení Angle na
0
° a Range na 360
° zajistí rovnoměrnou explozi do
všech směrů. Speed jsem nastavil na 200
a Range na
50
. Acceleration na 0
pro X a Y.
Potom jsem ještě upravil Color Ramp pro úpravu barvy. Kliknutím na slider přidáte druhý kontrolní bod a klikem na něj můžete upravit barvu. Zvolil jsem světle oranžovou a kontrolní bod posunul, viz obrázek níže:

Myslím, že výsledek nevypadá vůbec špatně :

Ve skutečné hře by to samozřejmě chtělo více variant exploze. Takže byste mohli první výsledek rozkopírovat a mírně upravit parametry, aby nepřátelé nebouchali tak repetitivně.
Spuštění efektu
Upravíme metodu missileHit()
, kde nejdříve nastavíme
name
obou objektů na nil
a vytvoříme explozi. Tu
nastavíme na bod kontaktu:
missile.name = nil enemy.name = nil if let explosion = SKEmitterNode(fileNamed: "Explosion") { explosion.position = point explosion.zPosition = 5 addChild(explosion) }
Jména nastavujeme na nil
jako pojistku, aby náhodou nedošlo k
rozpoznání druhého kontaktu mezi objekty, se kterými ještě pracujeme.
Pro odebrání nepřítele můžeme ještě vytvořit krátkou
SKAction
s animací, aby okamžitě nezmizel:
let fadeOut = SKAction.fadeIn(withDuration: 0.2) let sequence = SKAction.sequence([fadeOut, SKAction.removeFromParent()]) enemy.run(sequence)
Samozřejmě nezapomeňte odstranit původní volání
enemy.removeFromParent()
.
Možná si všimnete drobné chybky a sice, že můžeme zneškodnit nepřítele, který má již připravenou laserovou střelu. Pak to vypadá, že se objevila z prázdna. To vyřešíme později.
Efekt zásahu laserem
Zásah raketou máme, teď je čas na zásah hráče. Na závěr lekce tedy připravíme další částicový efekt a vyřešíme kolizi laseru a hráče. Později hráči přidáme životy, teď bude zatím nesmrtelný.
Vytvoření efektu
Laser by měl spíše způsobit menší kouř než plnohodnotnou explozi.
Přidáme si tedy nový soubor s částicemi a jako šablonu vybereme Smoke.
Birthrate jsem nastavil na 900
a Maximum na 10
. Dále
Lifetime Start na 0.5
a Range na 0.1
. Position Range
5
pro X a 10
pro Y. Dále Angle Start na
90
° a Range 180
°, takže dojde k pokrytí směru,
odkud bude hráč zasažen laserem. Speed Start nastavíme na 40
a
Range na 0
. A konečně Alpha Start 0.2
a Range
0.1
.
A výsledek:

Jako vždy můžete experimentovat a vytvořit si vlastní efekt nebo klidně několik a střídat je náhodně.
Opět platí, že opakování je vidět pouze v náhledu.
Přidání efektu
Přidání efektu po zasažení hráče je skoro stejné jako u raket a nepřátel. Připravíme si metodu pro reakci na zasažení hráče:
func laserHitPlayer(_ laser: SKNode, at point: CGPoint) {
}
Pro objekt hráče máme referenci přímo v GameScene
, takže
parametr není potřeba. Teď stačí v didBegin()
detekovat kolizi
laseru a hráče:
if nodeA.name == "laser" || nodeB.name == "laser" { if nodeA.name == "player" { laserHitPlayer(nodeB, at: contact.contactPoint) } else { laserHitPlayer(nodeA, at: contact.contactPoint) } }
Na konec předchozí podmínky pro rakety jsem přidal return
,
aby zbytečně metoda nezkoušela vyhodnotit druhou podmínku, když jsme kolizi
již zpracovali.
A nakonec zbývá doplnit metodu laserHitPlayer()
. Nejdříve
vymažeme jméno a přidáme efekt kouře:
laser.name = nil if let laserHit = SKEmitterNode(fileNamed: "LaserHit") { laserHit.position = point laserHit.zPosition = 5 addChild(laserHit) }
Efekt pohlcení střely lodí
Bylo by hezké nějak zapracovat s objektem laserové střely. Můžeme
zkusit vytvořit efekt, že je celá střela vlivem nárazu "pohlcena" lodí
hráče. To zní docela komplexně. Pomocí SKAction
můžeme
změnit škálu (rozměr) buď celkově nebo na ose X či Y. Když změníme
škálu Y na 0
, můžeme tím dosáhnout efektu, kdy bude animací
laserová střela zmenšena, jako by reagovala na zásah. Jenže bude zmenšena
do svého středu. Můžeme si ale pomoci druhou SKAction
, která
zmenšující se střelu posune po ose Y a tím navodí dojem, že se zmenšuje
přesně v bodě, kde trefila loď hráče
Protože je na střele již jedna aktivní SKAction
pro její
pohyb, tak nejdříve odstraníme všechny akce a potom pomocí
guard
přetypujeme objekt na SKSpriteNode
. Budeme
totiž potřebovat získat výšku:
laser.removeAllActions() guard let laser = laser as? SKSpriteNode else { return }
Nyní již stačí "jen" poskládat SKAction
do sekvence:
let shrink = SKAction.scaleY(to: 0, duration: 0.2) let move = SKAction.moveBy(x: 0, y: -laser.size.height / 2, duration: 0.2) let fadeOut = SKAction.fadeOut(withDuration: 0.1) let group = SKAction.group([shrink, move]) let sequence = SKAction.sequence([group, fadeOut, SKAction.removeFromParent()]) laser.run(sequence)
Můžeme zakomentovat nastavení timeru playerFireTimer
a
podívat se, jak zásah laserem bude vypadat:

Aktuálně hra vypadá takto:

V příští lekci, Přidání parallax efektu a životů hráče ve SpriteKit, už budeme dolaďovat drobnosti. Přidáme hráči životy a ukážeme si paralax efekt.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 4x (962.35 kB)
Aplikace je včetně zdrojových kódů v jazyce Swift