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.
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.
Î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.
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.
Urmați pașii anteriori și adăugați încă două sprites.
Rezultatul ar trebui să arate similar cu următoarea scenă.
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ă.
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.
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];
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.
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:
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.
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ă.
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:
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:
SK3DNode
obiectÎ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];
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:
Pentru fiecare nod individual, efectuați întotdeauna trei acțiuni. Să luăm ca exemplu un nod al camerei.
SCNCamera
obiect și să definească proprietățile sale.SCNNode
la care SCNCamera
vor fi atribuite.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.
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.
Dacă doriți să aflați mai multe despre SpriteKit, vă încurajez să citiți următoarele tutoriale SpriteKit:
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.
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.