SpriteKit Basics Noder

SpriteKit är Apples 2D-spelmotor, en återgivningsmotor som bygger på OpenGL. Det introducerades med iOS 7, och varje efterföljande release har medfört stora tillägg till ramverket. Med användning av texturerad sprites, en inbyggd fysikmotor, och den mycket kraftfulla SKAction klass kan du snabbt bygga funktionella 2D-spel.

SpriteKit har inbyggda redigerare för scener och partiklar, en kamera node sedan utgåvan av iOS9 och inbyggt stöd för plattor sedan utgåvan av iOS 10. Med dessa nya tillägg blir SpriteKit snabbt ett kraftverk för att skapa 2D-spel.

För att följa med denna handledning, ladda bara den medföljande GitHub repo. Den har en mapp som heter ExempelProjekt Starter. Öppna projektet i den mappen i Xcode, och du är redo att gå!

noder

Noder är de grundläggande byggstenarna i SpriteKit, och SKNode är basklassen för alla noder. Alla dina tillgångar på skärmen kommer att vara en SKNode eller en underklass därav. SKNodes i sig ger inget visuellt innehåll. Allt visuellt innehåll är ritat med ett av ett antal fördefinierade SKNode subklasser. SKNodes och dess underklasser delar flera egenskaper du kan ändra. Några av de viktigaste är följande.

  • placera (CGPoint): nodens position inom sitt föräldras koordinatsystem
  • xScale (CGFloat): Skal bredden på en nod med en multiplikator
  • yScale(CGFloat): Skalar höjden på en nod med en multiplikator
  • alfa (CGFloat): nodens transparens
  • zRotation (CGFloat): Eulerrotationen runt z-axeln (i radianer)

En av de mest viktiga SKNodes är SKScene. Detta är rotknutpunkten till vilken alla andra noder läggs till. Av sig själv, SKScene tillhandahåller inga visuella element, men det visar de noder som läggs till det.

Scennoder

SKScenes är de rotnoder som alla andra noder läggs till. Scenen animerar och gör innehållet från sina barnnoder. För att visa en scen lägger du till den i en SKView (vilket är en underklass av UIView och har därför många av samma egenskaper som UIView).

I SpriteKit-startprojektet visas den ursprungliga scenen när projektet laddas. För nu är det bara en blank svart skärm. Det visas när GameViewController anropar presentScene (_ :) i visningsexemplet, passerar in i scenen som en parameter:

åsidosätta func viewDidLoad () super.viewDidLoad () låt scen = GameScene (storlek: CGSize (bredd: 768, höjd: 1024)) låt skView = self.view as! SKView skView.showsFPS = false skView.showsNodeCount = false skView.ignoresSiblingOrder = false scene.scaleMode = .aspektFill skView.presentScene (scen) // Presentera scenen

Oroa dig inte för de andra alternativen för nu Jag ska förklara dem senare i denna serie.

Skapa en scen

Många spel har mer än en skärm eller scen, så vi kommer att skapa en ny scen från början och visa den från vår första scen.

Välj Fil > Ny > Fil från Xcode-menyn och välj Kakao Touch Class.

Se till Klass är satt till NewScene och det Underklass av är satt till SKScene. Tryck Nästa och då Skapa, se till att huvudmålet är kontrollerat. Nedan är koden för NewScene.swift.

importera UIKit import SpriteKit klass NewScene: SKScene 

Nu har vi två scener i vårt projekt och har inget visuellt innehåll. Låt oss lägga till en SKLabelNode (som alla noder, det här är en underklass av SKNode). De SKLabelNodeDess enda syfte är att visa en textetikett.

Etikettnoder

Etikettnoder, implementerade i SKLabelNode klass, används för att visa text inom ditt spel. Du kan använda anpassade teckensnitt om du vill, men för våra ändamål kommer vi bara hålla fast vid standardvärdet, som visar vit text och är inställd på Helvetica Neue Ultra Light, 32 poäng.

Lägg till följande inuti didMove (till :) metod inom GameScene.swift. Denna metod kallas omedelbart efter att en scen presenteras av en vy. Vanligtvis är det här du skulle ställa in något av ditt spelets tillgångar och lägga till dem på scenen.

åsidosätta func didMove (för att visa: SKView) let startGameLabel = SKLabelNode (text: "Start Game")

Här skapar vi en SKLabelNode med hjälp av bekvämlighetsinitieraren init (text :), som tar som en parameter en textsträng.

Lägga till och ta bort nodar

Bara initiering av noder visar inte dem i scenen. För att få knutpunkterna att visa måste du påkalla addChild (_ :) metod på mottagarnoden, passerar SKNode som du vill lägga till som en parameter.

Lägg till följande inom didMove (till :) metod.

åsidosätta func didMove (för att visa: SKView) let startGameLabel = SKLabelNode (text: "Start Game") addChild (startGameLabel)

