SpriteKit From Scratch vincoli e azioni

introduzione

In questa esercitazione, la seconda rata della serie SpriteKit From Scratch, vengono illustrati i vincoli e le azioni. Queste funzionalità sono utilizzate per aggiungere facilmente movimenti e animazioni al tuo gioco SpriteKit limitando al tempo stesso la posizione e l'orientamento dei nodi nel gioco.

Per seguire insieme a me, puoi utilizzare il progetto che hai creato nel primo tutorial di questa serie o scaricare una nuova copia da GitHub.

La grafica utilizzata per il gioco di questa serie può essere trovata su GraphicRiver. GraphicRiver è un'ottima fonte per trovare grafica e grafica per i tuoi giochi.

1. Classi di nodi e scene personalizzati

Prima di poter iniziare ad aggiungere vincoli e azioni a una scena, dobbiamo prima creare alcune classi in modo da poter lavorare con i nostri nodi nel codice. Crea una nuova classe, PlayerNode, basato sul iOS> Source> Cocoa Touch Class modello e assicurarsi che sia una sottoclasse di SKSpriteNode.

Se Xcode genera un errore dopo aver creato la classe, aggiungi un'istruzione import per il framework SpriteKit sotto importa UIKit dichiarazione:

import UIKit import SpriteKit

Quindi, dichiarare le seguenti tre proprietà nel file PlayerNode classe. Queste proprietà terranno i vincoli usati per limitare il movimento orizzontale dell'auto.

import UIKit import SpriteKit class PlayerNode: SKSpriteNode var leftConstraint: SKConstraint! var middleConstraint: SKConstraint! var rightConstraint: SKConstraint! 

Creane un altro Cocoa Touch Class e nominalo MainScene, rendendolo una sottoclasse di SKScene.

In alto, aggiungi una dichiarazione di importazione per il framework SpriteKit.

import UIKit import SpriteKit

Con queste classi create, aperte MainScene.sks, fare clic sullo sfondo grigio per selezionare la scena, aprire il Custom Class Inspector a destra, e impostare Classe personalizzata a MainScene.

Seleziona la macchina e imposta la sua classe a PlayerNode allo stesso modo che hai fatto per la scena. Infine, con la macchina ancora selezionata, apri il pulsante Attributi ispettore e cambiare NomeGiocatore.

Ora che abbiamo impostato le classi di base, possiamo iniziare a creare alcuni vincoli nel codice.

2. Vincoli

Vincoli in SpriteKit, rappresentati dal SKConstraint classe, sono usati per limitare la posizione e l'orientamento di particolari nodi. Si può ottenere molta varietà con i vincoli in quanto possono essere relativi alla scena o relativi ad altri nodi. I vincoli funzionano anche con intervalli di valori oltre ai valori costanti in modo che gli sprite all'interno della scena possano essere fissati a una posizione specifica o autorizzati a spostarsi all'interno di una determinata area.

I vincoli che stiamo per aggiungere sono i tre che abbiamo dichiarato nel PlayerNode classe. Questi vincoli verranno utilizzati per bloccare l'auto sulle tre corsie del gioco.

Aperto MainScene.swift e creare una proprietà per il giocatore di tipo PlayerNode!. Questa proprietà memorizzerà un riferimento al nodo del giocatore.

import UIKit import SpriteKit class MainScene: SKScene var player: PlayerNode! 

Successivamente, ignoriamo il didMoveToView (_ :) metodo del MainScene classe:

override func didMoveToView (visualizza: SKView) super.didMoveToView (view) size = view.frame.size se let foundPlayer = childNodeWithName ("Player") as? PlayerNode player = foundPlayer lascia center = size.width / 2.0, difference = CGFloat (70.0) player.leftConstraint = SKConstraint.positionX (SKRange (constantValue: center - difference)) player.middleConstraint = SKConstraint.positionX (SKRange (constantValue: center)) player.rightConstraint = SKConstraint.positionX (SKRange (constantValue: center + difference)) player.leftConstraint.enabled = false player.rightConstraint.enabled = false player.constraints = [player.leftConstraint, player.middleConstraint, player.rightConstraint ]

