SpriteKit Basics Noder

SpriteKit er Apples 2D-spillmotor - en gjengivelsesmotor bygget på toppen av OpenGL. Det ble introdusert med iOS 7, og hver etterfølgende utgivelse har brakt tillegg til rammen. Med bruk av teksturerte sprites, en innebygd fysikkmotor, og den meget kraftige SKAction klassen, kan du veldig raskt bygge funksjonelle 2D-spill.

SpriteKit har innebygde redaktører for scener og partikler, en kamera node siden utgivelsen av iOS9, og innebygd støtte for fliser siden utgivelsen av iOS 10. Med disse nye tilleggene, blir SpriteKit raskt et kraftverk for å skape 2D-spill.

For å følge med denne opplæringen, bare last ned den medfølgende GitHub repo. Den har en mappe som heter Eksempelprosjektstarter. Åpne prosjektet i den mappen i Xcode, og du er klar til å gå!

noder

Noder er de grunnleggende byggeblokkene til SpriteKit, og SKNode er basen klassen av alle noder. Alle dine skjermaktiver vil være en SKNode eller en underklasse derav. SKNodes av seg selv gir ikke noe visuelt innhold, men. Alt visuelt innhold er tegnet ved hjelp av et av et antall forhåndsdefinerte SKNode subklasser. SKNodes og dens underkategorier deler flere egenskaper du kan endre. Noen av de viktigste er som følger.

  • stilling (CGPoint): knutepunktets posisjon innenfor foreldrenes koordinatsystem
  • XScale (CGFloat): skalerer bredden på en node med en multiplikator
  • ySkala(CGFloat): skalerer høyden på en knute med en multiplikator
  • alfa (CGFloat): gjennomsiktigheten av noden
  • zRotation (CGFloat): Euler-rotasjonen om z-aksen (i radianer)

En av de viktigste SKNodes er SKScene. Dette er rotnoden som alle andre noder legges til. Av seg selv, SKScene gir ingen visuelle elementer, men det viser noder som legges til det.

Scene noder

SKScenes er roten noder som alle andre noder er lagt til. Scenen animerer og gjør innholdet fra sine barnnoder. For å vise en scene, legger du den til en SKView (som er en underklasse av UIView og har derfor mange av de samme egenskapene som UIView).

I SpriteKit-startprosjektet vises den første scenen når prosjektet laster. For nå er dette bare en blank svart skjerm. Det vises når GameViewController påkaller presentScene (_ :) på visningsinstansen, passerer inn i scenen som en parameter:

overstyr func viewDidLoad () super.viewDidLoad () la scene = GameScene (størrelse: CGSize (bredde: 768, høyde: 1024)) la skView = self.view as! SKView skView.showsFPS = false skView.showsNodeCount = false skView.ignoresSiblingOrder = falsk scene.scaleMode = .aspektFill skView.presentScene (scene) // Present scenen

Ikke bekymre deg for de andre alternativene for nå; Jeg skal forklare dem senere i denne serien.

Opprette en scene

Mange spill har mer enn en skjerm eller scene, så vi vil lage en ny scene fra bunnen av og deretter vise den fra vår første scene.

Å velge Fil > Ny > Fil fra Xcode-menyen, og velg Cocoa Touch Class.

Forsikre Klasse er satt til NewScene og det Underklasse av er satt til SKScene. trykk neste og så Skape, sørge for at hovedmål er merket. Nedenfor er koden for NewScene.swift.

importere UIKit import SpriteKit klasse NewScene: SKScene 

Nå har vi to scener i prosjektet vårt, og har heller ikke noe visuelt innhold. La oss legge til en SKLabelNode (som alle noder, dette er en underklasse av SKNode). De SKLabelNodeeneste formål er å vise en tekstetikett.

Etikettnoder

