Lucrul cu SKTransition

Acest tutorial vă va învăța să vă combinați UIKit vizualizări și SKTransition pentru a crea tranziții frumoase, personalizate între diferite SKScenes. Citește mai departe!


Vizualizare finală

Ilustrația rezultatului final.

1. Transitions between Scenes

Scenele sunt interfețe care dețin mai multe obiecte de vizualizare. În mod normal, proiectați mai multe scene pentru fiecare parte a jocului dvs. și apoi utilizați tranzițiile între scenele după cum este necesar. De exemplu, puteți crea diferite clase de scenă pentru a reprezenta oricare dintre următoarele concepte:

  • Scena unui meniu principal pentru a alege dificultatea unui anumit nivel pe care utilizatorul dorește să îl joace.
  • O scenă pentru a configura detaliile efectelor sonore și muzicale ale unui joc.
  • O scenă care oferă interfața joc-joc.
  • O scenă care oferă interfața de lider online.
  • O scenă care oferă performanțe actuale și generale.

După cum puteți vedea, o scenă poate fi ceva ce programatorul ar dori să creeze. De obicei, treci la o scenă nouă bazată pe obiectivele jocului sau pe intrarea directă a utilizatorului. De exemplu, în cazul în care cronometrul se termină, poate fi prezentată o nouă scenă care prezintă un "joc peste". Alternativ, dacă un utilizator apasă un buton de opțiuni, puteți trece la o nouă scenă pentru a configura setările jocului. Rețineți că, la pasul de tranziție, proprietatea scenei este imediat actualizată pentru a indica noua scenă. După aceasta, se produce tranziția.

O tranziție poate avea și un obiect de tranziție (un efect sau o animație). Acest obiect va crea o prezentare dinamică și frumoasă atunci când are loc tranziția. Există mai multe obiecte și pentru o referire completă și oficială ar trebui să consultați referința de clasă SKTransition.


2. Metode de clasă

SKTransition clasa prezintă mai multe metode și două proprietăți (mai multe despre acestea mai târziu). Scopul tuturor metodelor este de a crea o tranziție strălucitoare și dinamică între scene. Metodele de clasă pot fi împărțite în patru secțiuni principale:

  • Cu Durata: Tranziții care vor avea loc într-o anumită perioadă de timp.
  • Cu culoarea: Tranziții care vor folosi a UIColor obiect de culoare tranziția inerentă.
  • Cu Direcția: Tranziții care vor fi făcute dintr-o direcție specificată.
  • Cu CIFilter: Tranziții care vor utiliza un filtru personalizat pentru a produce un efect vizual în tranziție.

Durată și Culoare sunt obiecte simple, dar ambele Direcţie și CIFilter nu sunt.

Ca sugestii de nume, proprietatea direcției înseamnă că tranziția va avea loc într-o anumită direcție. Proprietatea direcției poate avea una din cele patru constante. Aceste constante sunt declarate ca fiind NS_ENUM, asa:

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

CIFilter este chiar mai robust decât Direcţie deoarece este de asemenea o clasă de referință cu metode de clasă, metode de instanță și proprietăți. Acest tutorial nu va acoperi CIFilter clasa în profunzime, dar va prezenta un exemplu de cum să-l utilizați pentru a crea un filtru personalizat și inerent SKTransition. O notă suplimentară privind CIFilter clasa: suportă zeci de efecte, dar nu toate sunt susținute de cea mai recentă versiune de iOS. Ar trebui să consultați Referința filtrelor de bază pentru a vedea lista de compatibilitate.

Rețineți că puteți utiliza mai multe "metode grupate" pentru a crea o metodă SKTransiton. Dar cum știți care dintre ele pot fi combinate? Pentru aceasta, trebuie să vă uitați la semnătura metodei și să determinați proprietățile acceptate de fiecare metodă.

De exemplu, să analizăm trei metode pentru a vedea ce pot face:

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

După cum sa menționat anterior, numele metodelor vă permit să înțelegeți rapid ce pot face fiecare metodă. Pentru a elabora, doorsOpenVerticalWithDuration: metoda va lua în considerare doar o durată fadeWithColor: Durata: metoda utilizează atât o culoare, cât și o durată. Trebuie mai întâi să definiți a UIColor obiect și apoi un timp de durată. revealWithDirection: Durata: metoda va folosi doar o direcție, care, la rândul său, poate fi una din cele patru proprietăți. Rețineți că puteți extinde, de asemenea SKTransition pentru a crea tranziții personalizate și pentru a vă alătura Durată, Culoare, Direcţie, și CIFilter.


