Questo tutorial ti insegnerà a combinare UIKit
viste e il SKTransition
classe per creare transizioni belle e personalizzate tra diversi SKScenes
. Continuare a leggere!
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:
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.
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:
UIColor
oggetto per colorare la transizione intrinseca.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
.
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.
Ora che conosci le basi del SKTransition
classe, ora puoi iniziare la fase di programmazione.
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
.
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;
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);
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
.
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!
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).
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.
SKTransition
l'inizializzazione della transizione è simile a tutte le transizioni.Durata
il tempo è definito dal UISlider
valore.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!
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:
Nel corso di questo SKTransition
tutorial, abbiamo coperto quanto segue:
SKTransition
classe.SKTransition
opzioni.SKTransition
proprietà.UITableView
e UISlider
e usarli in parallelo con Sprite Kit.Se avete domande o commenti, non esitate a lasciarli qui sotto!