De addChild (_ :) Metoden är inte exklusiv för SKScenes, men är en metod för SKNode. Detta gör att du kan bygga en komplex hierarki med noder som är kända som "node tree". Tänk dig att du har ett speltecken och du ville flytta dina armar och ben separat. Du kan skapa en SKNode exempel och lägg sedan till varje enskild del som ett barn av det SKNode (den inneboende noden är känd som moderkoden). Detta skulle ge dig nytta av att kunna flytta karaktären som en hel enhet genom att flytta föräldern SKNode, men låter dig också flytta varje enskild del individuellt.

En annan viktig metod för att lägga till noder är insertChild (_: vid :) metod, som sätter in ett barn i en specifik position inom mottagarens nods lista över barn. När du lägger till ett barn i en nod, behåller noden en ordnad lista över barn som refereras genom att läsa nodens barn fast egendom. Det är viktigt när du lägger till flera noder till en moderkod för att ta hänsyn till detta, eftersom den ordning i vilken du lägger till knutpunkterna påverkar några av aspekterna av scenbehandling, inklusive träfftestning och återgivning.

För att ta bort en nod, ringer du på removeFromParent () metod på noden du vill ta bort.

Nu när vi har täckt lägga till och avlägsna noder, kan vi flytta vårt fokus tillbaka till exempelprojektet. Om du kommer ihåg, hade vi just lagt till en SKLabelNode till GameScene. Om du testar nu ser du bara hälften av texten till längst ned till vänster på skärmen.

Varför visas bara hälften av texten, dock? Nu skulle det vara en bra tid att prata om SpriteKits koordinat- och positionssystem.

Positionering och koordinater

Som standard placerar SpriteKits koordinatsystem (0,0) längst ner till vänster på skärmen. Som standard placerar SpriteKit noder så att de är placerade på (0,0). Men ändå ... varför ser vi bara hälften av texten? Detta beror på att textmarkeringen som standard är centrerad horisontellt på etikettnodets ursprung, vilket är (0,0). Nedan visas en bild som visar hur en nods koordinatsystem fungerar.

Nodens ursprung är hos (0,0), och en positiv x-koordinat rör sig åt höger och en positiv y-koordinat går upp på skärmen. Kom ihåg att en SKScene är en nod, och därför är dess ursprung också (0,0).

Ställ in en nods position

Nu när vi har lärt oss SpriteKits koordinatsystem fungerar och hur det placerar noder kan vi flytta SKLabelNode till en annan position så att vi kan se hela texten. Lägg till följande i didMove (till :) metod inom GameScene.swift.

överträffa func didMove (för att visa: SKView) let startGameLabel = SKLabelNode (text: "Start Game") startGameLabel.position = CGPoint (x: size.width / 2, y: size.height / 2) addChild (startGameLabel)

Här placerar vi etiketten i mitten av scenen. De placera egendom är av typ CGPoint, som har x och y värden som representerar en enda punkt inom scenen.

Om du testar nu ska du se att etiketten har placerats i mitten av scenen.

Växla mellan scener

Som det står för närvarande, NewScene är bara en tom scen. Låt oss också lägga till en etikett till det och då kan vi lära oss att växla mellan scener. Det här är en utmaning: Försök att lägga till en etikett till innan du läser framåt NewScene det säger, "Gå tillbaka". Min lösning är nedan.

Det första vi behöver göra är att lägga till didMove (till :) metod. Lägg till följande till NewScene.swift.

klass NewScene: SKScene override func didMove (för att visa: SKView) 

Därefter måste vi lägga till etiketten. Lägg till följande inom didMove (till :) metod som du lagt till ovan.

override func didMove (för att visa: SKView) let goBackLabel = SKLabelNode (text: "Gå tillbaka") goBackLabel.position = CGPoint (x: size.width / 2, y: size.height / 2) addChild (goBackLabel)

Detta lägger till en etikett till  NewScene med texten "Gå tillbaka". Sedan genomför vi den funktionalitet som denna etikett föreslår - vi svarar på beröringshändelser genom att byta scener.

Svara på Touch

Nästan alla mobila spel kommer att interagera med att använda touch. I det här steget lär du dig att svara på beröringshändelser i ditt spel.

För att registrera händelsehanterare i ditt spel måste du implementera visningen touchesBegan (_: med :) metod. Lägg till följande till GameScene.swift:

åsidosätta func touchesBegan (_ berör: Set, med händelse: UIEvent?) print ("YOU TOUCHED")

Om du vill testa detta nu ser du DU TECKNADE tryckt på konsolen när du trycker på skärmen. Vad vi vanligtvis behöver är dock att kunna berätta när en specifik nod har berörts. För att göra detta behöver vi något sätt att hitta och identifiera noderna. Vi kommer att lära oss hur vi åstadkommer detta, och sedan komma tillbaka och avsluta touchesBegan (_: med :) metod.

Söka på nodträdet

För att kunna identifiera en nod använder du noden namn egenskapen och sökningen i nodträdet för en nod med det namnet. Noden är namn Egenskapen tar en alfanumerisk sträng utan någon skillnad. 

