iOS 8 Ce este nou în SpriteKit, Partea 2

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.

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.

Descărcați proiectul Xcode pe care l-am creat în articolul precedent de la GitHub dacă doriți să continuați.

1. Fizica

În iOS 8, SpriteKit a introdus noi caracteristici fizice, cum ar fi fizica pe pixeli, constrângeri, kinematică inversă și câmpuri de fizică.

Cinematica este procesul de calcul al poziției 3D a capătului unei structuri legate, având în vedere unghiurile tuturor articulațiilor. Kinematica inversă (IK) face opusul. Având în vedere punctul final al structurii, ce unghiuri trebuie să facă articulațiile pentru a atinge acest punct final? Următoarea imagine clarifică aceste concepte.

Cu SpriteKit, utilizați sprites pentru a reprezenta articulațiile care utilizează relația părinte-copil pentru a crea o ierarhie comună. Pentru fiecare relație, definiți constrângerile cinematice inverse pe fiecare îmbinare și controlați unghiul de rotație minim și maxim între ele. Rețineți că fiecare articulație se rotește în jurul punctului său de ancorare.

Pasul 1: Cinematica inversă (IK)

Deschide PhysicsSceneEditor și adăugați crochete-o.png sprite la dreptunghiul galben. Selectați sprite și schimbați Nume în SKNode Inspector la Rădăcină. Seteaza Definiția fizicii Tipul corpului la Nici unul.

Adăugați un al doilea sprite, wood.png și schimba-l Nume la FirstNode. Schimba Mamă câmp la Root. Mișcare FirstNode prin punerea ei pe dreapta Rădăcină și redimensionați-l pentru a crea un dreptunghi, după cum se arată mai jos. Seteaza Definiția fizicii Tipul corpului la Nici unul.

Rezultatul ar trebui să arate similar cu următoarea scenă.

Rețineți că atunci când selectați un nod sprite, în centrul său apare un cerc alb. Acest cerc reprezintă punctul de ancorare a nodului sprite în jurul căruia se efectuează fiecare rotire.

Pasul 2: Adăugați mai multe sprite

Urmați pașii anteriori și adăugați încă două sprites.

Primul Sprite

  • Adaugă altul crochete-o.png spiriduș.
  • Schimbă-l Nume SecondNode.
  • Schimbă-l Mamă la FirstNode.
  • Poziționați-o în partea dreaptă a paginii FirstNode.
  • Schimbă-l Definiția fizicii Tipul corpului la Nici unul.

Al doilea Sprite

  • Adaugă altul wood.png spiriduș.
  • Schimbă-l Nume câmp la ThirdNode.
  • Schimbă-l Mamă la SecondNode.
  • Poziționați-o în partea dreaptă a paginii SecondNode.
  • Redimensionați-l pentru a crea un dreptunghi.
  • Schimbă-l Definiția fizicii Tipul corpului la Nici unul.

Rezultatul ar trebui să arate similar cu următoarea scenă.

Pasul 3: Editați și simulați

Pentru a testa conexiunile, interacțiunile și constrângerile comune, nu este nevoie să construiți și să executați proiectul. Xcode oferă două moduri, editează și simulează.

Modul de simulare oferă un mediu de testare în timp real, în timp ce modul de editare este utilizat pentru a crea și edita scena. Până acum, am lucrat în modul de editare. Rețineți că orice modificări pe care le faceți în modul simulat nu sunt salvate.

În partea de jos a editorului de scenă, puteți vedea modul în care lucrați în prezent. Dacă bara inferioară a editorului de scenă este albă, atunci sunteți în modul de editare. Un fundal albastru indică faptul că sunteți în modul simulat. Faceți clic pe eticheta din bara inferioară pentru a comuta între cele două moduri.

Modificați modul pentru a simula și selectați spritele FirstNode, SecondNode și ThirdNode. Puteți selecta mai multe sprite, apăsând Comanda.

Apoi, apăsați Shift-Control-clic și mutați spritele în jurul scenei. Rezultatul este că nodurile sprite animă și se rotesc. Cu toate acestea, rotația este ciudată și trebuie corectată.

Pasul 4: constrângeri IK

Reveniți la modul de editare și adăugați câteva constrângeri la nodurile sprite. Selectați fiecare nod sprite și modificați proprietățile acestuia după cum urmează.

