SpriteKit is de 2D-game-engine van Apple: een rendering-engine bovenop OpenGL. Het werd geïntroduceerd met iOS 7 en elke volgende release heeft geweldige toevoegingen aan het framework opgeleverd. Met het gebruik van getextureerde sprites, een ingebouwde physics-engine en de zeer krachtige SKAction
klasse, kun je heel snel functionele 2D-games bouwen.
SpriteKit heeft ingebouwde editors voor scènes en deeltjes, een cameraknooppunt sinds de release van iOS9, en ingebouwde ondersteuning voor tilesets sinds de release van iOS 10. Met deze nieuwe toevoegingen wordt SpriteKit snel een krachtpatser voor het maken van 2D-games.
Volg deze tutorial om de bijbehorende GitHub-repo te downloaden. Het heeft een map genaamd VoorbeeldProject Starter. Open het project in die map in Xcode en je bent klaar om te gaan!
Knopen zijn de fundamentele bouwstenen van SpriteKit, en SKNode
is de basisklasse van alle knooppunten. Al uw activa op het scherm zijn een SKNode
of een subklasse daarvan. SKNode
s zelf leveren echter geen visuele inhoud op. Alle visuele inhoud wordt getekend met een van een aantal vooraf gedefinieerde SKNode
subklassen. SKNode
s en de subklassen delen verschillende eigenschappen die u kunt wijzigen. Enkele van de belangrijkste zijn als volgt.
positie
(CGPoint
): de positie van het knooppunt binnen het coördinatensysteem van de ouderxScale
(CGFloat
): schaalt de breedte van een knoop door een vermenigvuldigeryScale
(CGFloat
): schaalt de hoogte van een knoop door een vermenigvuldigeralpha
(CGFloat
): de transparantie van het knooppuntzRotation
(CGFloat
): de Euler-rotatie om de z-as (in radialen)Een van de meest belangrijke SKNode
s is het SKScene
. Dit is het hoofdknooppunt waaraan alle andere knooppunten zijn toegevoegd. Alleen, SKScene
levert geen visuele elementen op, maar geeft de knooppunten weer die eraan zijn toegevoegd.
SKScenes
zijn de wortelknooppunten waaraan alle andere knooppunten zijn toegevoegd. De scène animeert en rendert de inhoud van de onderliggende knooppunten. Om een scène weer te geven, voegt u deze toe aan een SKView
(dat is een subklasse van UIView
en heeft daarom veel van dezelfde eigenschappen als UIView
).
In het SpriteKit-startproject wordt de beginscène weergegeven wanneer het project wordt geladen. Voorlopig is dit slechts een leeg zwart scherm. Het wordt getoond wanneer het GameViewController
oproept presentScene (_ :)
in de view-instantie, doorgeven van de scène als een parameter:
override func viewDidLoad () super.viewDidLoad () laat scène = GameScene (maat: CGSize (breedte: 768, hoogte: 1024)) laat skView = self.view as! SKView skView.showsFPS = false skView.showsNodeCount = false skView.ignoresSiblingOrder = false scene.scaleMode = .aspectFill skView.presentScene (scene) // Present the Scene
Maak je voorlopig geen zorgen over de andere opties; Ik zal ze later in deze serie uitleggen.
Veel spellen hebben meer dan één scherm of scène, dus we zullen vanaf het begin een nieuwe scène maken en deze vervolgens laten zien vanuit onze eerste scène.
kiezen het dossier > nieuwe > het dossier uit het Xcode-menu en kies Cocoa Touch Class.
Zorg ervoor dat Klasse ingesteld op NewScene en dat Subklasse van ingesteld op SKScene
. druk op volgende en dan creëren, ervoor zorgen dat het hoofddoel wordt gecontroleerd. Hieronder staat de code voor de NewScene.swift.
import UIKit import SpriteKit-klasse NewScene: SKScene
Nu hebben we twee scènes in ons project en geen van beide heeft visuele inhoud. Laten we een toevoegen SKLabelNode
(zoals alle knooppunten, dit is een subklasse van SKNode
). De SKLabelNode
Het enige doel is om een tekstlabel weer te geven.
Labelknooppunten, geïmplementeerd in de SKLabelNode
klasse, worden gebruikt om tekst weer te geven in je game. U kunt desgewenst aangepaste lettertypen gebruiken, maar voor onze doeleinden houden we ons gewoon aan de standaardinstelling, die witte tekst weergeeft en is ingesteld op Helvetica Neue Ultra Light, 32 punt.
Voeg het volgende toe in de didMove (naar :)
methode binnen GameScene.swift. Deze methode wordt meteen aangeroepen nadat een scène door een weergave wordt gepresenteerd. Over het algemeen stelt u hier de activa van uw spel in en voegt u deze toe aan de scène.
override func didMove (om te bekijken: SKView) let startGameLabel = SKLabelNode (tekst: "Start Game")
Hier creëren we een SKLabelNode
gebruik van de gemakinitialisator init (tekst :)
, die als een parameter een tekenreeks opneemt.
Als u knooppunten initialiseert, worden deze niet in de scène weergegeven. Om de knooppunten te laten weergeven, moet u de addChild (_ :)
methode op het ontvangende knooppunt, het passeren van de SKNode
die u als een parameter wilt toevoegen.
Voeg het volgende toe binnen de didMove (naar :)
methode.
override func didMove (te bekijken: SKView) let startGameLabel = SKLabelNode (tekst: "Start Game") addChild (startGameLabel)
De addChild (_ :)
methode is niet exclusief voor SKScene
s, maar is een methode van SKNode
. Hiermee kunt u een complexe hiërarchie van knooppunten maken, ook wel bekend als de "knoopboom". Stel dat je een spelkarakter hebt en je zijn armen en benen apart wilt verplaatsen. Je zou een kunnen maken SKNode
en voeg vervolgens elk afzonderlijk onderdeel toe als een onderliggende waarde SKNode
(het bevattende knooppunt staat bekend als het bovenliggende knooppunt). Dit zou je het voordeel geven dat je het personage als een geheel kunt verplaatsen door de ouder te verplaatsen SKNode
, maar laat je ook toe om elk individueel onderdeel afzonderlijk te verplaatsen.
Een andere belangrijke methode voor het toevoegen van knooppunten is de insertChild (_: bij :)
methode, die een kind invoegt in een specifieke positie binnen de lijst met kinderen van de ontvanger-node. Wanneer u een kind aan een knoop toevoegt, houdt het knooppunt een geordende lijst met kinderen bij, waarnaar wordt verwezen door het lezen van de knooppunten. kinderen
eigendom. Het is belangrijk om meerdere knooppunten aan een bovenliggend knooppunt toe te voegen om hiermee rekening te houden, omdat de volgorde waarin u de knooppunten toevoegt, van invloed is op enkele aspecten van scèneverwerking, waaronder treffer testen en renderen.
Om een knoop te verwijderen, roept u de removeFromParent ()
methode op het knooppunt dat u wilt verwijderen.
Nu we het toevoegen en verwijderen van knooppunten hebben behandeld, kunnen we onze focus verleggen naar het voorbeeldproject. Als je je eraan herinnert, hadden we zojuist een toegevoegd SKLabelNode
naar de GameScene
. Als u nu test, ziet u slechts de helft van de tekst linksonder op het scherm.
Waarom is maar de helft van de tekst te zien? Het zou een goed moment zijn om te praten over het coördinaten- en positioneringssysteem van SpriteKit.
Standaard plaatsen de coördinatensystemen van SpriteKit (0,0) linksonder op het scherm. Ook plaatst SpriteKit standaard knooppunten zodat ze op (0,0). Maar toch ... waarom zien we slechts de helft van de tekst? Dit komt omdat het tekstlabel standaard horizontaal is gecentreerd op de oorsprong van het labelknooppunt, wat0,0). Hieronder ziet u een afbeelding die laat zien hoe het coördinatensysteem van een knooppunt werkt.
De oorsprong van knooppunten ligt bij (0,0) en een positieve x-coördinaat beweegt naar rechts en een positieve y-coördinaat gaat omhoog op het scherm. Vergeet niet dat een SKScene is een knoop, en daarom is de oorsprong ook (0,0).
Nu we hebben geleerd dat het coördinatensysteem van SpriteKit werkt en hoe het knooppunten plaatst, kunnen we het verplaatsen SKLabelNode
naar een andere positie, zodat we alle tekst kunnen zien. Voeg het volgende toe aan de didMove (naar :)
methode binnen GameScene.swift.
override func didMove (te bekijken: SKView) let startGameLabel = SKLabelNode (tekst: "Start Game") startGameLabel.position = CGPoint (x: size.width / 2, y: size.height / 2) addChild (startGameLabel)
Hier plaatsen we het label in het midden van de scène. De positie
eigendom is van het type CGPoint
, die x- en y-waarden heeft die een enkel punt in de scène vertegenwoordigen.
Als u nu test, ziet u dat het label in het midden van de scène is geplaatst.
Zoals het er nu staat, NewScene
is gewoon een lege scène. Laten we er ook een label aan toevoegen en dan kunnen we leren schakelen tussen scènes. Dit is een uitdaging: probeer voordat je verder leest een label toe te voegen NewScene
dat zegt, "Ga terug". Mijn oplossing is hieronder.
Het eerste dat we moeten doen is het toevoegen van didMove (naar :)
methode. Voeg het volgende toe aan NewScene.swift.
class NewScene: SKScene override func didMove (om te bekijken: SKView)
Vervolgens moeten we het label toevoegen. Voeg het volgende toe binnen de didMove (naar :)
methode die u hierboven hebt toegevoegd.
negeer func didMove (te bekijken: SKView) let goBackLabel = SKLabelNode (text: "Go Back") goBackLabel.position = CGPoint (x: size.width / 2, y: size.height / 2) addChild (goBackLabel)
Hiermee voegt u een label toe aan NewScene
met de tekst "Ga terug". Vervolgens implementeren we de functionaliteit die dit label suggereert: we reageren op aanraakgebeurtenissen door van scène te wisselen.
Bijna alle mobiele spellen zullen worden gebruikt met behulp van aanraking. In deze stap leert u hoe u reageert op aanraakgebeurtenissen in uw spel.
Om Touch Event-handlers binnen je game te registreren, moet je de view's implementeren touchesBegan (_: met :)
methode. Voeg het volgende toe aan GameScene.swift:
override func touchesBegan (_ touches: Set, met evenement: UIEvent?) print ("YOU TOUCHED")
Als je dit nu wilt testen, zul je het zien JIJ AANRAAKT afgedrukt op de console wanneer u op het scherm tikt. Wat we echter meestal nodig hebben, is te kunnen vertellen wanneer een specifiek knooppunt is aangeraakt. Om dit te doen, hebben we een manier nodig om de knooppunten te vinden en te identificeren. We zullen leren hoe dit te bereiken, en dan terugkomen en het voltooien touchesBegan (_: met :)
methode.
Om een knooppunt te kunnen identificeren, gebruik je de knooppunten naam
eigenschap en zoek in de knoopboom naar een knooppunt met die naam. Het knooppunt is naam
eigenschap neemt een alfanumerieke tekenreeks zonder interpunctie.
Er zijn een aantal methoden om naar een knooppunt te zoeken naam
eigendom. Als je al een verwijzing naar het knooppunt hebt, kun je het gewoon aanvinken naam
eigendom direct, wat we zullen doen in de touchesBegan (_: met :)
methode. Het is echter belangrijk om te weten hoe u de knooppuntenstructuur voor een bepaald knooppunt op naam zoekt, of om te zoeken naar een groep knooppunten met dezelfde naam.
De childNode (withName :)
methode zoekt de kinderen van een knooppunt op voor de specifieke naam die als parameter is doorgegeven.
De enumerateChildNodes (withName: met behulp van :)
methode doorzoekt de kinderen van een knooppunt en roept het blok eenmaal aan voor elk overeenkomend knooppunt dat het vindt. U gebruikt deze methode wanneer u alle knooppunten met dezelfde naam wilt vinden.
De subscript (_ :)
methode retourneert een array van knooppunten die overeenkomen met de parameter name.
U kunt ook naar knooppunten zoeken met behulp van een geavanceerde zoeksyntaxis waarmee u de hele scèneboomstructuur kunt doorzoeken of bijvoorbeeld een patroon kunt zoeken in plaats van een exacte naam. Deze geavanceerde zoekfunctie valt buiten het bestek van deze zelfstudie. Als u meer wilt weten, kunt u hierover lezen in de SKNode
programmeerreferentie.
Nu we weten hoe we moeten zoeken naar knooppunten in de knooppuntenboom, laten we onze labels een naam geven.
Voeg het volgende toe binnen de didMove (naar :)
methode binnen GameScene.swift.
override func didMove (te bekijken: SKView) let startGameLabel = SKLabelNode (tekst: "Start Game") startGameLabel.name = "startgame" startGameLabel.position = CGPoint (x: size.width / 2, y: size.height / 2 ) addChild (startGameLabel)
Hier gaan we zitten startGameLabel
's name property to start het spel
.
We moeten ook de naam van het label hierbinnen zetten NewScene
. Voeg het volgende toe met de didMove (naar :)
methode binnen NewScene.swift.
override func didMove (te bekijken: SKView) let goBackLabel = SKLabelNode (text: "Go Back") goBackLabel.name = "goback" goBackLabel.position = CGPoint (x: size.width / 2, y: size.height / 2 ) addChild (goBackLabel)
We hebben de naam
eigendom aan ga terug
.
Voeg het volgende toe binnen de touchesBegan (_: met :)
methode binnen GameScene.swift.
override func touchesBegan (_ touches: Set, met evenement: UIEvent?) guard let touch = touches.first else return let touchLocation = touch.location (in: self) let touchedNode = self.atPoint (touchLocation) if (touchedNode.name == "startgame") let newScene = NewScene (size: size) newScene.scaleMode = scaleMode laat doorsClose = SKTransition.doorsCloseVertical (withDuration: 2.0) view? .presentScene (newScene, transition: doorsSlose)
De multiTouchEnabled
eigenschap van de scène is ingesteld op vals
Standaard betekent dit dat de weergave alleen de eerste aanraking van een multitouch-reeks ontvangt. Als deze eigenschap is uitgeschakeld, kunt u het aanraken ophalen met behulp van de eerste
berekende eigenschap van de aanrakingenset, omdat er maar één object in de set is.
We kunnen de touchLocation
in de scène van de plaats
eigendom van de aanraking. We kunnen dan uitzoeken welk knooppunt is aangeraakt door aan te roepen atPoint (_ :)
en passeren in de touchLocation
.
We controleren of het touchedNode
's naameigenschap is gelijk aan "start het spel"
, en als dat zo is, weten we dat de gebruiker het label heeft aangeraakt. We maken vervolgens een instantie van NewScene
en stel zijn scaleMode
eigenschap gelijk te zijn aan de huidige scène - dit zorgt ervoor dat de scène op verschillende apparaten hetzelfde werkt. Eindelijk maken we een SKTransition
en roep de presentScene (_: overgang :)
methode, die de scène samen met de overgang zal presenteren.
De SKTransition
class heeft veel klasse-methoden die u kunt gebruiken om verschillende overgangen tussen scènes weer te geven in plaats van onmiddellijk de scène te tonen. Dit zorgt voor een beetje "eye candy" voor de eindgebruiker en maakt het tonen van een nieuwe scène minder abrupt. Als u alle beschikbare overgangstypen wilt bekijken, bekijkt u de SKTransition
klasse in de referentiehandleiding.
Ik ga het. Niet implementeren touchesBegan (_: met :)
methode in NewScene
. Waarom doe je dat niet alleen en laat je de etikettransitie terug naar de GameScene
een ander overgangstype gebruiken? De code zal sterk lijken op wat we hierboven hebben, onthoud alleen dat we de naam hebben genoemd SKLabelNode
"ga terug"
.
We hebben tot nu toe een goed deel geleerd over knooppunten met behulp van scènes en je hebt gezien hoe een labelknooppunt als een algemeen voorbeeld te gebruiken om enkele kenmerken van knooppunten te leren. We hebben hun coördinatensystemen bestudeerd, hoe ze in de knoopboom te vinden zijn, hoe ze te positioneren en hoe ze reageren op aanraakgebeurtenissen.
Er zijn verschillende andere soorten knooppunten beschikbaar, en we zullen ze in de volgende zelfstudie bekijken - te beginnen met SKSpriteNode
!
Voor meer informatie over hoe u aan de slag kunt met SpriteKit, kunt u ook het bericht van Davis Allie hier op Envato Tuts bekijken+.
Bekijk ook onze SpriteKit-cursussen! Deze zullen je door alle stappen leiden van het bouwen van je eerste SpriteKit-game voor iOS, zelfs als je nog nooit met SpriteKit hebt gecodeerd.