iOS 8 Ce este nou în SpriteKit, Partea 1


Acest tutorial oferă o imagine de ansamblu asupra noilor caracteristici ale cadrului SpriteKit introduse în iOS 8. Noile caracteristici sunt concepute pentru a facilita suportul pentru efecte avansate ale jocului și includ suportul pentru shaderele personalizate OpenGL ES, iluminare, umbre, efectele fizice și animațiile și integrarea cu SceneKit. În acest tutorial, veți învăța cum să implementați aceste noi caracteristici.

Înainte de a începe tutorialul, aș dori să-i mulțumesc lui Mélodie Deschans (Wicked Cat) pentru că ne-a oferit arta jocului folosită în această serie.

Cerințe preliminare

Acest tutorial presupune că sunteți familiarizat atât cu SpriteKit și Obiectiv-C. Pentru a interacționa cu shader și editorul de scenă fără întârziere de intrare, vă recomandăm să descărcați și să instalați Xcode 6.1 sau o versiune ulterioară. Descărcați proiectul Xcode de la GitHub, dacă doriți să continuați.

Seria Format

Această serie este împărțită în două tutoriale și acoperă cele mai importante caracteristici noi ale cadrului SpriteKit. În prima parte, ne uităm la shadere, iluminare și umbre. În partea a doua, voi vorbi despre fizică și integrarea SceneKit.

În timp ce fiecare parte din această serie se află pe cont propriu, vă recomand să urmați pas cu pas înțelegerea corectă a noilor caracteristici ale cadrului SpriteKit. După ce ați citit ambele părți, veți putea crea atât jocuri simple, cât și mai avansate, utilizând noile caracteristici ale cadrului SpriteKit.

1. Introducere

SpriteKit oferă o conductă de randare care poate fi utilizată pentru a anima sprite. Conducta de randare conține o buclă de randare care se alternează între determinarea conținutului și a cadrelor de randare. Dezvoltatorul determină conținutul fiecărui cadru și modul în care acesta se schimbă. SpriteKit utilizează GPU-ul dispozitivului pentru a reda eficient fiecare cadru.

Cadrul SpriteKit este disponibil atât pe iOS cât și pe sistemul de operare OS X și suportă multe tipuri diferite de conținut, inclusiv sprite, text, forme și video.

Noile caracteristici SpriteKit introduse în iOS 8 sunt:

  • shader: Shadere personaliza modul în care lucrurile sunt atras de ecran. Ele sunt utile pentru adăugarea sau modificarea efectelor. Shaderele se bazează pe shaderul de fragmente OpenGL ES. Fiecare efect este aplicat pe bază de pixeli. Folosiți un limbaj de programare asemănător C pentru a programa shader-ul și poate fi implementat atât pentru iOS cât și pentru OS X. Un shader poate fi aplicat unei scene sau unor clase acceptate, SKSpriteNode, SKShapeNode, SKEmitterNode, SKEffectNode, și SKScene.
  • Lumini și umbre: Iluminarea este folosită pentru a ilumina o scenă sau o sprite. Fiecare lumină acceptă configurații de culoare, umbre și caderi. Puteți avea până la opt lumini diferite pe sprite.
  • Fizică: Fizica este folosită pentru a adăuga realism la jocuri. SpriteKit introduce patru tipuri noi de proprietăți fizice, fizică pe pixeli, constrângeri, kinematică inversă și câmpuri de fizică. Proprietățile per pixel oferă o reprezentare exactă a interacțiunii unui obiect. Datorită unei varietăți de constrângeri predefinite, poate fi eliminat codul de boilerplate în actualizările scenelor. Cinematica inversă este utilizată pentru a reprezenta articulațiile folosind sprite (puncte de ancorare, relații părinte-copil, rotație maximă și minimă și altele). În cele din urmă, puteți crea câmpuri fizice pentru a simula forțele gravitaționale, trageți și electromagnetice. Aceste noi caracteristici fizice fac simulări complexe mult mai ușor de implementat.
  • Integrarea SceneKit: Prin intermediul SceneKit, puteți include conținut 3D în aplicațiile SpriteKit și le puteți controla ca în mod obișnuit SKNode instanțe. Realizează conținutul 3D direct în interiorul conductei de redare SpriteKit. Puteți să importați fișiere .dae sau .abc existente SKScene.