Selectează Rădăcină și SecondNode sprite și setați Condițiile IK Max Angle la 0. Selectează FirstNode și ThirdNode sprite noduri și set  Punct de ancorare X la 0 și IK Constrângeri Max. Unghi la 90.

Prin modificarea acestor proprietăți, poziția și mărimea nodurilor sprite se vor schimba. După adăugarea constrângerilor, reglați manual mărimea și poziția acestora și treceți la modul simulat pentru a testa noile constrângeri pe care le-am adăugat.

Imaginea de mai jos ilustrează configurația corectă a constrângerilor.

Pasul 5: Nodul câmpului magnetic

Câmpurile magnetice sunt, de asemenea, noi în SpriteKit. Să vedem cum funcționează acest lucru prin adăugarea unui câmp magnetic la scena fizică. Deschis PhysicsScene.m și o variabilă de exemplu numită magneticFieldNode de tip SKFieldNode.

@implementation PhysicsScene SKFieldNode * magneticFieldNode; 

În didMoveToView: , mai întâi configuram scena creând o SKPhysicsBody exemplu pentru scenă și adăugarea unei forțe gravitaționale. Aceasta înseamnă că orice noduri din scenă vor fi trase în jos.

SKPhysicsBody * physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect: self.frame]; [auto.physicsWorld setGravity: CGVectorMake (0, -9)]; [auto-setPhysicsBody: physicsBody];

Pentru a configura magneticFieldNode obiect, trebuie să configurați corpul său fizic, precum și poziția și puterea lui. Rețineți că fiecare SKFieldNode are proprietati proprii. Următorul fragment de cod arată modul de configurare a nodului de câmp magnetic. Adăugăm nodul nou ca nod copil la scena.

magneticFieldNode = [SKFieldNode magneticField]; [magneticFieldNode setPhysicsBody: [SKPhysicsBody bodyWithCircleOfRadius: 80]]; [magneticFieldNode setPosition: CGPointMake (100, 100)]; [magneticFieldNode setStrength: 3]; [auto addChild: magneticFieldNode];

Pasul 6: Interacțiuni

Pentru a vedea câmpul magnetic în acțiune, trebuie să adăugăm câteva noduri cu care nota câmpului magnetic poate interacționa. În următorul fragment de cod, creăm trei sute de sprite. Rețineți că fiecare nod sprite are propriul corp fizic și am setat affectedByGravity proprietate la DA.

pentru (int i = 0; i < 300; i++)  SKSpriteNode *node4 = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImageNamed:@"wood.png"] size:CGSizeMake(25, 25)]; [node4 setPhysicsBody:[SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(25, 25)]]; [node4 setPosition:CGPointMake(arc4random()%640, arc4random()%950)]; [node4.physicsBody setDynamic:YES]; [node4.physicsBody setAffectedByGravity:YES]; [node4.physicsBody setAllowsRotation:true]; [node4.physicsBody setMass:0.9]; [self addChild:node4]; 

Completat didMoveToView: metoda ar trebui să arate după cum urmează:

-(void) didMoveToView: (SKView *) vizualizare SKPhysicsBody * physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect: self.frame]; [auto.physicsWorld setGravity: CGVectorMake (0, -9)]; [auto-setPhysicsBody: physicsBody]; magneticFieldNode = [SKFieldNode magneticField]; [magneticFieldNode setPhysicsBody: [SKPhysicsBody bodyWithCircleOfRadius: 80]]; [magneticFieldNode setPosition: CGPointMake (100, 100)]; [magneticFieldNode setStrength: 3]; [auto addChild: magneticFieldNode]; pentru (int i = 0; i < 300; i++)  SKSpriteNode *node4 = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImageNamed:@"wood.png"] size:CGSizeMake(25, 25)]; [node4 setPhysicsBody:[SKPhysicsBody bodyWithRectangleOfSize:CGSizeMake(25, 25)]]; [node4 setPosition:CGPointMake(arc4random()%640, arc4random()%950)]; [node4.physicsBody setDynamic:YES]; [node4.physicsBody setAffectedByGravity:YES]; [node4.physicsBody setAllowsRotation:true]; [node4.physicsBody setMass:0.9]; [self addChild:node4];  

