În prima parte a acestei serii, am explorat elementele de bază ale cadrului Sprite Kit și am implementat ecranul de pornire a jocului. În acest tutorial, vom implementa clasele principale ale jocului.
Swift este un limbaj orientat pe obiecte și vom profita de acest lucru prin separarea tuturor entităților jocului în propriile clase. Vom începe prin implementarea Invadator
clasă.
Invadator
ClasăInvadator
ClasăSelectați Nou > Fişier… din Xcode Fişier meniu, alegeți Cocoa Touch Class de la iOS> Sursă secțiune și faceți clic pe Următor →. Denumiți clasa Invadator
și asigurați-vă că acesta moștenește SKSpriteNode
. Asigura-te ca Limba este setat sa Rapid. Introduceți codul următor Invader.swift.
import Import UIKit Clasa SpriteKit Invadator: SKSpriteNode var invaderRow = 0 var invaderColumn = 0 init () permite texture = SKTexture (imageNamed: "invader1") super.init (textură: textură, culoare: SKColor.clearColor texture.size ()) auto.name = "invader" cerut init? (coder aDecoder: NSCoder) super.init (coder: aDecoder) func fireBullet (scena: SKScene)
Invadator
clasa este o subclasă a SKSpriteNode
clasă. Are două proprietăți, invaderRow
și invaderColumn
. Invadatorii sunt aliniate într-o rețea, la fel ca în jocul Space Invaders. Cele două proprietăți ne oferă o modalitate ușoară de a urmări ce rând și coloană se află în invadator.
În init
metodă, inițiază o SKTexture
instanță. init (imageNamed :)
metoda ia o imagine ca parametru. Apoi invocăm inițializatorul superclasei, trecând în textură
, SKColor.clearColor
pentru culoare
parametru și pentru mărimea
parametru treceți în mărimea texturii. În cele din urmă, am setat numele la "invadator"
astfel încât să îl putem identifica mai târziu.
init
metoda este un inițializator desemnat, ceea ce înseamnă că trebuie să delegăm inițializarea până la un inițializator desemnat al Invadator
superclaj. De aceea invocăm init (textura: culoare: dimensiunea :)
metodă.
S-ar putea să vă întrebați de ce este necesar init (coder :)
metoda este acolo, de asemenea. SKSpriteNode
este în conformitate cu NSCoding
protocol. init (coder :)
metoda este marcată după cum este necesar, ceea ce înseamnă că fiecare subclasă trebuie să suprascrie această metodă.
Vom implementa fireBullet
mai târziu în acest tutorial.
În acest pas, vom adăuga invadatorii la GameScene
. Deschis GameScene.swift și șterge totul înăuntru didMoveToView (_ :)
metodă, precum și totul în cadrul touchesBegan (_: withEvent :)
metodă. Conținutul GameScene.swift Ar trebui să arate așa.
import SpriteKit clasa de jocScene: SKScene override func didMoveToView (vedere: SKView) suprascrie func atingeBegan (atinge: Set, cu evenimentul Eveniment: UIEvent) / * Chemat atunci când începe o atingere * / suprascrie func actual (actualTime: CFTimeInterval) / * Chemată înainte ca fiecare cadru să fie redat * /
Vom avea o variabilă globală în proiectul nostru, invaderNum
. Această variabilă este utilizată pentru a urmări nivelul curent al jocului. Prin declararea acesteia ca fiind o variabilă globală, avem acces la invaderNum
pe scenele. Pentru a declara variabila ca fiind o variabilă globală, o declanșăm în afara GameScene
clasă.
importați SpriteKit var invaderNum = 1 clasă Scor de joc: SKScene ...
Apoi, adăugați următoarele proprietăți la GameScene
clasă.
Clasa de jocuriScene: SKScene let rowsOfInvaders = 4 var invaderSpeed = 2 let leftBounds = CGFloat (30) var rightBounds = CGFloat (0) var invadersWhoCanFire: [Invadator] = [] override funk didMoveToView
rowsOfInvaders
proprietatea este cât de multe rânduri de invadatori jocul va avea și invaderSpeed
proprietatea este cat de repede invadatorii se vor muta. leftBounds
și rightBounds
proprietățile sunt utilizate pentru a crea o marjă în partea stângă și dreaptă a ecranului, limitând mișcarea invadatorilor în direcțiile din stânga și din dreapta. Și, în final, invadersWhoCanFire
proprietatea este o matrice folosită pentru a urmări ce invadatori pot declanșa un glonț.
Adaugă setupInvaders
mai jos actualizare (currentTime :)
metodă în GameScene
clasă.
func setupInvaders () var invaderRow = 0; var invaderColumn = 0; let numberOfInvaders = invaderNum * 2 + 1 pentru var i = 1; eu <= rowsOfInvaders; i++ invaderRow = i for var j = 1; j <= numberOfInvaders; j++ invaderColumn = j let tempInvader:Invader = Invader() let invaderHalfWidth:CGFloat = tempInvader.size.width/2 let xPositionStart:CGFloat = size.width/2 - invaderHalfWidth - (CGFloat(invaderNum) * tempInvader.size.width) + CGFloat(10) tempInvader.position = CGPoint(x:xPositionStart + ((tempInvader.size.width+CGFloat(10))*(CGFloat(j-1))), y:CGFloat(self.size.height - CGFloat(i) * 46)) tempInvader.invaderRow = invaderRow tempInvader.invaderColumn = invaderColumn addChild(tempInvader) if(i == rowsOfInvaders) invadersWhoCanFire.append(tempInvader)
Avem invaderRow
și invaderColumn
variabile care vor fi folosite pentru a seta proprietățile cu același nume pe invadator. Apoi, folosim un dublu pentru
pentru a stabili invadatorii pe ecran. Există o mulțime de conversii de tip numeric, deoarece conversia rapidă nu implică conversia numerelor la tipul corespunzător. Trebuie să o facem noi înșine.
Inițializăm mai întâi un nou Invadator
, tempInvader
, și apoi să declare o constantă invaderHalfWidth
care este de jumătate din dimensiunea tempInvader
.
Apoi, calculam xPositionStart
astfel încât invadatorii să fie întotdeauna aliniați în mijlocul scenei. Obținem jumătate din lățimea scenei și scăpăm jumătate din lățimea invadatorului, deoarece punctul de înregistrare implicit este centrul (0,5, 0,5) al spritei. Apoi, trebuie să scădem cât mai mult lățimea invadatorului invaderNum
este egal cu, și adăugați 10 la această valoare, deoarece există 10 puncte de spațiu între invadatori. Acest lucru poate fi puțin greu de înțeles la început, deci luați-vă timpul să o înțelegeți.
Apoi am setat invadator
„s poziţie
proprietate, care este a GGPoint
. Folosim un pic mai mult matematica pentru a ne asigura ca fiecare invadator are 10 puncte intre ele si fiecare rand are 46 de puncte intre ele.
Noi atribuim invaderRow
și invaderColumn
proprietăți și adăugați tempInvader
la scena cu addChild (_ :)
metodă. Dacă acesta este ultimul rând de invadatori, am pus tempInvader
în invadersWhoCanFire
mulțime.
setupInvaders
metoda este invocată în didMoveToView (_ :)
metodă. În această metodă, am setat și culoare de fundal
proprietate la SKColor.blackColor
.
override funcția didMoveToView (vizualizare: SKView) backgroundColor = SKColor.blackColor () setupInvaders ()
Dacă testați aplicația, ar trebui să vedeți 4 rânduri de 3 invadatori. Dacă ați setat invaderNum
la 2, ar trebui să vedeți 4 rânduri de 5 invadatori aliniate în mijlocul scenei.
Jucător
ClasăJucător
ClasăCreaza un nou Cocoa Touch Class numit Jucător
care este o subclasă de SKSpriteNode
. Adăugați următoarea implementare la Player.swift.
Importați importul UIKit Clasa SpriteKit Player: SKSpriteNode init () permite texture = SKTexture (imageNamed: "player1") super.init (textură: textură, culoare: SKColor.clearColor ) init (coder aDecoder: NSCoder) super.init (coder: aDecoder) priv func animate () var playerTextures: [SKTexture] = [] pentru i în 1 ... 2 playerTextures.append (SKTexture : "player \ (i)")) a permite playerAnimation = SKAction.repeatActionForever (SKAction.animateWithTextures (playerTextures, timePerFrame: 0.1)) self_runAction (playerAnimation) func die () func fireBullet (scena: SKScene)
init
metoda ar trebui să pară familiarizată. Singura diferență este că folosim o imagine diferită pentru configurația inițială. Sunt numite două imagini player1 și player2 în folderul de imagini, unul are propulsorul angajat și celălalt are propulsorul oprit. Vom schimba în mod constant între aceste două imagini, creând iluzia unei arderi și a unei arme. Aceasta este ceea ce anima
metoda face.
În anima
metoda, avem o matrice playerTextures
care va păstra texturile pentru animație. Adăugăm SKTexture
obiecte la această matrice utilizând un a pentru-in
buclă și o gamă închisă utilizând operatorul de domeniu închis. Utilizăm interpolarea șirului pentru a obține imaginea corectă și pentru a inițializa o imagine SKTexture
instanță.
Declarăm o constantă, playerAnimation
, care invocă repeatActionForever
metodă a SKAction
clasă. În acea acțiune, noi invocăm animateWithTextures (_: timePerFrame :)
. animateWithTextures (_: timePerFrame :)
metoda ia ca parametri o serie de texturi și cantitatea de timp pe care fiecare textura este afișată. În cele din urmă, invocăm runAction (_ :)
și treceți în playerAnimation
.
Celelalte metode vor fi implementate mai târziu în acest tutorial.
Declarați o proprietate constantă numită jucător
la GameScene
clasă.
Clasa GameScene: SKScene ... var invadersWhoCanFire: [Invadator] = [Invadator] () permite jucatorului: Player = Player ()
Apoi, adăugați setupPlayer
mai jos setupInvaders
metodă.
func setupPlayer () player.position = CGPoint (x: CGRectGetMidX (auto.frame), y: player.size.height / 2 + 10) addChild (player)
Ar trebui să cunoașteți implementarea setupPlayer
metodă. Am setat jucător
„s poziţie
și adăugați-o la scenă. Cu toate acestea, folosim o nouă funcție, CGRectGetMidX (_ :)
, care returnează centrul unui dreptunghi de-a lungul axei x. Aici folosim scenă
's cadru.
Acum puteți invoca setupPlayer
metodă în didMoveToView (_ :)
metodă.
suprascrie func didMoveToView (vizualizare: SKView) backgroundColor = SKColor.blackColor () setupInvaders () setupPlayer ()
Dacă testați aplicația, ar trebui să vedeți că player-ul a fost adăugat în partea de jos a ecranului cu propulsoarele angajate și ardere.
Glonţ
ClaseGlonţ
clasăCreaza un nou Cocoa Touch Class numit Glonţ
care este o subclasă a SKSpriteNode
clasă.
importați Importul UIKit Clasa SpriteKit Bullet: SKSpriteNode init (imageName: String, bulletSound: String?) permite textură = SKTexture (imageNamed: imageName) super.init (textură: textură, culoare: SKColor.clearColor () (codul: aDecoder) dacă este necesar (bulletSound! = nil) runAction (SKAction.playSoundFileNamed (bulletSound !, waitForCompletion: false)
init
metoda ia doi parametri, imageName
și bulletSound
. Al doilea parametru este opțional. Jucătorul va juca un sunet cu laser de fiecare dată când este declanșat un glonț. Nu am invadatorii să facă asta în acest joc, deși cu siguranță ai putea. Acesta este și motivul pentru care sunetul glonțului este un parametru opțional. Puteti chiar folosi un sunet diferit pentru fiecare.
Prima parte ar trebui să fie familiară, deși noi creăm acum textură
cu orice imagine a fost trecută ca primul argument. Acest lucru vă va permite să utilizați diferite imagini pentru gloanțele jucătorului și invadatorilor, dacă doriți.
Dacă bulletSound
nu este zero
, conducem un SKAction
metodă playSoundFileNamed (_: waitForCompletion :)
. Această metodă ia ca parametri a Şir
, care este numele fișierului audio care include extensia și a bool
, waitForCompletion
. waitForCompletion
parametru nu este important pentru noi. Dacă ar fi fost setat Adevărat
, atunci acțiunea ar dura mult timp fișierul de sunet este.
InvaderBullet
ClasăCreaza un nou Cocoa Touch Class numit InvaderBullet
care este o subclasă a Glonţ
clasă.
importul UIKit import SpriteKit clasa InvaderBullet: Bullet suprascrie init (imageName: String, bulletSound: String?) super.init (imageName: imageName, bulletSound: bulletSound) init (coder aDecoder: NSCoder) super.init : aDecoder)
Punerea în aplicare a directivei InvaderBullet
clasa ar putea să nu aibă prea mult sens, pentru că noi numim doar init (imageName: bulletSound :)
metoda superclasei în init (imageName: bulletSound :)
initializare. Cu toate acestea, va fi mult mai logic de ce este creat acest mod când adăugăm codul pentru detectarea coliziunilor.
PlayerBullet
ClasăCreaza un nou Cocoa Touch Class numit PlayerBullet
care este, de asemenea, o subclasă a Glonţ
clasă. După cum puteți vedea, punerea în aplicare a PlayerBullet
clasa este identică cu cea a InvaderBullet
clasă.
importul UIKit import SpriteKit class PlayerBullet: Bullet suprascrie init (imageName: String, bulletSound: String?) super.init (imageName: imageName, bulletSound: bulletSound) init (coder aDecoder: NSCoder) super.init : aDecoder)
În acest tutorial, am creat și implementat câteva dintre clasele cheie ale jocului. Am adaugat o grilă de invadatori la scena si nava spatiala pe care jucatorul o va controla. Vom continua să lucrăm cu aceste clase în următoarea parte a seriei în care implementăm gameplay-ul.