În acest tutorial, a doua tranșă a seriei SpriteKit From Scratch, învățați despre constrângeri și acțiuni. Aceste caracteristici sunt folosite pentru a adăuga cu ușurință mișcări și animații în jocul dvs. SpriteKit, limitând în același timp poziția și orientarea nodurilor în joc.
Pentru a urmări împreună cu mine, puteți utiliza fie proiectul pe care l-ați creat în primul tutorial al acestei serii, fie puteți descărca o copie nouă de la GitHub.
Grafica folosită pentru joc în această serie poate fi găsită pe GraphicRiver. GraphicRiver este o sursă excelentă pentru găsirea de ilustrații și grafică pentru jocurile dvs..
Înainte de a putea începe să adăugăm constrângeri și acțiuni la o scenă, mai întâi trebuie să creăm câteva clase astfel încât să putem lucra cu nodurile noastre în cod. Creați o nouă clasă, PlayerNode, bazat pe iOS> Source> Cocoa Touch Class șablon și asigurați-vă că este o subclasă de SKSpriteNode
.
Dacă Xcode aruncă o eroare după crearea clasei, adăugați o instrucțiune de import pentru cadrul SpriteKit de mai jos import UIKit
afirmație:
importați importul UIKit SpriteKit
Apoi, declarați următoarele trei proprietăți în PlayerNode
clasă. Aceste proprietăți vor menține constrângerile utilizate pentru a limita mișcarea orizontală a mașinii.
import import UIKit Clasă SpriteKit PlayerNode: SKSpriteNode var leftConstraint: SKConstraint! var middleConstraint: SKConstraint! var rightConstraint: SKConstraint!
Creați un altul Cocoa Touch Class și numește-o MainScene, făcându-i o subclasă de SKScene
.
În partea de sus, adăugați o declarație de import pentru cadrul SpriteKit.
importați importul UIKit SpriteKit
Cu aceste clase create, deschise MainScene.sks, faceți clic pe fundalul gri pentru a selecta scena, deschideți Inspector de clasă personalizată pe dreapta și setat Clasa personalizată la MainScene.
Selectați mașina și stabiliți clasa acesteia PlayerNode în același mod pe care l-ați făcut pentru scenă. În cele din urmă, cu mașina încă selectată, deschideți Atribute Inspector și schimbare Nume la Jucător.
Acum, că avem clasele de bază stabilite, putem începe să creăm unele constrângeri în cod.
Constrângeri în SpriteKit, reprezentate de SKConstraint
sunt folosite pentru a limita poziția și orientarea anumitor noduri. O multitudine de varietăți pot fi realizate cu constrângeri, deoarece pot fi relative la scenă sau relativ la alte noduri. Constrângerile funcționează, de asemenea, cu valori de valori în plus față de valorile constante, astfel încât spritele din scena dvs. pot fi fixate într-o anumită locație sau pot fi mutate într-o anumită zonă.
Constrângerile pe care le vom adăuga sunt cele trei pe care le-am declarat în PlayerNode
clasă. Aceste constrângeri vor fi folosite pentru a bloca mașina pe cele trei benzi din joc.
Deschis MainScene.swift și să creați o proprietate pentru jucătorul de tip PlayerNode!
. Această proprietate va stoca o referință la nodul jucătorului.
import Importul UIKit Clasa SpriteKit MainScene: SKScene var player: PlayerNode!
Apoi, noi suprascrie didMoveToView (_ :)
metodă a MainScene
clasă:
override func didMoveToView (vizualizare: SKView) super.didMoveToView (view) size = view.frame.size daca a lasat foundPlayer = childNodeWithName ("Player") ca? PlayerNode player = foundPlayer letcent centre = size.width / 2.0, difference = CGFloat (70.0) player.leftConstraint = SKConstraint.positionX (SKRange (constantValue: )) player.rightConstraint = SKConstraint.positionX (SKRange (constantValue: centru + diferență)) player.leftConstraint.enabled = false player.rightConstraint.enabled = false player.constraints = [player.leftConstraint, player.middleConstraint, player.rightConstraint ]
Hai să trecem prin codul pas cu pas. didMoveToView (_ :)
metoda se numește ori de câte ori scena este prezentată de o viziune. După ce a sunat didMoveToView (_ :)
metoda superclasei, redimensionăm scena la aceeași dimensiune cu cea curentă. Acest lucru asigură faptul că scena umple întotdeauna mărimea ecranului dispozitivului curent și se măsoară corespunzător.
Accesăm sprite-ul jucătorului pe care l-am adăugat în editorul de scenarii Xcode căutând-o după numele pe care l-am dat mai devreme. Apoi atribuim această valoare către jucător
proprietate.
După calcularea centrului scenei și specificarea unei diferențe constante de 70.0
, noi creăm constrângerile spritei. Prin utilizarea funcției positionX (_ :)
metoda de clasă a SKConstraint
, vom crea constrângerile stânga, mijlocul și dreapta pentru playerul sprite. Această metodă necesită o SKRange
exemplu ca parametru, care, în cazul nostru, este un interval cu o valoare constantă. Dacă doriți să vă uitați la posibilele constrângeri și game în SpriteKit, vă recomand să aruncați o privire la SKConstraint
și SKRange
referințe de clasă.
Dezactivați constrângerile stânga și dreapta, deoarece nu vrem ca acestea să acționeze pe nodul jucătorului atunci când începe jocul. În final, le atribuim acestor constrângeri constrângeri
proprietatea nodului jucătorului. Această proprietate este definită în SKNode
clasă.
Construiți și rulați jocul pe orice simulator sau dispozitiv fizic. Ar trebui să vedeți acum că scena dvs. este calibrată corect cu mașina centrat în partea de jos.
Puteți vedea că mașina este acum limitată la centrul orizontal al scenei și este capabilă să fie limitată la benzile stângi și drepte atunci când adăugăm o mișcare spre joc.
Acțiunile în SpriteKit sunt reprezentate de cei puternici SKAction
clasă. Acțiunile ne permit să animăm cu ușurință și să mutăm spritele într-o scenă. Acestea sunt executate de noduri și sunt evaluate de API-urile SpriteKit și funcționează alături de constrângeri și simulări fizice.
Pe lângă specificarea a ceea ce face o acțiune, puteți programa și modul în care acționează acțiunea prin configurarea acesteia. Puteți, de exemplu, să întrerupeți și să reluați acțiunile sau să configurați comportamentul de relaxare a unei acțiuni. Acest lucru vă oferă un grad mai mare de control, deoarece puteți accelera sau încetini cu ușurință anumite acțiuni pentru a produce unele elemente de joc interesante.
Similar cu modul în care nodurile pot avea noduri copil, există trei tipuri de acțiuni care pot avea acțiuni copil:
Puteți crea acțiuni programat sau în editorul de scenă Xcode, pe care l-am folosit în tutorialul anterior. Vom folosi ambele tehnici în acest tutorial.
Deschis MainScene.sks și faceți clic pe pictograma de lângă Anima butonul din stânga jos a scenei pentru a afișa Vizualizare editare acțiune.
Apoi, derulați în jos în Biblioteca de obiecte de dreapta și de a găsi Mutați acțiunea articol. Faceți clic și trageți acest lucru în linia temporală a Vizualizare editare acțiune și plasați-o la marginea din stânga după cum se arată mai jos:
Acest lucru determină începerea executării acțiunii la 0:00, care este, de îndată ce scena este prezentată. Dacă este plasat în altă parte, acțiunea va începe executarea după intervalul de timp afișat în partea de sus a liniei de timp.
Plasați mouse-ul peste acțiune și faceți clic pe pictograma săgeată mică din partea stângă jos. În fereastra pop-up care apare, faceți clic pe infinit buton din stânga. Aceasta face ca acțiunea să se repete pentru totdeauna.
Cu acțiunea selectată, deschideți Atribuții Inspector în dreapta și schimbați Y Offset valoare pentru 100.
Celelalte valori specifică faptul că mașina începe să animeze imediat (Timpul de începere) și fiecare 1 al doilea (Durată) se va muta 0 puncte în X direcție și 100 în Y direcție (ofset). Funcția de temporizare proprietatea poate fi utilizată pentru a porni treptat și / sau pentru a opri o acțiune. În acest caz, folosim Liniar, ceea ce înseamnă că mașina se mișcă întotdeauna cu aceeași viteză.
În cele din urmă, pentru a testa acțiunea, faceți clic pe Anima butonul din stânga jos a editorului de scenă. Bara inferioară de instrumente ar trebui să devină albastră și mașina ar trebui să înceapă să se deplaseze.
Odată cu acțiunea de mutare implementată, este timpul să creați acțiunile orizontale programat. Înainte de a face acest lucru, trebuie să adăugăm o anumită logică, astfel încât butoanele din joc să poată controla mașina.
Creați un fișier nou selectând iOS> Source> File Swift șablon și numește-l LaneStateMachine.
Adăugați următorul cod în noul fișier:
importați clasa GameplayKit LaneStateMachine: GKStateMachine clasa LaneState: GKState varNameName: PlayerNode init (player: PlayerNode) playerNode = player clasa LeftLane: LaneState supride func isValidNextState (stateClass: AnyClass) ()) ClassName.model ()) clasa MiddleLane: LaneState override func isValidNextState (stateClass: AnyClass) -> Bool dacă stateClass == LeftLane.self || (dacă este precedentă): ifName (), dacă este precedentul lui leftName (dacă este precedent), ifNameImageInDirection () .LineState override func esteValidNextState (stateClass: AnyClass) -> Bool if stateClass == MiddleLane.self return true return false suprascrie func didEnterWithPreviousState (previousState: GKState?) playerNode.moveInDirection (.Right, toLane: self)
Tot ceea ce face acest cod, utilizează noul cadru GameplayKit pentru a crea o mașină de stat care reprezintă cele trei benzi și mișcarea între ele în joc. Dacă doriți să înțelegeți mai bine ce face acest cod, consultați tutorialul meu care acoperă GameplayKit.
În continuare, deschideți-vă PlayerNode.swift și adăugați următoarele două metode la PlayerNode
clasă:
func disableAllConstraints () leftConstraint.enabled = false middleConstraint.enabled = false rightConstraint.enabled = false func moveInDirection (direcție: ButtonDirection, laLane Lane: LaneState) disableAllConstraints () lasă changeInX = (direcția == -70.0: 70.0 lăsați rotația = (direcția == .Left)? M_PI / 4: -M_PI / 4 ani durată = 0.5 let moveAction = SKAction.moveByX (CGFloat (changeInX), y: 0.0, duration: duration) let rotateAction = SKAction.rotateByAngle (durată / rotateAction.timingMode = .EaseInEaseOut lasa rotateSequence = SKAction.sequence ([rotateAction, rotateAction.reversedAction ()]) lasa moveGroup = SKAction.group ([moveAction, rotateSequence]) let finalizare = SKAction.runBlock () -> lane caz este LeftLane: self.leftConstraint.enabled = adevărat caz este MiddleLane: self.middleConstraint.enabled = adevărat caz este RightLane: self.rightConstraint.enabled = true implicit: break leave sequenceAction = SKAction.sequence ([moveGroup, finalizare]) runAction (sequenceAction)
disableAllConstraints ()
este o metodă convenabilă pentru a dezactiva constrângerile nodului jucătorului.
În moveInDirection (_: toLane :)
, determinăm direcția în care mașina trebuie să se deplaseze orizontal, -70.0 când se mișcă stânga și +70.0 când se mișcă drept. Apoi calculam unghiul corect (în radiani) pentru a roti autoturismul atunci când se mișcă. Rețineți că numerele pozitive reprezintă o rotație în sens invers acelor de ceasornic.
După ce specificăm o durată constantă, vom crea acțiunile de mișcare și rotire folosind moveByX (_: y: durata :)
și rotateByAngle (_: durata :)
clasa respectiv. Creați o secvență de rotație pentru a roti mașina înapoi la modul în care a fost înainte de mișcare. reversedAction ()
metoda creează automat o inversă a unei acțiuni pentru dvs..
Apoi, creăm o acțiune de grup de mișcare pentru a executa mișcarea și rotirea orizontală în același timp. În cele din urmă, vom crea o acțiune de completare pentru a executa o închidere atunci când este executată. În această închidere, aflăm care banda este în prezent în mașină și permiterea constrângerii corecte pentru banda respectivă.
Deschis ViewController.swift și adăugați o proprietate, stateMachine
, de tip LaneStateMachine!
la ViewController
clasă.
clasa ViewController: UIViewController var stateMachine: LaneStateMachine! ...
Înlocuiți implementările din viewDidLoad ()
și didPressButton (_ :)
în ViewController
clasă cu următoarele:
override functie viewDidLoad () super.viewDidLoad () let skView = Vizualizare SKV (cadru: view.frame) let scene = MainScene (fileNamed: "MainScene")! skView.presentScene (scena) view.insertSubview (skView, atIndex: 0) lasa left = LeftLane (player: scene.player) let middle = MiddleLane (player: scene.player) = LaneStateMachine (state: [stânga, mijlocul, dreapta]) stateMachine.enterState (MiddleLane) @IBAction func didPressButton (expeditor: UIButton) switch sender.tag case ButtonDirection.Left.rawValue: switch stateMachine.currentState : cazul StateMachine.enterState (MiddleLane) este MiddleLane: stateMachine.enterState (LeftLane) implicit: break caz ButtonDirection.Right.rawValue: switch stateMachine.currentState cazul este LeftLane: stateMachine.enterState (MiddleLane) cazul MiddleLane: stateMachine.enterState (TrueLane) implicit: break implicit: break
În viewDidLoad ()
, introducem SKView
obiect la index 0 astfel încât butoanele de control să fie vizibile și, de asemenea, să inițializăm mașina de stare.
În didPressButton (_ :)
, aflăm ce buton a apăsat utilizatorul, pe baza etichetelor butoanelor, și introduceți banda corectă de unde este în prezent mașina.
Construiți și conduceți jocul. Apăsați butonul stânga sau dreapta din partea de jos a ecranului pentru a face mașina să se deplaseze. Ar trebui să vedeți mașina și să vă deplasați în direcția butonului pe care l-ați apăsat.
Rețineți că pictogramele butoanelor pot să nu corespundă după cum se arată mai jos.
Pentru a remedia acest lucru, deschideți catalogul de active (Image.xcassets) și pentru fiecare imagine (Sageata stanga și Sageata dreapta) a stabilit Modul de redare la Imaginea originală.
Acum ar trebui să fii încrezător în utilizarea constrângerilor și acțiunilor în SpriteKit. După cum puteți vedea, aceste caracteristici ale cadrului fac foarte ușor să adăugați animații și mișcări unui joc SpriteKit.
În următorul tutorial al acestei serii, ne vom uita la nodurile camerei din SpriteKit, astfel încât mașina noastră să nu se miște mereu în partea de sus a ecranului. După aceasta, vom analiza în profunzime sistemul de simulare a fizicii din SpriteKit, cu accent pe corpurile fizicii și detectarea coliziunilor.
Ca întotdeauna, asigurați-vă că părăsiți comentariile și comentariile dvs. în comentariile de mai jos.