revealWithDirection (UP) ilustrare

3. Proprietățile clasei

SKTransition clasa are doar două proprietăți: pausesIncomingScene și pausesOutgoingScene. Ambele configurează dacă animațiile se joacă în timpul tranziției și ambele proprietăți sunt boolean valori. Diferența este după cum urmează:

  • pausesIncomingScene determină dacă scena primită este întreruptă în timpul tranziției.
  • pausesOutgoingScene determină dacă scena de ieșire este întreruptă în timpul tranziției.

Deoarece ambele sunt boolean valori, definiția este ușoară și poate fi înțeleasă în fragmentul următor:

 // alt cod ... transitionCrossFade = [SKTransition crossFadeWithDuration: 1]; transitionCrossFade.pausesIncomingScene = TRUE; tranzițieDeclorareHorizontal = [Ușile de tranziție înclinateDeformare orizontală: 2]; transitionDoorsCloseHorizontal.pausesOutgoingScene = FALSE;

pausesIncomingScene și pausesOutgoingScene proprietățile de pe obiectul de tranziție definesc care animații sunt redate în timpul tranziției. În mod implicit, ambele scene continuă să proceseze animația în timpul tranziției. Cu toate acestea, este posibil să doriți să întrerupeți una sau ambele scene până când tranziția va fi finalizată.


4. Proiectul Tutorial

Acum că știți elementele de bază ale SKTransition , puteți începe etapa de programare.

Pasul 1

Primul pas este să deschideți Xcode și să începeți un nou SpriteKit proiect. Apoi, ar trebui să adăugați altul Obiectiv-C clasa numita TransitionResult și o super-clasă de SKScene.

Obiectivul acestui proiect este acela de a avea două clase care vor fi schimbate între ele. Primul (Scena mea deja definit de Xcode) va conține a UITableView care va menține referința la fiecare SKTransition. Al doilea (TransitionResult) va fi scena destinației după o tranziție.

Atunci când utilizatorul întrerupe ecranul după o tranziție, acesta va fi din nou transferat la Scena mea.

Pasul 2

În MyScene.h, veți declara 3 obiecte: a UITableView, UISlider, si un NSArray. UITableView va afișa numele fiecărei tranziții, UISlider va defini Durată din acea tranziție și NSArray vor conține numele fiecăruia SKTransition. Finala MyScene.h codul va fi similar cu acest fragment:

 @property (reține, nonatomic) IBOutlet UITableView * tableView; @property (nonatomic, reține) IBOutlet UISlider * sliderTimer; @property (puternic, nonatomic) NSArray * transitionsArray;

Pasul 3

Acum, concentrați-vă atenția în Scena mea fișier de implementare.

Primul pas este de a utiliza -(Id) initWithSize: (CGSize) dimensiunea de inițializare a obiectelor menționate mai sus. O posibilă configurare a configurației este următoarea:

 _tableView = [[UITableView alloc] initWithFrame: CGRectMake (CGRectGetMinX (auto.frame), CGRectGetMinY (auto.frame) +20, CGRectGetMaxX (selfframe), CGRectGetMaxY (self.frame) -80)]; _tableView.dataSource = auto; _tableView.delegate = auto; _sliderTimer = [[UISlider alin] initWithFrame: CGRectMake (CGRectGetMidX (auto.frame) -70, CGRectGetMaxY (auto.frame) -40, 140, 3)]; [_sliderTimer addTarget: acțiune auto: @selector (sliderAction) forControlEvents: UIControlEventValueChanged]; [_sliderTimer setBackgroundColor: [UICcolor clearColor]]; _sliderTimer.minimumValue = 1; _sliderTimer.maximumValue = 4; _sliderTimer.continuous = DA; _sliderTimer.value = 1; _ "TransformăriArray = [[NSArray alocare] initWithObjects: @" crossFadeWithDuration ", @" doorsCloseHorizontalWithDuration ", @" doorsOseVerticalWithDuration ", @" doorOpenHorizontalWithDuration " , @ "moveInWithDirectionUp: duration", @ "moveInWithDirectionUp: duration", @ "moveInWithDirectionRight: duration", @ "pushWithDirection: duration", @ "revealWithDirection: durată ", @" transitionWithCIFilter: duration ", nil];

Cu toate acestea, un avertisment este prezentat de la sliderAction lipseste. Metoda va actualiza în timp real transitionTimerText ținând seama de UISlider valoare.

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