Înainte de a construi și a rula aplicația, vom trece peste touchesMoved: withEvent: astfel încât să puteți muta nodul câmpului magnetic atingând degetul.

-(void) atingeTransferul: (NSSet *) atinge cu EventEvent: (UIEvent *) eveniment pentru (UITouch * atinge in atinge) [magneticFieldNode setPosition: [atinge locInNode: auto]]; 

Construiți și rulați aplicația pentru a testa efectul nodului câmpului magnetic pe scena. Pentru informații suplimentare despre simularea fizicii utilizând cadrul SpriteKit, vă recomandăm să citiți documentația Apple despre acest subiect.

2. Integrarea SceneKit

SceneKit este un cadru Objective-C la nivel înalt pentru construirea de aplicații și jocuri care utilizează grafică 3D. Acesta susține importul, manipularea și redarea de active 3D. Algoritmul de redare necesită doar descrierea conținutului, animațiilor și acțiunilor scenei pe care doriți să le efectuați.

Prin SceneKit, acum puteți crea și distribui conținut 3D folosind SpriteKit. SceneKit are o structură arborescentă și poate fi folosit în două moduri:

  • un mediu SceneKit independent
  • integrat în SpriteKit

SceneKit are o compoziție de ierarhie de copaci. Într-un mediu stand-alone SceneKit, clasa de bază pentru structura arborelui este o SCNNode după cum se arată în diagrama de mai jos. Un SCNNode obiect de la sine nu are conținut vizibil atunci când scena care îl conține este redată. Pur și simplu definește o poziție în spațiu care reprezintă poziția, rotația și scara unui nod în raport cu nodul părinte.

T

Când integrați SceneKit într-o aplicație bazată pe SpriteKit, trebuie să definiți a SK3DNode obiect ca obiect rădăcină pentru scena dvs. Aceasta înseamnă că ierarhia de bază a SceneKit se modifică la următoarele:

Rețineți că nu este necesar fiecare nod copil în diagrama de mai sus. Definiți și configurați numai nodurile care se potrivesc nevoilor dvs. De exemplu, puteți adăuga un SCNLight nod pentru a ilumina scena, chiar dacă nu includeți SCNCamera nod în scenă.

Pasul 1: Previzualizarea live a modelelor

SpriteKit și SceneKit suportă un număr de formate de fișiere pentru importul de modele. Puteți vizualiza aceste modele în timp real în Xcode. În interiorul texturi dosar în proiectul dvs.(Resurse> Texturi), există un fișier numit ship.dae. Când selectați acest fișier, vi se prezintă o nouă interfață de utilizator după cum se arată mai jos.

În stânga editorului, puteți vedea două grupuri:

  • entităţile: Acest grup conține informații despre animațiile predefinite, poziția camerei, luminile și materialele definite de fișierul modelului. Fișierul pe care l-am deschis doar conține informații despre geometria modelului și despre materialul acestuia.
  • Graficul graficului: Acest grup conține informații despre rețeaua originală de obiecte. În acest caz, obiectul a fost creat în ansamblu și vedeți numai o singură plasă.

Pasul 2: Importul unui model extern

Pentru a utiliza SceneKit în combinație cu SpriteKit, trebuie să importați biblioteca SceneKit din cadrul SceneKit. Deschis SceneKitScene.m și includeți-o după cum se arată mai jos.

#include 

Vom folosi modelul stocat în ship.dae ca scenă 3D. În interiorul didMoveToView: metoda, creați SCNScene obiect care încarcă o scenă din acel fișier.

SCNScene * ShipScene = [SCNScene scenăNamed: @ "ship.dae"];

Amintiți-vă ierarhia de copaci pe care am menționat-o mai devreme? Pentru a adăuga shipScene obiecte față de SKScene obiect, sunt necesare două etape:

  • creeaza o SK3DNode obiect
  • definiți o scenă SceneKit pentru a reda

În acest caz, scena care trebuie făcută este shipScene. Rețineți că definiți și poziția și mărimea nodului.

SK3DNode * sk3DNodeFist = [[SK3DNode alocare] initWithViewportSize: CGSizeMake (300, 300)]; [sk3DNodeFist setPosition: CGPointMake (200,300)]; [sk3DNodeFist setScnScene: ShipScene];