Etikettnoder, implementert i SKLabelNode klassen, brukes til å vise tekst i spillet ditt. Du kan bruke egendefinerte skrifttyper hvis du ønsker det, men for vår hensikt vil vi bare holde oss til standarden, som viser hvit tekst og er satt til Helvetica Neue Ultra Light, 32 poeng.

Legg til følgende inne i didMove (i :) metode innenfor GameScene.swift. Denne metoden kalles umiddelbart etter at en scene er presentert av en visning. Vanligvis er det her du vil sette opp et hvilket som helst av spillets eiendeler og legge dem til scenen.

overstyr func didMove (for å se: SKView) la startGameLabel = SKLabelNode (tekst: "Start Game")

Her oppretter vi en SKLabelNode ved hjelp av bekvemmelighetsinitiatoren init (tekst :), som tar som en parameter en tekststreng.

Legge til og fjerne nodene

Bare initialisering av noder vil ikke vise dem i scenen. For å få noderne til å vise, må du påkalle addChild (_ :) metode på mottakskoden, passerer SKNode som du ønsker å legge til som en parameter.

Legg til følgende i didMove (i :) metode.

overstyr func didMove (for å se: SKView) la startGameLabel = SKLabelNode (tekst: "Start Game") addChild (startGameLabel)

De addChild (_ :) Metoden er ikke eksklusiv til SKScenes, men er en metode for SKNode. Dette lar deg bygge et komplekst hierarki av noder, kjent som "nodetreet". For eksempel, anta at du har et spilltegn, og du vil bevege armene og beina separat. Du kan opprette en SKNode forekomst og deretter legge til hver enkelt del som et barn av det SKNode (den inneholdende node er kjent som parentnoden). Dette vil gi deg fordelen av å kunne flytte tegnet som en helhet ved å flytte overordnet SKNode, men lar deg også flytte hver enkelt del enkeltvis.

En annen viktig metode for å legge til noder er insertChild (_: i :) metode, som setter et barn inn i en bestemt posisjon i mottakerens liste over barn. Når du legger til et barn i en node, opprettholder noden en bestilt liste over barn som refereres ved å lese nodeens barn eiendom. Det er viktig når du legger til flere noder til en forelderknutepunkt for å ta dette i betraktning, da rekkefølgen du legger til noder påvirker noen av aspektene av scenebehandling, inkludert trefftesting og gjengivelse.

For å fjerne en node, påkaller du removeFromParent () metode på noden du ønsker å fjerne.

Nå som vi har dekket å legge til og fjerne noder, kan vi flytte fokuset vårt tilbake til eksempelprosjektet. Hvis du husker, hadde vi nettopp lagt til en SKLabelNode til GameScene. Hvis du tester nå, ser du bare halvparten av teksten av til nederst til venstre på skjermen.

Hvorfor vises bare halvparten av teksten, skjønt? Nå vil det være en god tid å snakke om SpriteKits koordinat- og posisjoneringssystem.

Plassering og koordinater