Rețineți că vizualizările, locația, configurația și aspectul sunt complet configurabile. Dacă doriți, puteți să vă acordați acest lucru pentru interesele cele mai bune. În plus, veți adăuga o SKLabelNode pentru a stoca și a afișa UISlider valoare. Această valoare va fi reprezentativă pentru Durata de tranziție SKT efecte. Adaugă SKLabelNode * transitionTimerText la fișierul de implementare și la inițializarea corespunzătoare vor fi:

 transitionTimerText = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; transitionTimerText.text = [[NSString alloc] initWithFormat: @ "Durata de tranziție:% f", _sliderTimer.value]; transitionTimerText.fontSize = 10; transitionTimerText.color = [SKColor colorWithRed: 0 verde: 0 albastru: 0 alfa: 1]; transitionTimerText.position = CGPointMake (CGRectGetMidX (auto.frame), CGRectGetMinY (auto.frame) +45);

Pasul 4

Acum că ați configurat obiectele, trebuie doar să le adăugați la scenă. Pentru asta, veți folosi -(void) didMoveToView: (SKView *) vizualizare metodă. Adăugați-l în fișierul dvs. și adăugați în interior afișările menționate mai sus în vizualizarea principală:

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

Dacă executați proiectul acum, veți vedea două obiecte pe ecran: a UISlider și a SKLabelNode.

Pasul 5

Următorul pas este afișarea SKTransition metode în UITableView. Pentru aceasta, trebuie să vă modificați MyScene.h fișier și extindeți clasa cu protocoale. Finala MyScene.h ar trebui să arate astfel:

 @ interfață MyScene: SKScene 

Reveniți la fișierul de implementare și veți primi un avertisment. Acest avertisment spune că trebuie să pună în aplicare alte metode inerente UITableView. Metodele necesare sunt: -(NSInteger) tableView: (UITableView *) tabelVizualizare numărOfRowsInSecție: (NSInteger) secțiune și -(UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath. Primul va returna numărul de rânduri din tabel, în timp ce al doilea va ocupa logica pentru fiecare celulă din tabel. Pentru note suplimentare referitoare la UITableView clasa, trebuie să consultați clasa oficială de referință.

Prima metodă este simplă și este doar o singură linie:

 -(NSInteger) tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) sectiunea return [_transitionsArray Count]; 