2. Prezentarea proiectului

Am creat un proiect Xcode pentru a ne începe. Aceasta ne permite să începem imediat utilizarea noilor caracteristici SpriteKit. Cu toate acestea, există câteva lucruri pe care trebuie să le cunoașteți.

  • Proiectul utilizează obiectivul C, care vizează numai dispozitive iPhone care rulează iOS 8.1. Cu toate acestea, puteți modifica dispozitivul destinație dacă doriți.
  • Sub Resurse > Editor, veți găsi trei fișiere de scenă SpriteKit (.sks). În această serie, veți adăuga un al patrulea fișier de scenă SpriteKit. Fiecare fișier scenă este responsabil pentru o anumită secțiune tutorial.
  • Un shader poate fi inițializat una din cele două căi. Primul utilizează metoda tradițională, în timp ce al doilea utilizează noua metodă de scenă SpriteKit. Obiectivul este să învățați diferențele și, în proiectele viitoare, să alegeți cel care se potrivește nevoilor dvs..
  • Dacă instanțiați un SKScene folosind un fișier scenă SpriteKit, veți folosi întotdeauna unarchiveFromFile: metodă. Cu toate acestea, este obligatoriu să adăugați pentru fiecare fișier scenă SpriteKit cea corespunzătoare SKScene clasă.
  • Dacă instanțiați un SKScene obiect fără a utiliza un fișier scena SpriteKit, ar trebui să utilizați initWithSize: așa cum ați procedat în versiunile anterioare ale iOS.
  •  GameViewController și GameScene clasele conțin o metodă numită unarchiveFromFile:. Această metodă transformă obiectele grafice definite într-o scenă SpriteKit și le transformă într-un SKScene obiect. Metoda utilizează instancetype , deoarece returnează o instanță a clasei pe care o numește, în acest caz SKScene clasă.

Descărcați proiectul și faceți o clipă pentru a răsfoi dosarele, clasele și resursele acestuia. Construiți și executați proiectul pe un dispozitiv fizic sau în Simulatorul iOS. Dacă aplicația rulează fără probleme, atunci este timpul să începeți să explorați noile caracteristici iOS 8 SpriteKit.

3. Shaders

Pasul 1: Creați scena SpriteKit

În proiectul Xcode, adăugați un nou Scena SpriteKit fişier. Alege Fişier > Nou > Fişier…  și, de la Resursă secțiune, alegeți Scena SpriteKit. Numeste ShaderSceneEditor și faceți clic pe Crea. Ar trebui să apară o interfață gri.

Pasul 2: Configurarea scenei SpriteKit

În SKNode Inspector în dreapta, ar trebui să vedeți două proprietăți, mărimea și Gravitatie. Seteaza mărimea proprietate luând în considerare rezoluția ecranului dispozitivului și setați Gravitatie la 0.0.

Veți observa că mărimea dreptunghiului galben se modifică pentru a reflecta modificările pe care le-ați făcut. Dreptunghiul galben este interfața dispozitivului virtual. Vă arată cum sunt afișate obiectele pe dispozitiv.

Pasul 3: Adăugați o culoare Sprite

În interiorul Biblioteca de obiecte din dreapta, selectați Color Sprite și trageți-l în dreptunghiul galben.

Selectați sprite de culori și deschideți SKNode Inspector pe dreptul de a vedea proprietățile sale.

Puteți interacționa cu obiectul în timp real. Orice modificări pe care le faceți sunt afișate în editor. Poți să te joci cu Poziţie, mărimea, Culoare, sau Scară, dar ceea ce chiar vrei este Custom Shader opțiune. Cu toate acestea, veți observa că nu există încă un shader disponibil.

Pasul 4: Adăugați un Shader personalizat: Metoda 1

Adăugați un nou fișier sursă gol (Fişier > Nou> Fişier… ), alegeți Alte > gol de la iOS și denumiți-o Shader01.fsh. Adăugați următorul cod în fișierul pe care tocmai l-ați creat.