Passiamo al codice passo dopo passo. Il didMoveToView (_ :) il metodo viene chiamato ogni volta che la scena viene presentata da una vista. Dopo aver chiamato il didMoveToView (_ :) metodo della superclasse, ridimensioniamo la scena alla stessa dimensione della vista corrente. Questo assicura che la scena riempia sempre le dimensioni dello schermo del dispositivo corrente e si adatti correttamente.

Accediamo allo sprite del giocatore che abbiamo aggiunto nell'editor di scene Xcode cercandolo con il nome che gli abbiamo dato in precedenza. Quindi assegniamo questo valore al giocatore proprietà.

Dopo aver calcolato il centro della scena e specificando una differenza costante di 70,0, creiamo i vincoli dello sprite. Usando il positionX (_ :) metodo di classe del SKConstraint classe, creiamo i vincoli sinistro, centrale e destro per lo sprite del giocatore. Questo metodo richiede un SKRange istanza come parametro, che nel nostro caso è un intervallo con un valore costante. Se si desidera esaminare i possibili vincoli e intervalli in SpriteKit, si consiglia di dare un'occhiata al SKConstraint e SKRange riferimenti di classe.

Disabilitiamo i vincoli sinistro e destro, perché non vogliamo che questi agiscano sul nodo del giocatore all'avvio del gioco. Infine, assegniamo questi vincoli al vincoli proprietà del nodo giocatore. Questa proprietà è definita nel SKNode classe.

Costruisci ed esegui il tuo gioco su qualsiasi simulatore o dispositivo fisico. Ora dovresti vedere che la tua scena è ridimensionata correttamente con l'auto centrata in basso.

Puoi vedere che l'auto è ora vincolata al centro orizzontale della scena ed è in grado di essere vincolata alle corsie sinistra e destra una volta aggiunto del movimento al gioco.

2. azioni

Le azioni in SpriteKit sono rappresentate dai potenti SKAction classe. Le azioni ci permettono di animare e muovere facilmente gli sprite in una scena. Vengono eseguiti dai nodi e vengono valutati dalle API SpriteKit e funzionano insieme a vincoli e simulazioni fisiche.

Oltre a specificare cosa fa un'azione, puoi anche programmare come funziona l'azione configurandola. È possibile, ad esempio, sospendere e riprendere le azioni o configurare il comportamento di andamento di un'azione. Questo ti dà un maggiore controllo dato che puoi facilmente accelerare o rallentare determinate azioni per produrre alcuni interessanti elementi di gioco.

Analogamente a come i nodi possono avere nodi figli, esistono tre tipi di azioni che possono avere azioni figlio:

  • sequenza azioni, che eseguono una serie di azioni una dopo l'altra
  • gruppo azioni, che eseguono una serie di azioni tutte allo stesso tempo
  • ripetendo azioni, che ripetono una singola azione per un dato numero di volte o indefinitamente

Puoi creare azioni a livello di programmazione o nell'editor di scene di Xcode, che abbiamo utilizzato nel tutorial precedente. Utilizzeremo entrambe le tecniche in questo tutorial.

Aperto MainScene.sks e fare clic sull'icona accanto al Animare pulsante in basso a sinistra della scena per far apparire il Vista Editor azioni.

Quindi, scorrere verso il basso nella Libreria di oggetti di destra e trova il Sposta azione articolo. Fare clic e trascinare questo nella timeline del Vista Editor azioni e posizionarlo sul bordo sinistro come mostrato di seguito:

Ciò fa iniziare l'azione a 00:00, cioè, non appena viene presentata la scena. Se posizionato altrove, l'azione inizierà l'esecuzione dopo l'intervallo di tempo mostrato nella parte superiore della timeline.

Passa il mouse sopra l'azione e fai clic sulla piccola icona a forma di freccia in basso a sinistra. Nel popup che appare, clicca su infinito pulsante a sinistra. Questo fa sì che l'azione si ripeta per sempre.