A doua metodă este mai complexă, deoarece trebuie să definim proprietățile și configurațiile celulei tabelului (conținutul celulelor). În acest exemplu, veți folosi un simplu UITableViewCellStyleSubtitle. Dacă aveți probleme la scrierea metodei, versiunea completă este prezentată mai jos:

 -(UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath NSString * tranziții = [transciseArray objectAtIndex: indexPath.row]; UITableViewCell * celula = [tableView dequeueReusableCellWithIdentifier: @ "Identifier"]; dacă (celula == zero) cell = [[UITableViewCell alin] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: @ "Identifier"];  [cell.textLabel setText: tranziții]; celule retur; 

Rulați codul acum și ar trebui să vedeți fiecare linie celulară cu un nume unic. Fiecare nume reprezintă inerentul SKTransiton se utilizează dacă utilizatorul pune în legătură acea celulă. Veți observa, de asemenea, că UITableView nu are un titlu. Să rezolvăm asta!

Pasul 6

Adăugați următoarea metodă: - (NSString *) tableView: (UITableView *) tableVizualizare titluForHeaderInSection: (NSInteger). În cadrul acestei metode, adăugați următorul cod:

 NSString * sectionName; comutator (secțiune) cazul 0: sectionName = NSLocalizedString ("SKTransition List", "SKTransition List"); pauză; implicit: sectionName = @ ""; pauză;  se întoarce secțiuneaNume;

Această metodă are permisiunea de a avea mai multe titluri pentru mai multe UITableView secțiuni. Cu toate acestea, vom avea doar o singură secțiune, astfel că titlul va fi "Lista de tranziție SK" (sau oricare altul la alegere).

Pasul 7

În acest moment, trebuie să adăugați interacțiunea utilizatorului cu celulele. Pentru aceasta, este necesară o altă metodă suplimentară. De data aceasta -(void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath ar trebui să fie chemată metoda. Această metodă este lungă, dar este ușor de înțeles. Veți aloca resursele necesare pentru fiecare SKTransition și, pe baza celulei lovit, veți prezenta un alt SKScene.

Primul pas este importul TransitionResult header, apoi definiți a TransitionResult obiect pentru rezultat SKScene. Aruncați o privire la următoarele pentru a vedea acest lucru în acțiune:

 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;

Acum, în -(void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath este timpul să alocăm resursele necesare. Codul complet este:

 transitionCrossFade = [SchimbareFranțareFranțare: _sliderTimer.value]; transitionCrossFade.pausesIncomingScene = TRUE; tranzițieDoarme ClosestHorizontal = [Ușile de tranziție SKCloseHorizontalWithDuration: _sliderTimer.value]; transitionDoorsCloseHorizontal.pausesOutgoingScene = FALSE; transitionDoorsCloseVertical = [Uși de tranziție închiseVerticalWithDuration: _sliderTimer.value]; tranziție la domiciliuOpenHorizontal = [Ușile de tranzițieDeschiderea orizontală: _sliderTimer.value]; transitionDoorsOpenVertical = [Ușile de tranzițieDeschideVerticalWithDuration: _sliderTimer.value]; transitionDoorway = [SKTransition doorwayWithDuration: _sliderTimer.value]; transitionFadeWithColor = [SKTransition fadeWithColor: [Durata UICcolor galben]: _sliderTimer.value]; transitionFadeWithDuration = [SKTransition FadeWithDuration: _sliderTimer.value]; tranzițieFlipHorizontal = [SKTransition flipHorizontalWithDuration: _sliderTimer.value]; tranzițieFlipVertical = [SKTransition flipVerticalWithDuration: _sliderTimer.value]; transitionMoveInWithDirectionDown = [SKTransition moveInWithDirection: SKTransitionDirectionDown duration: _sliderTimer.value]; transitionMoveInWithDirectionUp = [SKTransition moveInWithDirection: Durata SKTransitionDirectionUp: _sliderTimer.value]; transitionMoveInWithDirectionLeft = [SKTransition moveInWithDirection: SKTransitionDirection Durata Dreapta: _sliderTimer.value]; transitionMoveInWithDirectionRight = [SKTransition moveInWithDirection: SKTransitionDirection Durata de timp: _sliderTimer.value]; transitionPushWithDirection = [SKTransition pushWithDirection: SKTransitionDirectionDown duration: _sliderTimer.value]; transitionRevealWithDirectionUp = [SKTransition revealWithDirection: SKTransitionDirectionUp durata: _sliderTimer.value]; CGRect screenRect = [[UIScreen mainScreen] limite]; CIVector * extensia = [CIVector vectorWithX: 0 Y: 0 Z: screenRect.size.width W: screenRect.size.height]; tranzițieWithCIFilter = [tranziția SKTransitionWithCIFilter: [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 verde: 0.8 albastru: 0.6 alpha: 1], "inputMaxStriationRadius", @ 2.5, @ inputStriationStrength, @ 0.5, @ inputStriationContrast, @ 1.37, @ "inputFadeThreshold" @ 0.85, zero] durată: _sliderTimer.value]; transitionResult = [[TransitionResult alocare] initWithSize: CGSizeMake (CGRectGetMaxX (auto.frame), CGRectGetMaxY (auto.frame)); switch (indexPath.row) caz 0: [auto.scene.view prezentScene: tranziție tranzițieResult: transitionCrossFade]; [self removeUIKitViews]; pauză; cazul 1: [auto.scene.view prezentScene: tranzițieRezultatul tranziție: tranzițieDoarceCloseHorizontală]; [self removeUIKitViews]; pauză; cazul 2: [auto.scene.view prezentScene: tranzițieRezultatul tranziție: tranzițieDoori închisVertical]; [self removeUIKitViews]; pauză; cazul 3: [auto.scene.view prezentScene: tranzițieRezultatul tranziție: tranzițiedoorsOpenHorizontal]; [self removeUIKitViews]; pauză; cazul 4: [auto.scene.view prezentScene: tranzițieRezultatul tranziție: tranzițieDoateOpenVertică]; [self removeUIKitViews]; pauză; cazul 5: [auto.scene.view presentScene: tranziție tranzițieResult: tranzițieDoarway]; [self removeUIKitViews]; pauză; cazul 6: [auto.scene.view presentScene: tranziție tranzițieResult: transitionFadeWithColor]; [self removeUIKitViews]; pauză; cazul 7: [auto.scene.view prezentScene: tranziție tranzițieResult: tranzițieFadeWithDuration]; [self removeUIKitViews]; pauză; cazul 8: [auto.scene.view prezentScene: tranzițieRezultatul tranziție: tranzițieFlipHorizontal]; [self removeUIKitViews]; pauză; cazul 9: [auto.scene.view prezentScene: tranzițieRezultatul tranziție: tranzițieFlipVertical]; [self removeUIKitViews]; pauză; cazul 10: [auto.scene.view presentScene: tranziție tranzițieResult: transitionMoveInWithDirectionDown]; [self removeUIKitViews]; pauză; cazul 11: [auto.scene.view presentScene: tranziție tranzițieResult: transitionMoveInWithDirectionUp]; [self removeUIKitViews]; pauză; cazul 12: [auto.scene.view presentScene: tranziție tranzițieResult: transitionMoveInWithDirectionLeft]; [self removeUIKitViews]; pauză; cazul 13: [auto.scene.view presentScene: tranziție tranzițieResult: transitionMoveInWithDirectionRight]; [self removeUIKitViews]; pauză; cazul 14: [auto.scene.view presentScene: tranziție tranziție tranziție: transitionPushWithDirection]; [self removeUIKitViews]; pauză; cazul 15: [auto.scene.view presentScene: tranzițieRezultă tranziție: transitionRevealWithDirectionUp]; [self removeUIKitViews]; pauză; cazul 16: [auto.scene.view presentScene: tranziție tranzițieResult: tranzițieWithCIFilter]; [self removeUIKitViews]; pauză; prestabilit: pauză; 

Veți primi un avertisment care spune că o metodă (removeUIKitViews) lipseste. Această metodă este un apel simplu pentru a elimina unele vederi din vizualizarea parentală și super. În timp ce este simplist, codul necesar este:

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

Acum pentru mai multe note cu privire la -(void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath metodă.

  • SKTransition inițierea tranziției este similară cu toate tranzițiile.
  • Filtrul definit este unul personalizat. După cum sa menționat mai sus, îl puteți reconfigura sau puteți defini un filtru complet nou.
  • Durată timpul este definit de UISlider valoare.

Pasul 8

Pentru a rula codul și pentru a testa tranzițiile, va trebui să introduceți TransitionResult clasă. Deplasați acea clasă și adăugați-o -(Id) initWithSize: (CGSize) dimensiunea metodă. Este similar cu MyScene.m metodă. Puteți încerca să-l scrieți singur. Copiați-și lipiți de la cealaltă clasă pentru a face ca aceasta să arate ca următoarea metodă:

 -(dimensiune CGSize) if (auto = [super initWithSize: size]) auto.backgroundColor = [SKColor colorWithRed: 0.35 verde: 0.45 albastru: 0.23 alfa: 1.0]; SKLabelNode * myLabel = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; myLabel.text = @ "Apăsați înapoi"; myLabel.fontSize = 15; myLabel.position = CGPointMake (CGRectGetMidX (auto.frame), CGRectGetMidY (auto.frame)); [self addChild: MyLabel];  întoarce-te; 

Acum puteți rula codul și puteți testa tranzițiile. Mergeți și încercați!

Pasul 9

După cum probabil ați observat deja, de fiecare dată când doriți să testați o nouă tranziție, trebuie să rulați din nou codul. Deci, haideți să modificăm TransitionResult.m fișier care permite o navigare infinită. De fiecare dată când utilizatorul fixează ecranul, acesta va fi mutat la scena inițială.

Veți avea nevoie de -(void) touchesBegan: (NSSet *) atinge evenimentul Event: (UIEvent *) și va trebui să importați MyScene.h clasă. Deci, pasul final este de a aloca și de a iniția un obiect de clasă și de a schimba scenele. Fragmentul următor vă va ajuta să faceți exact acest lucru:

 -(void) atingeBegan: (NSSet *) atinge cu EventEvent: (UIEvent *) eveniment MyScene * home = [[MyScene alin] initWithSize: CGSizeMake (CGRectGetMaxX (selfframe), CGRectGetMaxY (self.frame) [self.scene.view presentScene: home]; 

În cele din urmă, executați programul și testați toate SKTransitions. Următoarea imagine reprezintă una dintre tranziții:


O altă ilustrare a efectului SKTRansition

Concluzie

Pe parcursul acestui lucru SKTransition tutorial, am abordat următoarele:

  • O prezentare completă a SKTransition clasă.
  • Cum se creează și se configurează toate SKTransition Opțiuni.
  • Lucrând cu SKTransition proprietăţi.
  • Cum se creează și se configurează o UITableView și UISlider și să le folosiți în paralel cu Sprite Kit.

Dacă aveți întrebări sau comentarii, vă rugăm să le lăsați mai jos!

Cod