În cele din urmă, adăugați SK3DNode obiect ca un nod copil la SKScene obiect.

[auto addChild: sk3DNodeFist];

Pentru a face rezultatul final un pic mai atrăgător, setați culoarea de fundal a scenei în verde, după cum se arată mai jos.

[auto setBackgroundColor: [SKColor greenColor]];

Asta este ceea ce este complet didMoveToView: metoda ar trebui să arate ca. Construiți și rulați aplicația pentru a vedea rezultatul.

-(void) didMoveToView: (SKView *) vizualizare [auto setBackgroundColor: [SKColor greenColor]]; SCNScene * ShipScene = [SCNScene scenăNamed: @ "ship.dae"]; SK3DNode * sk3DNodeFist = [[SK3DNode alocare] initWithViewportSize: CGSizeMake (300, 300)]; [sk3DNodeFist setPosition: CGPointMake (200,300)]; [sk3DNodeFist setScnScene: ShipScene]; [auto addChild: sk3DNodeFist]; 

Pasul 3: Crearea unei scene personalizate

Să creăm o scenă mai complexă care conține mai multe SCNNode obiecte. Pentru această a doua scenă, trebuie să creăm un altul SK3DNode obiect.

SK3DNode * sk3DNode = [[SK3DNode alocare] initWithViewportSize: CGSizeMake (400, 400)]; [sk3DNode setPosition: CGPointMake (150,200)]; 

Apoi, vom crea SCNScene obiect, cel care va conține nodurile scena copilului.

SCNScene * sceneObject = [SCNScene scenă];

Acest sceneObject va avea trei noduri:

  • Aparat foto: Acest nod este utilizat pentru a vizualiza scena printr-o poziție dată.
  • Ușoară: Acest nod vă permite să vedeți proprietăți diferite ale materialului obiect 3D. Definiți în mod normal tipul și culoarea luminii.
  • Obiect 3D: Acesta este obiectul importat sau definit din codul dvs. Implicit, SceneKit vă permite să definiți mai multe obiecte parametrice 3D, cum ar fi torus, cutie, piramida, sferă, cilindru, con, tub, capsulă, podea, text 3D sau o formă personalizată.

Pentru fiecare nod individual, efectuați întotdeauna trei acțiuni. Să luăm ca exemplu un nod al camerei.

  1. Creaza un SCNCamera obiect și să definească proprietățile sale.
  2. Creaza un SCNNode la care SCNCamera vor fi atribuite.
  3. Adaugă SCNNode ca nod copil la SCNScene obiect.

Să creați acum cele trei noduri pe care le-am menționat mai devreme. Aceasta este ceea ce trebuie să implementăm pentru a crea nodul camerei.

SCNCamera * camera = [Camera SCNCamera]; SCNNode * cameraNode = [nod SCNNode]; [cameraNode setCamera: camera]; [cameraNode setPosition: SCNVector3Make (0, 0, 40)]; [scenaObject.rootNode addChildNode: cameraNode];

În mod implicit, locația camerei și scena 3D sunt localizate la origine, (0,0,0). Folosind proprietatea de poziție, puteți ajusta camera de-a lungul celor trei axe x, y și z pentru a-și schimba poziția.

Nodul de lumină necesită puțin mai multă muncă, dar fragmentul de cod următor ar trebui să fie ușor de înțeles.

SCNLight * spotLight = [lumină SCNLight]; [tipul de tip spotLight: SCNLightTypeDirectional]; [spotLight setColor: [SKColor redColor]]; * SCNNode * spotLightNode = [nod SCNNode]; [spotLightNode setLight: spotLight]; [spotLightNode setPosition: SCNVector3Make (0, 0, 5)]; [cameraNode addChildNode: spotLightNode]; [scenaObject.rootNode addChildNode: spotLightNode];

Vom crea, de asemenea, un obiect torus, după cum se arată în fragmentul de cod următor.

SCNTorus * torus = [SCNTorus torusWithRingRadius: 13 pipeRadius: 1,5]; SCNNode * torusNode = [nodul SCNNode cu gheometrie: torus]; [torusNode setTransform: SCNMatrix4MakeRotare (M_PI / 3, 0, 1, 0)]; [scenaObject.rootNode addChildNode: torusNode];

