Lavorare con SKTransition

Questo tutorial ti insegnerà a combinare UIKit viste e il SKTransition classe per creare transizioni belle e personalizzate tra diversi SKScenes. Continuare a leggere!


Anteprima finale

Illustrazione del risultato finale.

1. Transizioni tra le scene

Le scene sono interfacce che contengono diversi oggetti vista. Normalmente, si progettano diverse scene per ogni parte del gioco e quindi si utilizzano le transizioni tra le scene secondo necessità. Ad esempio, potresti creare diverse classi di scene per rappresentare uno o tutti i seguenti concetti:

  • Una scena del menu principale per scegliere la difficoltà di un livello specifico che l'utente desidera riprodurre.
  • Una scena per configurare i dettagli degli effetti sonori e musicali di un gioco.
  • Una scena che fornisce l'interfaccia di gioco.
  • Una scena che fornisce l'interfaccia della classifica leader online.
  • Una scena che offre risultati di gioco attuali e generali.

Come puoi vedere, una scena può essere qualsiasi cosa che il programmatore vorrebbe creare. In genere, si passa a una nuova scena basata su obiettivi di gioco o input diretto dell'utente. Ad esempio, se il timer si esaurisce, può essere presentata una nuova scena che presenta un "game over". In alternativa, se un utente preme un pulsante di opzioni, è possibile passare a una nuova scena per configurare le impostazioni di gioco. Si noti che, nella fase di transizione, la proprietà della scena viene immediatamente aggiornata per puntare alla nuova scena. Dopo questo, si verifica la transizione.