Det finns ett par metoder för att söka efter en nod av dess namn fast egendom. Om du redan har en referens till noden kan du bara kolla på det namn egendom direkt, vilket är vad vi ska göra i touchesBegan (_: med :) metod. Det är emellertid viktigt att veta hur man letar efter nodtreen för en viss nod med namn eller för att söka efter en grupp noder med samma namn.

De childNode (withName :) Metoden söker barnen till en nod för det specifika namn som passerat som en parameter.

De enumerateChildNodes (withName: användning :) Metoden söker efter en nods barn och kallar blocket en gång för varje matchande nod som den finner. Du använder den här metoden när du vill hitta alla noder som delar samma namn.

De index(_:) Metoden returnerar en rad noder som matchar namnparametern.

Du kan också söka efter noder med en avancerad söksyntax som låter dig söka i hela scenträdet, eller söka efter ett mönster istället för ett exakt namn. Denna avancerade sökfunktion ligger utanför omfattningen av denna handledning. Men om du vill lära dig mer kan du läsa om i SKNode programmeringsreferens.

Nu när vi vet hur man söker efter noder inom nodtreen, låt oss ge våra etiketter ett namn.

Lägg till följande inom didMove (till :) metod inom GameScene.swift.

ignorera func didMove (för att visa: SKView) let startGameLabel = SKLabelNode (text: "Start Game") startGameLabel.name = "startspel" startGameLabel.position = CGPoint (x: size.width / 2, y: size.height / 2 ) addChild (startGameLabel)

Här ställer vi in startGameLabels namn egendom till starta spelet.

Vi måste också ange etikettens namn inom NewScene. Lägg till följande med didMove (till :) metod inom NewScene.swift.

 override func didMove (för att visa: SKView) let goBackLabel = SKLabelNode (text: "Gå tillbaka") goBackLabel.name = "goback" goBackLabel.position = CGPoint (x: size.width / 2, y: size.height / 2 ) addChild (goBackLabel)

Vi ställer in namn egendom till gå tillbaka.

Detekterar vilken nod som är tuff

Lägg till följande inom touchesBegan (_: med :) metod inom GameScene.swift.

 åsidosätta func touchesBegan (_ berör: Set, med händelse: UIEvent?) vakt låt dig beröra = berör.första gången return låt touchLocation = touch.location (i: själv) låt touchedNode = self.atPoint (touchLocation) om (touchedNode.name == "startgame")  låt newScene = NewScene (storlek: storlek) newScene.scaleMode = scaleMode låt doorsClose = SKTransition.doorsCloseVertical (withDuration: 2.0) visa? .presentScene (newScene, transition: doorsClose)

De multiTouchEnabled egenskapen för scenens vy är inställd på falsk som standard, vilket innebär att vyn endast tar emot den första kontakten av en multitouch-sekvens. Med den här egenskapen inaktiverad kan du hämta kontakten med hjälp av först beräknade egenskaper för handenheten, eftersom det bara finns ett objekt i uppsättningen.

Vi kan få touchLocation inom scenen från plats beröringsegenskapen. Vi kan sedan räkna ut vilken nod som berördes genom att åberopa atPoint (_ :) och passerar i touchLocation.

Vi kontrollerar om touchedNodeNamnets egendom är lika med "starta spelet", och om det är vet vi att användaren har berört etiketten. Vi skapar sedan en förekomst av NewScene och sätt dess scalemode egenskapen är densamma som den aktuella scenen, vilket gör att scenen fungerar på samma sätt över olika enheter. Slutligen skapar vi en SKTransition och åberopa presentScene (_: övergång :) metod som kommer att presentera scenen tillsammans med övergången.

De SKTransition klassen har många klassmetoder som du kan åberopa för att visa olika övergångar mellan scener istället för att genast visa scenen. Detta ger lite "ögonkock" för slutanvändaren, och gör att en ny scen verkar vara mindre plötslig. För att se alla tillgängliga övergångstyper, kolla in SKTransition klass i referensguiden.

Jag ska inte genomföra touchesBegan (_: med :) metod i NewScene. Varför försöker du inte göra det själv och få etikettövergången tillbaka till GameScene använder en annan övergångstyp? Koden kommer att likna vad vi har ovan, bara kom ihåg att vi heter SKLabelNode "gå tillbaka".

Slutsats

Vi har lärt oss en hel del om noder hittills med scener, och du har sett hur du använder en etikettnod som ett generiskt exempel för att lära dig några av egenskaperna hos noder. Vi har studerat deras koordinatsystem, hur man lokaliserar dem inom nodtreen, hur man placerar dem och hur man svarar på beröringshändelser. 

Det finns flera andra typer av noder tillgängliga, och vi tar en titt på dem i nästa handledning - börjar med SKSpriteNode!

För att lära dig mer om hur du kommer igång med SpriteKit, bör du också kolla in Davis Allies post här på Envato Tuts+.

Titta även på våra SpriteKit kurser! Dessa kommer att ta dig igenom alla steg för att bygga ditt första SpriteKit-spel för iOS, även om du aldrig kodat med SpriteKit innan.