În cele din urmă, am setat scena pe care dorim să o redați și adăugăm sk3DNode ca nod al copilului SKScene instanță.

[sk3DNode setScnScene: sceneObject]; [auto addChild: sk3DNode];

Acesta este ultimul didMoveToView: metoda ar trebui să arate ca.

-(void) didMoveToView: (SKView *) vizualizare [auto setBackgroundColor: [SKColor greenColor]]; SCNScene * ShipScene = [SCNScene scenăNamed: @ "ship.dae"]; SK3DNode * sk3DNodeFist = [[SK3DNode alocare] initWithViewportSize: CGSizeMake (300, 300)]; [sk3DNodeFist setPosition: CGPointMake (200,300)]; [sk3DNodeFist setScnScene: ShipScene]; [auto addChild: sk3DNodeFist]; SK3DNode * sk3DNode = [[SK3DNode alocare] initWithViewportSize: CGSizeMake (400, 400)]; [sk3DNode setPosition: CGPointMake (150,200)]; SCNScene * sceneObject = [SCNScene scenă]; SCNCamera * camera = [Camera SCNCamera]; SCNNode * cameraNode = [nod SCNNode]; [cameraNode setCamera: camera]; [cameraNode setPosition: SCNVector3Make (0, 0, 40)]; [scenaObject.rootNode addChildNode: cameraNode]; SCNLight * spotLight = [lumină SCNLight]; [tipul de tip spotLight: SCNLightTypeDirectional]; [spotLight setColor: [SKColor redColor]]; * SCNNode * spotLightNode = [nod SCNNode]; [spotLightNode setLight: spotLight]; [spotLightNode setPosition: SCNVector3Make (0, 0, 5)]; [cameraNode addChildNode: spotLightNode]; [scenaObject.rootNode addChildNode: spotLightNode]; SCNTorus * torus = [SCNTorus torusWithRingRadius: 13 pipeRadius: 1,5]; SCNNode * torusNode = [nodul SCNNode cu gheometrie: torus]; [torusNode setTransform: SCNMatrix4MakeRotare (M_PI / 3, 0, 1, 0)]; [scenaObject.rootNode addChildNode: torusNode]; [sk3DNode setScnScene: sceneObject]; [auto addChild: sk3DNode]; 

Construiți și executați aplicația. Ar trebui să vedeți ceva similar cu următoarea captură de ecran.

Pasul 4: Animarea scenei

Puteți anima scena folosind CABasicAnimation clasă. Trebuie doar să creați o instanță CABasicAnimation invocând animationWithKeyPath:. Animația pe care o creăm în următorul fragment de cod va trece pe o perioadă nedefinită și va avea o durată de cinci secunde. Adăugați următorul fragment de cod în secțiunea didMoveToView: metodă.

CABasicAnimation * torusRotation = [CABasicAnimation animationWithKeyPath: @ "rotație"]; torusRotation.byValue = [valoarea NSValueWithSCNVector4: SCNVector4Make (1, 1, 0, 4.0 * M_PI)]; [torusRotație setTemmingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionLinear]]; [torusRotație setRepeatCount: INFINITY]; [set de rotație: 5.0]; [torusNode addAnimation: torusRotație pentruKey: nil];

Creați și rulați aplicația pentru a testa animația.

3. Mai mult SpriteKit

Dacă doriți să aflați mai multe despre SpriteKit, vă încurajez să citiți următoarele tutoriale SpriteKit:

  • Construiți un joc de avion cu kitul Sprite 
  • Construiți comanda rachetelor cu kitul Sprite 
  • iOS SDK: construiți un joc de fapte

Dacă doriți să citiți mai multe despre cadrul SpriteKit, vă recomandăm să citiți Ghidul de programare SpriteKit al Apple sau să răsfoiți referința cadru.

Concluzie

Acest lucru încheie cel de-al doilea tutorial al acestei serii cu două părți privind noile caracteristici ale cadrului SpriteKit introdus în iOS 8. În această parte, ați învățat cum să utilizați simularea fizică și să integrați SceneKit. Dacă aveți întrebări sau comentarii, nu ezitați să renunțați la o linie în comentarii.

Cod