Con l'azione ancora selezionata, apri il Ispettore degli attributi a destra e cambia il Offset Y valore a 100.

Gli altri valori specificano che l'auto inizia ad animare immediatamente (Orario di inizio) e ogni 1 secondo (Durata) si sposterà 0 punti nel X direzione e 100 nel direzione (Compensare). Il Funzione di cronometraggio la proprietà può essere utilizzata per avviare e / o interrompere gradualmente un'azione. In questo caso, stiamo usando Lineare, il che significa che l'auto si muove sempre alla stessa velocità.

Infine, per testare l'azione, fare clic su Animare pulsante in basso a sinistra dell'editor di scena. La barra degli strumenti in basso dovrebbe diventare blu e l'auto dovrebbe iniziare a salire.

Con l'azione di spostamento implementata, è il momento di creare le azioni orizzontali a livello di programmazione. Prima di farlo, dobbiamo aggiungere un po 'di logica in modo che i pulsanti del gioco possano controllare l'auto.

Crea un nuovo file scegliendo il iOS> Origine> File Swift modello e chiamarlo LaneStateMachine.

Aggiungi il seguente codice al nuovo file:

import GameplayKit class LaneStateMachine: GKStateMachine  class LaneState: GKState var playerNode: PlayerNode init (player: PlayerNode) playerNode = player classe LeftLane: LaneState override func isValidNextState (stateClass: AnyClass) -> Bool if stateClass == MiddleLane.self return true return false override func didEnterWithPreviousState (previousState: GKState?) PlayerNode.moveInDirection (.Left, toLane: self) classe MiddleLane: LaneState override func isValidNextState (stateClass: AnyClass) -> Bool  if stateClass == LeftLane.self || stateClass == RightLane.self return true return false override func didEnterWithPreviousState (previousState: GKState?) if previousState è LeftLane playerNode.moveInDirection (.Right, toLane: self) else if previousState è RightLane playerNode.moveInDirection ( .Left, toLane: self) class RightLane: LaneState override func isValidNextState (stateClass: AnyClass) -> Bool if stateClass == MiddleLane.self return true return false override func didEnterWithPreviousState (previousState: GKState?) playerNode.moveInDirection (.Right, toLane: self)

Tutto questo codice fa, è utilizzare il nuovo framework GameplayKit per creare una macchina a stati che rappresenta le tre corsie e il movimento tra di loro nel gioco. Se vuoi capire meglio cosa sta facendo questo codice, dai un'occhiata al mio tutorial su GameplayKit.

Avanti, aperto PlayerNode.swift e aggiungere i seguenti due metodi al PlayerNode classe:

func disableAllConstraints () leftConstraint.enabled = false middleConstraint.enabled = false rightConstraint.enabled = false func moveInDirection (direction: ButtonDirection, toLane lane: LaneState) disableAllConstraints () lascia changeInX = (direction == .Left)? -70.0: 70.0 let rotation = (direction == .Left)? M_PI / 4: -M_PI / 4 let duration = 0.5 let moveAction = SKAction.moveByX (CGFloat (changeInX), y: 0.0, duration: duration) lascia ruotareAction = SKAction.rotateByAngle (CGFloat (rotation), duration: duration / 2) rotateAction.timingMode = .EaseInEaseOut lascia ruotareSequence = SKAction.sequence ([ruotaAction, ruotaAction.reversedAction ()]) lascia moveGroup = SKAction.group ([moveAction, ruotaSequenza]) lascia il completamento = SKAction.runBlock () -> Void in switch lane case è LeftLane: self.leftConstraint.enabled = true case is MiddleLane: self.middleConstraint.enabled = true case is RightLane: self.rightConstraint.enabled = true default: break let sequenceAction = SKAction.sequence ([moveGroup, completamento]) runAction (sequenceAction)

Il disableAllConstraints () metodo è un metodo comodo per disabilitare i vincoli del nodo giocatore.