Una transizione può anche avere un oggetto di transizione (un effetto o un'animazione). Quell'oggetto creerà una presentazione bella e dinamica quando si verifica la transizione. Esistono diversi oggetti e per un riferimento completo e ufficiale è necessario consultare il riferimento alla classe SKTransition.


2. Metodi di classe

Il SKTransition classe presenta diversi metodi e due proprietà (più su quelle successive). L'obiettivo di tutti i metodi è creare una transizione brillante e dinamica tra le scene. I metodi di classe possono essere suddivisi in quattro sezioni principali:

  • Con durata: Transizioni che si verificano in un determinato periodo di tempo.
  • Con il colore: Transizioni che useranno a UIColor oggetto per colorare la transizione intrinseca.
  • Con la direzione: Transizioni che verranno effettuate da una direzione specificata.
  • Con CIFilter: Transizioni che utilizzeranno un filtro personalizzato per produrre un effetto visivo nella transizione.

Durata e Colore sono oggetti semplici, ma entrambi Direzione e CIFilter non sono.

Come suggerisce il nome, la proprietà direction indica che la transizione avverrà in una direzione specifica. La proprietà direction può avere una delle quattro costanti. Queste costanti sono dichiarate come NS_ENUM, come questo:

 typedef NS_ENUM (NSInteger, SKTransitionDirection) SKTransitionDirectionUp, SKTransitionDirectionDown, SKTransitionDirectionRight, SKTransitionDirectionLeft,;

CIFilter è ancora più robusto di Direzione poiché è anche una classe di riferimento con metodi di classe, metodi di istanza e proprietà. Questo tutorial non coprirà il CIFilter approfondimento di classe, ma presenterà un esempio di come usarlo per creare un filtro personalizzato e l'inerente SKTransition. Un'ulteriore nota riguardante il CIFilter class: supporta dozzine di effetti, ma non tutti sono supportati dall'ultima versione di iOS. Per consultare l'elenco di compatibilità, consultare il Riferimento del filtro immagine di base.

Si noti che è possibile utilizzare diversi "metodi raggruppati" per creare un SKTransiton. Ma come fai a sapere quali possono essere combinati? Per questo, è necessario cercare la firma del metodo e determinare le proprietà accettate da ciascun metodo.

Ad esempio, analizziamo tre metodi per vedere cosa possono gestire:

  • doorsOpenVerticalWithDuration:
  • fadeWithColor: Durata:
  • revealWithDirection: Durata:

Come affermato in precedenza, i nomi dei metodi consentono di capire rapidamente cosa può fare ciascun metodo. Per elaborare, il doorsOpenVerticalWithDuration: metodo prenderà in considerazione solo una durata fadeWithColor: Durata: il metodo usa sia un colore che una durata. È necessario innanzitutto definire a UIColor oggetto e quindi una durata. Il revealWithDirection: Durata: il metodo utilizzerà solo una direzione, che a sua volta può essere una delle quattro proprietà. Nota che puoi anche estendere il SKTransition classe per creare transizioni personalizzate e partecipare Durata, Colore, Direzione, e CIFilter.


revealWithDirection (UP) illustration

3. Proprietà di classe

Il SKTransition la classe ha solo due proprietà: pausesIncomingScene e pausesOutgoingScene. Entrambi configurano se le animazioni vengono riprodotte durante la transizione e entrambe le proprietà lo sono booleano valori. La differenza è la seguente:

  • pausesIncomingScene determina se la scena in entrata viene messa in pausa durante la transizione.
  • pausesOutgoingScene determina se la scena in uscita viene messa in pausa durante la transizione.

Dal momento che entrambi sono booleano valori, la definizione è semplice e può essere compresa nel prossimo snippet:

 // altro codice ... transitionCrossFade = [SKTransition crossFadeWithDuration: 1]; transitionCrossFade.pausesIncomingScene = TRUE; transitionDoorsCloseHorizontal = [SKTransition doorsCloseHorizontalWithDuration: 2]; transitionDoorsCloseHorizontal.pausesOutgoingScene = FALSE;

Il pausesIncomingScene e pausesOutgoingScene le proprietà sull'oggetto di transizione definiscono quali animazioni vengono riprodotte durante la transizione. Per impostazione predefinita, entrambe le scene continuano a elaborare l'animazione durante la transizione. Tuttavia, potresti voler sospendere una o entrambe le scene fino al completamento della transizione.


4. Il progetto Tutorial

Ora che conosci le basi del SKTransition classe, ora puoi iniziare la fase di programmazione.

Passo 1

Il primo passo è aprire Xcode e iniziare una nuova SpriteKit progetto. Successivamente, dovresti aggiungere un altro Objective-C classe di nome TransitionResult e una super classe di SKScene.

L'obiettivo di questo progetto è di avere due classi che verranno scambiate tra loro. Il primo (La mia scena già definito da Xcode) conterrà a UITableView che manterrà il riferimento a ciascuno SKTransition. Il secondo (TransitionResult) sarà la scena di destinazione dopo una transizione.

Quando l'utente tocca lo schermo dopo una transizione, verrà nuovamente trasferito a La mia scena.

Passo 2

Nel MyScene.h, dichiarerai 3 oggetti: a UITableView, UISlider, e un NSArray. Il UITableView mostrerà i nomi di ogni transizione, il UISlider definirà il Durata di quella transizione, e il NSArray conterrà i nomi di ciascuno SKTransition. Il finale MyScene.h il codice sarà simile a questo snippet:

 @property (retain, nonatomic) IBOutlet UITableView * tableView; @property (nonatomic, retain) IBOutlet UISlider * sliderTimer; @property (strong, nonatomic) NSArray * transitionsArray;

Passaggio 3

Adesso focalizza la tua attenzione su La mia scena file di implementazione.

Il primo passo è usare il -(Id) initWithSize: (CGSize) dimensioni metodo per inizializzare gli oggetti di cui sopra. Una possibile configurazione è la seguente:

 _tableView = [[UITableView alloc] initWithFrame: CGRectMake (CGRectGetMinX (self.frame), CGRectGetMinY (self.frame) +20, CGRectGetMaxX (self.frame), CGRectGetMaxY (self.frame) -80)]; _tableView.dataSource = self; _tableView.delegate = self; _sliderTimer = [[UISlider alloc] initWithFrame: CGRectMake (CGRectGetMidX (self.frame) -70, CGRectGetMaxY (self.frame) -40, 140, 3)]; [_sliderTimer addTarget: self action: @selector (sliderAction) forControlEvents: UIControlEventValueChanged]; [_sliderTimer setBackgroundColor: [UIColor clearColor]]; _sliderTimer.minimumValue = 1; _sliderTimer.maximumValue = 4; _sliderTimer.continuous = YES; _sliderTimer.value = 1; _transitionsArray = [[NSArray alloc] initWithObjects: @ "crossFadeWithDuration", @ "doorsCloseHorizontalWithDuration", @ "doorsCloseVerticalWithDuration", @ "doorsOpenHorizontalWithDuration", @ "doorsOpenVerticalWithDuration", @ "doorwayWithDuration", @ "fadeWithColor: duration", @ "fadeWithDuration" , @ "flipHorizontalWithDuration", @ "flipVerticalWithDuration", @ "moveInWithDirectionDown: duration", @ "moveInWithDirectionUp: duration", @ "moveInWithDirectionLeft: duration", @ "moveInWithDirectionRight: duration", @ "pushWithDirection: duration", @ "revealWithDirection: duration ", @" transitionWithCIFilter: duration ", nil];

Tuttavia, viene presentato un avviso dal sliderAction manca. Il metodo aggiornerà in tempo reale il transitionTimerText tenendo conto del UISlider valore.

 -(void) sliderAction transitionTimerText.text = [[NSString alloc] initWithFormat: @ "Durata transizione:% f", _sliderTimer.value]; 

Si noti che le viste, la posizione, la configurazione e il layout sono completamente configurabili. Se vuoi, puoi accordarlo per i tuoi migliori interessi. Inoltre, si aggiungerà a SKLabelNode per memorizzare e visualizzare il UISlider valore. Tale valore sarà rappresentativo del SKTransition Duration effetti. Aggiungi il SKLabelNode * transitionTimerText al tuo file di implementazione e l'inizializzazione corrispondente sarà:

 transitionTimerText = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; transitionTimerText.text = [[NSString alloc] initWithFormat: @ "Durata transizione:% f", _sliderTimer.value]; transitionTimerText.fontSize = 10; transitionTimerText.color = [SKColor colorWithRed: 0 green: 0 blue: 0 alpha: 1]; transitionTimerText.position = CGPointMake (CGRectGetMidX (self.frame), CGRectGetMinY (self.frame) +45);

Passaggio 4

Ora che hai gli oggetti configurati devi solo aggiungerli alla scena. Per quello, userete il -(vuoto) didMoveToView: vista (SKView *) metodo. Aggiungilo al tuo file e all'interno aggiungi le viste di cui sopra alla vista principale:

 -(void) didMoveToView: (SKView *) view [self addChild: transitionTimerText]; [self.scene.view addSubview: _sliderTimer]; [self.scene.view addSubview: _tableView]; 

Se esegui il progetto ora vedrai due oggetti sullo schermo: a UISlider e a SKLabelNode.

Passaggio 5

Il prossimo passo è visualizzare il SKTransition metodi nel UITableView. Per questo, è necessario modificare il tuo MyScene.h file ed estendi la tua classe con il protocolli. Il finale MyScene.h dovrebbe assomigliare a questo:

 @interface MyScene: SKScene 

Torna al file di implementazione e ti verrà presentato un avvertimento. Questo avvertimento dice che è necessario implementare ulteriori metodi inerenti a UITableView. I metodi necessari sono: -(NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: sezione (NSInteger) e -(UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath. Il primo restituirà il numero di righe nella tabella, mentre il secondo gestirà la logica per ogni cella all'interno della tabella. Per ulteriori note riguardanti il UITableView classe, dovresti consultare la classe di riferimento ufficiale.

Il primo metodo è semplice ed è solo una riga:

 -(NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section return [_transitionsArray count]; 

Il secondo metodo è più complesso poiché è necessario definire le proprietà e le configurazioni della cella della tabella (contenuto della cella). In questo esempio, userai un semplice UITableViewCellStyleSubtitle. Se hai problemi a scrivere il metodo, la versione completa viene presentata sotto:

 -(UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath NSString * transitions = [_transitionsArray objectAtIndex: indexPath.row]; UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: @ "Identifier"]; if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle riuseIdentifier: @ "Identifier"];  [cell.textLabel setText: transitions]; cella di ritorno; 

Esegui il tuo codice ora e dovresti vedere ogni linea di celle con un nome univoco. Ogni nome rappresenta l'inerente SKTransiton usato se l'utente tocca quella cella. Noterai anche che il UITableView non ha un titolo. Risolviamolo!

Passaggio 6

Aggiungi il seguente metodo: - (NSString *) tableView: (UITableView *) tableView titleForHeaderInSection: sezione (NSInteger). All'interno di questo metodo, aggiungi il seguente codice:

 NSString * sectionName; switch (sezione) caso 0: sectionName = NSLocalizedString (@ "SKTransition List", @ "SKTransition List"); rompere; default: sectionName = @ ""; rompere;  return sectionName;

Questo metodo è autorizzato ad avere più titoli per più UITableView sezioni. Tuttavia, avremo solo una sezione, quindi il titolo sarà "SKTransition List" (o qualsiasi altra di tua scelta).

Passaggio 7

A questo punto, è necessario aggiungere l'interazione dell'utente alle celle. Per fare questo, è necessario un altro metodo aggiuntivo. Questa volta il -(void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath il metodo dovrebbe essere chiamato. Questo metodo è lungo, ma è semplice da capire. Assegnerai le risorse necessarie per ciascuno SKTransition e, in base alla cella intercettata, ne presenterai un'altra SKScene.

Il primo passo è importare il file TransitionResult file di intestazione, quindi definire a TransitionResult oggetto per il risultato SKScene. Dai un'occhiata a quanto segue per vedere questo in azione:

 TransitionResult * transitionResult; SKTransition * transitionCrossFade; SKTransition * transitionDoorsCloseHorizontal; SKTransition * transitionDoorsCloseVertical; SKTransition * transitiondoorsOpenHorizontal; SKTransition * transitionDoorsOpenVertical; SKTransition * transitionDoorway; SKTransition * transitionFadeWithColor; SKTransition * transitionFadeWithDuration; SKTransition * transitionFlipHorizontal; SKTransition * transitionFlipVertical; SKTransition * transitionMoveInWithDirectionDown; SKTransition * transitionMoveInWithDirectionUp; SKTransition * transitionMoveInWithDirectionLeft; SKTransition * transitionMoveInWithDirectionRight; SKTransition * transitionPushWithDirection; SKTransition * transitionRevealWithDirectionUp; SKTransition * transitionWithCIFilter;

Ora, nel -(void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath metodo, è il momento di allocare le risorse necessarie. Il codice completo è:

 transitionCrossFade = [SKTransition crossFadeWithDuration: _sliderTimer.value]; transitionCrossFade.pausesIncomingScene = TRUE; transitionDoorsCloseHorizontal = [SKTransition doorsCloseHorizontalWithDuration: _sliderTimer.value]; transitionDoorsCloseHorizontal.pausesOutgoingScene = FALSE; transitionDoorsCloseVertical = [SKTransition doorsCloseVerticalWithDuration: _sliderTimer.value]; transitiondoorsOpenHorizontal = [SKTransition doorsOpenHorizontalWithDuration: _sliderTimer.value]; transitionDoorsOpenVertical = [SKTransition doorsOpenVerticalWithDuration: _sliderTimer.value]; transitionDoorway = [SKTransition doorwayWithDuration: _sliderTimer.value]; transitionFadeWithColor = [SKTransition fadeWithColor: [UIColor yellowColor] durata: _sliderTimer.value]; transitionFadeWithDuration = [SKTransition fadeWithDuration: _sliderTimer.value]; transitionFlipHorizontal = [SKTransition flipHorizontalWithDuration: _sliderTimer.value]; transitionFlipVertical = [SKTransition flipVerticalWithDuration: _sliderTimer.value]; transitionMoveInWithDirectionDown = [SKTransition moveInWithDirection: SKTransitionDirectionDown duration: _sliderTimer.value]; transitionMoveInWithDirectionUp = [SKTransition moveInWithDirection: SKTransitionDirectionUp durata: _sliderTimer.value]; transitionMoveInWithDirectionLeft = [SKTransition moveInWithDirection: SKTransitionDirectionLeft duration: _sliderTimer.value]; transitionMoveInWithDirectionRight = [SKTransition moveInWithDirection: SKTransitionDirection Durata durata: _sliderTimer.value]; transitionPushWithDirection = [SKTransition pushWithDirection: SKTransitionDirectionDown duration: _sliderTimer.value]; transitionRevealWithDirectionUp = [SKTransition revealWithDirection: SKTransitionDirectionUp duration: _sliderTimer.value]; CGRect screenRect = [[UIScreen mainScreen] bounds]; CIVector * extent = [CIVector vectorWithX: 0 Y: 0 Z: screenRect.size.width W: screenRect.size.height]; transitionWithCIFilter = [SKTransition transitionWithCIFilter: [CIFilter filterWithName: @ "CIFlashTransition" keysAndValues: @ "inputExtent", extent, @ "inputCenter", [CIVector vectorWithX: 0.3 * screenRect.size.width Y: 0.7 * screenRect.size.height], @ "inputColor", [CIColor colorWithRed: 1.0 green: 0.8 blue: 0.6 alpha: 1], @ "inputMaxStriationRadius", @ 2.5, @ "inputStriationStrength", @ 0.5, @ "inputStriationContrast", @ 1.37, @ "inputFadeThreshold", @ 0.85, nil] duration: _sliderTimer.value]; transitionResult = [[TransitionResult alloc] initWithSize: CGSizeMake (CGRectGetMaxX (self.frame), CGRectGetMaxY (self.frame))]; switch (indexPath.row) case 0: [self.scene.view presentScene: transitionResult transition: transitionCrossFade]; [auto removeUIKitViews]; rompere; caso 1: [self.scene.view presentScene: transitionResult transition: transitionDoorsCloseHorizontal]; [auto removeUIKitViews]; rompere; caso 2: [self.scene.view presentScene: transitionResult transition: transitionDoorsCloseVertical]; [auto removeUIKitViews]; rompere; caso 3: [self.scene.view presentScene: transitionResult transition: transitiondoorsOpenHorizontal]; [auto removeUIKitViews]; rompere; caso 4: [self.scene.view presentScene: transitionResult transition: transitionDoorsOpenVertical]; [auto removeUIKitViews]; rompere; caso 5: [self.scene.view presentScene: transitionResult transition: transitionDoorway]; [auto removeUIKitViews]; rompere; caso 6: [self.scene.view presentScene: transitionResult transition: transitionFadeWithColor]; [auto removeUIKitViews]; rompere; caso 7: [self.scene.view presentScene: transitionResult transition: transitionFadeWithDuration]; [auto removeUIKitViews]; rompere; caso 8: [self.scene.view presentScene: transitionResult transition: transitionFlipHorizontal]; [auto removeUIKitViews]; rompere; caso 9: [self.scene.view presentScene: transitionResult transition: transitionFlipVertical]; [auto removeUIKitViews]; rompere; caso 10: [self.scene.view presentScene: transitionResult transition: transitionMoveInWithDirectionDown]; [auto removeUIKitViews]; rompere; caso 11: [self.scene.view presentScene: transitionResult transition: transitionMoveInWithDirectionUp]; [auto removeUIKitViews]; rompere; caso 12: [self.scene.view presentScene: transitionResult transition: transitionMoveInWithDirectionLeft]; [auto removeUIKitViews]; rompere; caso 13: [self.scene.view presentScene: transitionResult transition: transitionMoveInWithDirectionRight]; [auto removeUIKitViews]; rompere; caso 14: [self.scene.view presentScene: transitionResult transition: transitionPushWithDirection]; [auto removeUIKitViews]; rompere; caso 15: [self.scene.view presentScene: transitionResult transition: transitionRevealWithDirectionUp]; [auto removeUIKitViews]; rompere; caso 16: [self.scene.view presentScene: transitionResult transition: transitionWithCIFilter]; [auto removeUIKitViews]; rompere; default: break; 

Riceverai un avvertimento che dice che un metodo (removeUIKitViews) manca. Questo metodo è una semplice chiamata per rimuovere alcune viste dalla vista genitore e super. Mentre semplicistico, il codice necessario è:

 -(void) removeUIKitViews [transitionTimerText removeFromParent]; [_tableView removeFromSuperview]; [_sliderTimer removeFromSuperview]; 

Ora per diverse note riguardanti il -(void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath metodo.

  • Il SKTransition l'inizializzazione della transizione è simile a tutte le transizioni.
  • Il filtro definito è personalizzato. Come detto sopra, puoi riconfigurarlo o definire un filtro totalmente nuovo.
  • Il Durata il tempo è definito dal UISlider valore.

Passaggio 8

Per eseguire il codice e testare le transizioni, è necessario compilare il file TransitionResult classe. Sposta quella classe e aggiungi il -(Id) initWithSize: (CGSize) dimensioni metodo. È simile al MyScene.m metodo. Puoi provare a scrivere da solo. Copia e incolla dall'altra classe per far sembrare il prossimo metodo:

 -(id) initWithSize: (CGSize) size if (self = [super initWithSize: size]) self.backgroundColor = [SKColor colorWithRed: 0,35 verde: 0,45 blu: 0,23 alfa: 1,0]; SKLabelNode * myLabel = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; myLabel.text = @ "Tocca indietro"; myLabel.fontSize = 15; myLabel.position = CGPointMake (CGRectGetMidX (self.frame), CGRectGetMidY (self.frame)); [self addChild: myLabel];  return self; 

Ora puoi eseguire il codice e testare le transizioni. Vai avanti e provali!

Passaggio 9

Come avrai già notato, ogni volta che vuoi testare una nuova transizione devi eseguire nuovamente il codice. Quindi, modifichiamo il TransitionResult.m file che consente una navigazione infinita. Ogni volta che l'utente tocca lo schermo, verrà spostato nella scena iniziale.

Avrai bisogno del -(vuoto) touchBegan: (NSSet *) tocca Evento: (UIEvent *) evento metodo e sarà necessario importare il MyScene.h classe. Quindi, il passo finale è allocare e iniziare un oggetto di classe e scambiare le scene. Il prossimo frammento ti aiuterà a fare proprio questo:

 -(void) touchesBegan: (NSSet *) tocca conEvent: (UIEvent *) event MyScene * home = [[MyScene alloc] initWithSize: CGSizeMake (CGRectGetMaxX (self.frame), CGRectGetMaxY (self.frame))]; [self.scene.view presentScene: home]; 

Infine, esegui il tuo programma e prova tutto il SKTransitions. L'immagine successiva rappresenta una delle transizioni:


Un'altra illustrazione dell'effetto SKTRansition

Conclusione

Nel corso di questo SKTransition tutorial, abbiamo coperto quanto segue:

  • Una panoramica completa del SKTransition classe.
  • Come creare e configurare tutto il SKTransition opzioni.
  • Lavorando con SKTransition proprietà.
  • Come creare e configurare a UITableView e UISlider e usarli in parallelo con Sprite Kit.

Se avete domande o commenti, non esitate a lasciarli qui sotto!