Creați Space Invaders cu Swift și Sprite Kit Implementarea de clase

Ce veți crea

Î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ă.

1. Implementarea Invadator Clasă

Pasul 1: Creați 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 SKSpriteNodeclasă. 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 initmetodă, 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 Invadatorsuperclaj. 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.

Pasul 2: Adăugați invadatorii în scenă

Î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 InvadatortempInvader, ș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 2ar trebui să vedeți 4 rânduri de 5 invadatori aliniate în mijlocul scenei.

2. Implementarea Jucător Clasă

Pasul 1: Creați Jucător Clasă

Creaza un nou Cocoa Touch Class numit Jucătorcare 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-inbuclă ș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.

Pasul 2: Adăugarea playerului în scenă

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.

3. Implementarea Glonţ Clase

Pasul 1: Creați Glonţ 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 boolwaitForCompletion.  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.

Pasul 2: Creați 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.

Pasul 3: Creați 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)

Concluzie

Î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.

Cod