void principal () float currTime = u_time; vec2 uv = v_tex_coord; vec2 circleCenter = vec2 (0,5, 0,5); vec3 cercColor = vec3 (0,8, 0,5, 0,7); vec3 posColor = vec3 (uv, 0,5 + 0,5 * sin (currTime)) * cercColor; float illu = pow (1 - distanța (uv, circleCenter), 4.) * 1.2; illu * = (2. + abs (0.4 + cos (currTime * -20 + 50. * distanța (uv, circleCenter) / 1.5)); gl_FragColor = vec4 (posColor * illu * 2., illu * 2.) * v_color_mix.a; 

Blocul de cod de mai sus generează o fuziune de culori, luând în considerare centrul unui cerc și marginea acestuia. Apple a arătat acest shader în sesiunea lor SpriteKit în timpul WWDC 2014.

Reveniți la editor, selectați obiectul de culoare sprite și în Custom Shader selectați shaderul pe care tocmai l-ați creat. Ar trebui să vezi acum umbra în acțiune.

Pasul 5: Feedback în timp real

Programarea shadere folosind Xcode și SpriteKit este ușor, deoarece primiți feedback în timp real. Deschide Editor asistent și configurați-o pentru a afișa atât scena SpriteKit, cât și shaderul pe care tocmai l-ați creat.

Să vedem cum funcționează acest lucru. Introduceți o eroare de rulare în shader, de exemplu, schimbând numele unei variabile și salvați modificările pentru a vedea rezultatul.

După cum puteți vedea, Xcode oferă o modalitate rapidă și ușoară de a avertiza dezvoltatorul despre posibilele erori de shader. Avantajul este că nu aveți nevoie să construiți sau să implementați aplicația pe dispozitiv sau pe simulatorul iOS pentru a vedea dacă totul funcționează bine.

Acum este momentul să adăugați un alt shader și să îl programați manual.

Pasul 6: Adăugați un Shader personalizat: Metoda 2

În acest pas, veți afla cum să:

  • apelați manual un shader
  • atribuiți un shader unui obiect SpriteKit
  • creați și trimiteți proprietăți unui shader

În acest pas, veți adăuga un personalizat SKSpriteNode în poziția robinetului utilizatorului și apoi veți folosi un shader pentru a modifica culoarea texturii SKSpriteNode.

Primul pas este să adăugați un alt shader. Denumiți noul shader shader02.fsh și adăugați următorul bloc de coduri la fișierul shader:

void principal () gl_FragColor = textură2D (myTexture, v_tex_coord) * vec4 (1, 0,2, 0,2, 1); 

Deschideți fișierul de implementare al ShaderScene clasă. Primul pas este să detectezi dacă utilizatorul a lovit ecranul și a găsit locația robinetului. Pentru aceasta, trebuie să implementăm touchesBegan: withEvent: metodă. În cadrul acestei metode, adăugați a SKSpriteNode exemplu la locul robinetului. Puteți folosi orice sprite care vă place. Am folosit-o Spaceship.png, care este deja inclus în proiect.

- (void) atingeBegan: (NSSet *) atinge cu EventEvent: (UIEvent *) eveniment pentru (UITouch * atinge in atinge) CGPoint location = [touch locationInNode: self]; // Creați nodul SKSpriteNode * space = [SKSpriteNode spriteNodeWithImageNamed: @ "Spaceship.png"]; space.position = CGPointMake (locație.x, locație.y); [self addChild: spațiu]; 

Apoi creăm un SKShader obiect și inițializați-l folosind shader02.fsh fişier:

SKShader * shader = [SKShader shaderWithFileNamed: @ "shader02.fsh"];

Este posibil să fi observat că fișierul sursă al shader-ului se referă la a myTexture obiect. Aceasta nu este o proprietate predefinită a shader-ului, ci o referință pe care aplicația trebuie să o treacă la shader. Următorul fragment de cod ilustrează modul în care puteți face acest lucru.

shader.uniforms = @ [[SKUniform uniformă cu nume: @ "myTexture" textură: [SKTexture textureWithImageNamed: @ "Spaceship.png"]]];

Apoi adăugăm shader-ul la SKSpriteNode obiect.

space.shader = shader;

Aceasta este ceea ce touchesBegan: withEvent: metoda ar trebui să arate ca:

- (void) atingeBegan: (NSSet *) atinge cu EventEvent: (UIEvent *) eveniment pentru (UITouch * atinge in atinge) CGPoint location = [touch locationInNode: self]; // Creați nodul SKSpriteNode * space = [SKSpriteNode spriteNodeWithImageNamed: @ "Spaceship.png"]; space.position = CGPointMake (locație.x, locație.y); [self addChild: spațiu]; SKShader * shader = [SKShader shaderWithFileNamed: @ "shader02.fsh"]; shader.uniforms = @ [[SKUniform uniformă cu nume: @ "myTexture" textură: [SKTexture textureWithImageNamed: @ "Spaceship.png"]]]; space.shader = shader; 

Construiți și conduceți proiectul. Apasă pe Shadere (initWithSize) și atingeți ecranul. De fiecare dată când atingeți ecranul, se adaugă o sprite de navă spațială cu textura modificată.

Folosind această opțiune, veți vedea că primul shader nu este prezentat pe ecran. Acest lucru se întâmplă deoarece acel shader a fost creat și configurat în interiorul editorului Scene SpriteKit. Pentru ao vedea, trebuie să inițializați ShaderScene clasa folosind unarchiveFromFile: metodă.

În GameScene.m, ar trebui să vedeți o secțiune care detectează și analizează robinetele utilizatorului touchesBegan: withEvent:. In secunda dacă clauză, inițiazăm o ShaderScene exemplu după cum se arată mai jos.

dacă ([node.name esteEqualToString: @ "buttonShaderCoder"]) ShaderScene * scena = [ShaderScene unarchiveFromFile: @ "ShaderSceneEditor"]; [self.scene.view presentScene: scenă]; 

Construiți și executați din nou proiectul, atingeți Shadere (initWithCoder) și atingeți ecranul. Ambele shadere sunt acum active într-o singură scenă SpriteKit.

4. Lumini și umbre

Iluminarea și umbrele sunt două proprietăți care joacă împreună. Scopul acestei secțiuni este de a adăuga mai multe noduri ușoare și sprite, și să se joace cu proprietățile lor.

Pasul 1: Adăugați o lumină

Deschis LightingSceneEditor.sks și răsfoiți obiectele din interiorul Biblioteca media pe dreapta. În Biblioteca media, puteți vedea resursele incluse în proiect.

Selectați și trageți background.jpg la dreptunghiul galben. Dacă nu ați modificat rezoluția implicită a scenei, imaginea trebuie să se potrivească în interiorul dreptunghiului.

Când selectați sprite, veți observa că are mai multe proprietăți cum ar fi Poziţie, mărimea, Z Poziţie, Mască de iluminare, Mască de mascare a umbrelor, Definiția fizicii, și multe altele.

Simțiți-vă liber să jucați cu aceste proprietăți. Deocamdată, totuși, este important să lăsați proprietățile la valorile implicite. Trageți a Ușoară obiect de la Biblioteca de obiecte pe dreapta pe sprite de fundal. Poziția luminii nu este importantă, dar alte proprietăți ale luminii sunt.

Aveți posibilitatea să configurați Culoare, Umbră, și Înconjurător culoare pentru a configura lumina și umbra. Poziția Z este înălțimea nodului față de nodul părinte. Setați-l la 1. Mască de iluminare definește categoriile la care aparține această lumină. Când o scenă este redată, este o lumină categoryBitMask proprietatea este comparată cu fiecare nod sprite lightingBitMask, shadowCastBitMask, și shadowedBitMask proprietăți. Dacă valorile se potrivesc, sprite interacționează cu lumina. Aceasta vă permite să definiți și să utilizați mai multe lumini care interacționează cu unul sau mai multe obiecte.

Probabil ați observat că fundalul nu sa schimbat după adăugarea luminii. Acest lucru se întâmplă deoarece masca de iluminare a luminii și a fundalului este diferită. Trebuie să setați masca de iluminare a fundalului la cea a luminii, care este 1 în exemplul nostru.

Actualizați fundalul în SKNode Inspector și apăsați enter. Efectul acestei schimbări este imediat. Lumina luminează acum fundalul în funcție de poziția sa. Puteți modifica poziția luminii pentru a vedea interacțiunea dintre fundal și nodurile luminoase în timp real.

Pentru a crește realismul fundalului sau pentru a accentua una dintre caracteristicile sale, jucați cu Finete și Contrast proprietăți. Redați cu valorile pentru a vedea modificările în timp real.

Pasul 2: Populați scenă

Acum este momentul să adăugați câteva obiecte care interacționează cu nodul luminos. În Biblioteca media, găsi crochete-o.png și crochete-x.png sprite și adăugați-le la scenă.

Fiecare sprite trebuie să fie configurat individual. Selectați fiecare sprite și setați Mască de iluminare, Shadow Mask Cast, și Poziția Z la 1. Masca de iluminare asigură faptul că sprite este afectată de nodul luminos, în timp ce masca de umbră a umbrei creează o umbră în timp real în funcție de poziția nodului luminos. În cele din urmă, setați Tipul corpului (Definiția fizicii) la Nici unul. Faceți asta pentru ambii sprites.

Ar fi trebuit să observați că, chiar și după setarea proprietăților iluminării și umbrelor, nu puteți vedea interacțiunea dintre lumină și noduri. Pentru aceasta, trebuie să construiți și să executați proiectul pe un dispozitiv fizic sau în Simulator.

Pasul 3: Iluminarea manuală

Știți deja cum să adăugați luminile utilizând editorul de scenă. Să vedem cum să adăugăm o lumină fără a folosi editorul de scenă.

Deschide LightingScene.m și în interior didMoveToView: metoda pe care o cream SKSpriteNode obiect și a SKLightNode obiect.

Pentru SKSpriteNode obiect, vom folosi Wicked-Cat.png sprite. Poziția nodului nu este atât de importantă, ci de valorile lui zPosition, shadowCastBitMask, și lightingBitMask sunteți. Deoarece SpriteKit analizează secvențial datele, trebuie să setați nodurile zPosition la 1 pentru ca acest sprite să fie vizibil, deasupra sprite-ului de fundal. Noi am stabilit shadowCastBitMask și lightingBitMask la 1.

Aceasta este ceea ce didMoveToView: metoda pare până acum:

- (void) didMoveToView: (SKView *) vizualizați SKSpriteNode * sprite = [SKSpriteNode spriteNodeWithImageNamed: @ "Wicked-Cat.png"]; [sprite setPosition: CGPointMake (auto.frame.size.width / 2, auto.frame.size.height / 2)]; [Sprite setScale: 0,6]; [sprite setZPoziție: 1]; [sprite setShadowCastBitMask: 1]; [sprite setLightingBitMask: 1]; [auto addChild: sprite]; 

Apoi, să adăugăm SKLightNode obiect. Ar trebui să acordați o atenție deosebită categoryBitMask proprietate. Dacă l-ați setat 1, această lumină va interacționa cu fiecare sprite. Numeste ușoară și stabilit zPosition la 1.

Fragmentul complet pentru SKLightNode ar trebui să arate astfel:

SKLightNode * light = [[SKLightNode alocare] init]; [light setName: @ "lumină"]; [setPosition ușor: CGPointMake (100, 100)]; [lumină setCategoryBitMask: 1]; [lumină setFalloff: 1,5]; [setZPosition de lumină: 1]; [light setAmbientColor: [Culoarea UICcolor alb]]; [light setLightColor: [[UICcolor alocat] initWithRed: 1.0 verde: 0.0 albastru: 0.0 alpha: .5]]; [light setShadowColor: [[UICcolor alocat] initWithRed: 0.9 verde: 0.25 albastru: 0.0 alpha: .5]]; [auto addChild: lumină];

Pasul 4: Modificați locația luminii

În acest moment aveți oa doua lumină. Dar să adăugăm o anumită interacțiune cu utilizatorul. Pentru asta, trebuie să adăugați touchesMoved: withEvent: și schimbați poziția luminii, ținând cont de locația robinetului.

-(void) atingeModed: (NSSet *) atinge cu EventEvent: (UIEvent *) eveniment pentru (UITouch * atinge in atinge) CGPoint location = [touch locationInNode: self]; [self childNodeWithName: @ "light"] Poziție = CGPointMake (location.x, location.y); 

In cele din urma,construiți și executați aplicația. Apasă pe Iluminat buton și ar trebui să vedeți ceva similar cu ecranul de mai jos:

Concluzie

Acesta încheie primul tutorial din seriile noastre cu două părți despre noile caracteristici ale SpriteKit introduse în iOS 8. În această parte, ați învățat să creați shadere personalizate și efecte de iluminare utilizând atât editorul SpriteKit Scene, cât și codul. Dacă aveți întrebări sau comentarii, ca întotdeauna, nu ezitați să renunțați la un comentariu.

Cod