Som standard plasserer SpriteKits koordinatsystem (0,0) nederst til venstre på skjermen. Også som standard plasserer SpriteKit noder slik at de plasseres på (0,0). Likevel, skjønt ... hvorfor ser vi bare halvparten av teksten? Dette skyldes at tekstetiketten som standard er sentrert horisontalt på etikettkodenes opprinnelse, som er ((0,0). Nedenfor er et bilde som viser hvordan en nodes koordinatsystem fungerer.

Nodens opprinnelse er på (0,0), og en positiv x-koordinat beveger seg til høyre og en positiv y-koordinat går opp på skjermen. Husk at en SKScene er en node, og derfor er opprinnelsen også (0,0).

Stille inn en knuteposisjon

Nå som vi har lært SpriteKits koordinatsystem fungerer og hvordan det plasserer noder, kan vi flytte SKLabelNode til en annen posisjon slik at vi kan se hele teksten. Legg til følgende i didMove (i :) metode innenfor GameScene.swift.

overstyr func didMove (for å se: SKView) la startGameLabel = SKLabelNode (tekst: "Start spillet") startGameLabel.position = CGPoint (x: size.width / 2, y: size.height / 2) addChild (startGameLabel)

Her plasserer vi etiketten til midten av scenen. De stilling Eiendommen er av typen CGPoint, som har x og y verdier som representerer et enkelt punkt i scenen.

Hvis du tester nå, bør du se at etiketten har blitt plassert i midten av scenen.

Bytter mellom scener

Som det står for øyeblikket, NewScene er bare en tom scene. La oss også legge til en etikett på den, og så kan vi lære å bytte mellom scener. Her er en utfordring: Prøv å legge til en etikett før du leser fremover NewScene det sier, "Gå tilbake"Min løsning er under.

Det første vi må gjøre er å legge til didMove (i :) metode. Legg til følgende til NewScene.swift.

klasse NewScene: SKScene override func didMove (for å se: SKView) 

Deretter må vi legge til etiketten. Legg til følgende i didMove (i :) metode som du har lagt til ovenfor.

overstyr func didMove (for å se: SKView) la goBackLabel = SKLabelNode (tekst: "Gå tilbake") goBackLabel.position = CGPoint (x: size.width / 2, y: size.height / 2) addChild (goBackLabel)

Dette legger til en etikett til  NewScene med teksten "Gå tilbake". Deretter skal vi implementere funksjonaliteten som denne etiketten antyder - vi svarer på berøringshendelser ved å bytte scener.

Å svare på berøring

Nesten alle mobile spill vil bli interaksjon med bruk av berøring. I dette trinnet lærer du hvordan du svarer på berøringshendelser i spillet ditt.

For å registrere hendelseshåndterere i spillet ditt, må du implementere visningen touchesBegan (_: med :) metode. Legg til følgende til GameScene.swift:

overstyr func touchesBegan (_ berører: Set, med hendelse: UIEvent?) print ("YOU TOUCHED")

Hvis du vil teste dette nå, vil du se DU TOUCHED trykt på konsollen når du berører skjermen. Det vi vanligvis trenger, er imidlertid å kunne fortelle når en bestemt knute har blitt rørt. For å gjøre dette trenger vi noen måte å finne og identifisere nodene. Vi lærer å gjøre dette, og så kom tilbake og avslutt touchesBegan (_: med :) metode.

Søker på nodetreet

For å kunne identifisere en node, bruker du noden Navn eiendom og søke på nodetreet for en node med det navnet. Noden er Navn Egenskapen tar en alfanumerisk streng uten tegnsetting. 

Det er et par metoder for å søke etter en node av dens Navn eiendom. Hvis du allerede har en referanse til noden, kan du bare sjekke den Navn eiendom direkte, som er hva vi skal gjøre i touchesBegan (_: med :) metode. Det er imidlertid viktig å vite hvordan du skal søke på nodetreet for en bestemt node ved navn, eller å søke etter en gruppe noder med samme navn.

De childNode (withName :) Metoden søker barna til en node for det spesifikke navnet som er sendt inn som en parameter.

De enumerateChildNodes (withName: ved hjelp av :) Metoden søker en nods barn og kaller blokkene en gang for hver matchende node den finner. Du bruker denne metoden når du vil finne alle noder som deler samme navn.

De senket (_ :) Metoden returnerer en rekke noder som samsvarer med navnet parameteren.

Du kan også søke etter noder ved hjelp av en avansert søkesyntax som lar deg søke hele scenetreet, eller søke etter et mønster i stedet for et eksakt navn, for eksempel. Denne avanserte søkefunksjonen ligger utenfor omfanget av denne opplæringen. Men hvis du ønsker å lære mer, kan du lese om i SKNode programmeringsreferanse.

Nå som vi vet hvordan du søker etter noder i nodetreet, la oss gi våre etiketter et navn.

Legg til følgende i didMove (i :) metode innenfor GameScene.swift.

overstyr func didMove (for å se: SKView) la startGameLabel = SKLabelNode (tekst: "Start spillet") startGameLabel.name = "startgame" startGameLabel.position = CGPoint (x: size.width / 2, y: size.height / 2 ) addChild (startGameLabel)

Her setter vi startGameLabelnavn på eiendommen til start spill.

Vi må også sette etikettens navn innenfor NewScene. Legg til følgende med didMove (i :) metode innenfor NewScene.swift.

 overstyr func didMove (for å se: SKView) la goBackLabel = SKLabelNode (tekst: "Gå tilbake") goBackLabel.name = "goback" goBackLabel.position = CGPoint (x: size.width / 2, y: size.height / 2 ) addChild (goBackLabel)

Vi satte Navn eiendom til gå tilbake.

Detekterer hvilken knutepunkt som er tøyd

Legg til følgende i touchesBegan (_: med :) metode innenfor GameScene.swift.

 overstyr func touchesBegan (_ berører: Set, med hendelsen: UIEvent?) vakt låt berøre = berører.for det første return la touchLocation = touch.location (i: selv) la touchedNode = self.atPoint (touchLocation) hvis (touchedNode.name == "startgame")  la newScene = NewScene (størrelse: størrelse) newScene.scaleMode = scaleMode la doorsClose = SKTransition.doorsCloseVertical (withDuration: 2.0) vise? .presentScene (newScene, transition: doorsClose)

De multiTouchEnabled Egenskapen til scenens visning er satt til falsk som standard, som betyr at visningen bare mottar det første trykket på en multitouch-sekvens. Med denne egenskapen deaktivert, kan du hente kontakten ved å bruke først Beregnet egenskap av berøringssettet, siden det bare er ett objekt i settet.

Vi kan få touchLocation innenfor scenen fra plassering egenskapen til berøring. Vi kan da finne ut hvilken knute som var berørt ved å påkalle atPoint (_ :) og passerer i touchLocation.

Vi sjekker om touchedNodeNavn på eiendom er lik "start spill", og hvis det er, vet vi at brukeren har rørt etiketten. Vi lager deretter en forekomst av NewScene og sett dens scalemode Egenskapen er den samme som den nåværende scenen - dette sikrer at scenen virker på samme måte over ulike enheter. Til slutt lager vi en SKTransition og påkalle presentScene (_: overgang :) metode som vil presentere scenen sammen med overgangen.

De SKTransition klassen har mange klassemetoder som du kan påberope for å vise forskjellige overganger mellom scener i stedet for umiddelbart å vise scenen. Dette gir litt "eye candy" for sluttbrukeren, og gjør at det viser seg at en ny scene virker mindre brat. For å se alle tilgjengelige overgangstypene, sjekk ut SKTransition klasse i referanseveiledningen.

Jeg skal ikke implementere touchesBegan (_: med :) metode i NewScene. Hvorfor forsøker du ikke å gjøre det på egen hånd og få etikettovergangen tilbake til GameScene bruker en annen overgangstype? Koden vil ligner det vi har over, bare husk at vi heter SKLabelNode "gå tilbake".

Konklusjon

Vi har lært en god del om noder så langt ved hjelp av scener, og du har sett hvordan du bruker en etikettknute som et generisk eksempel for å lære noen av egenskapene til noder. Vi har studert sine koordinatsystemer, hvordan de skal lokaliseres i nodetreet, hvordan de skal plasseres og hvordan man svarer på berøringshendelser. 

Det finnes flere andre typer noder tilgjengelig, og vi tar en titt på dem i neste opplæring - starter med SKSpriteNode!

For å lære mer om hvordan du kommer i gang med SpriteKit, bør du også sjekke ut Davis Allies innlegg her på Envato Tuts+.

Se også våre SpriteKit kurs! Disse vil ta deg gjennom alle trinnene for å bygge ditt første SpriteKit-spill for iOS, selv om du aldri har kodet med SpriteKit før.