Nel moveInDirection (_: toLane :), determiniamo in quale direzione l'auto dovrebbe muoversi in orizzontale, -70,0 quando si sposta a sinistra e +70,0 quando si muove a destra. Quindi calcoliamo l'angolo corretto (in radianti) per ruotare l'auto quando ci si muove. Si noti che i numeri positivi rappresentano una rotazione in senso antiorario.

Dopo aver specificato una durata costante, creiamo lo spostamento e ruotiamo le azioni usando il moveByX (_: y: durata :) e rotateByAngle (_: durata :) metodi di classe rispettivamente. Creiamo una sequenza di rotazione per riportare l'auto indietro a come era prima del movimento. Il reversedAction () il metodo crea automaticamente il contrario di un'azione per te.

Successivamente, creiamo un'azione di movimento gruppo per eseguire contemporaneamente il movimento orizzontale e la rotazione. Infine, creiamo un'azione di completamento per eseguire una chiusura quando eseguita. In questa chiusura, scopriamo in quale corsia è posizionata la macchina e abilitare il vincolo corretto per quella corsia.

Aperto ViewController.swift e aggiungi una proprietà, Statemachine, di tipo LaneStateMachine! al ViewController classe.

class ViewController: UIViewController var stateMachine: LaneStateMachine! ...

Sostituisci le implementazioni di viewDidLoad () e didPressButton (_ :) nel ViewController classe con il seguente:

override func viewDidLoad () super.viewDidLoad () lascia skView = SKView (frame: view.frame) lascia scena = MainScene (fileNamed: "MainScene")! skView.presentScene (scena) view.insertSubview (skView, atIndex: 0) lascia left = LeftLane (player: scene.player) lascia middle = MiddleLane (player: scene.player) let right = RightLane (player: scene.player) stateMachine = LaneStateMachine (stati: [left, middle, right]) stateMachine.enterState (MiddleLane) @IBAction func fattoPressButton (sender: UIButton) switch sender.tag case ButtonDirection.Left.rawValue: switch stateMachine.currentState case is RightLane : caseMachine.enterState (MiddleLane) è MiddleLane: stateMachine.enterState (LeftLane) valore predefinito: break case ButtonDirection.Right.rawValue: switch stateMachine.currentState case è LeftLane: stateMachine.enterState (MiddleLane) case è MiddleLane: stateMachine.enterState (RightLane) default: break default: break

Nel viewDidLoad (), inseriamo il SKView oggetto all'indice 0 in modo che i pulsanti di controllo siano visibili e inizializziamo anche la macchina a stati.

Nel didPressButton (_ :), scopriamo quale pulsante l'utente ha premuto, in base alle etichette dei pulsanti, e immettere la corsia corretta da dove si trova attualmente l'auto.

Costruisci e avvia il gioco. Premi il pulsante sinistro o destro nella parte inferiore dello schermo per far muovere l'auto. Dovresti vedere la macchina girare e muoversi nella direzione del pulsante che hai premuto.

Si noti che le icone dei pulsanti potrebbero non corrispondere come mostrato di seguito.

Per risolvere questo problema, apri il catalogo delle risorse (Image.xcassets) e per ogni immagine (Freccia sinistraFreccia destra) impostato Modalità di renderingImmagine originale.

Conclusione

Ora dovresti essere sicuro di usare i vincoli e le azioni in SpriteKit. Come puoi vedere, queste caratteristiche del framework rendono molto facile aggiungere animazioni e movimenti a un gioco SpriteKit.

Nel prossimo tutorial di questa serie, esamineremo i nodi delle telecamere in SpriteKit in modo che la nostra auto non si sposti sempre dalla parte superiore dello schermo. Dopodiché analizzeremo in dettaglio il sistema di simulazione fisica in SpriteKit con particolare attenzione ai corpi fisici e al rilevamento delle collisioni.

Come sempre, assicurati di lasciare i tuoi commenti e feedback nei commenti qui sotto.