Sprite Kit este una dintre cele mai interesante noi tehnologii disponibile cu iOS 7 SDK și Xcode 5, dar cum se compară cu un motor de joc stabilit, cum ar fi Cocos2D? Acest tutorial va oferi o scurtă introducere la Sprite Kit înainte de a lua o privire detaliată asupra modului în care se stivează împotriva lui Cocos2D.
Dintre toate jocurile disponibile în App Store, multe dintre cele mai descărcate și cele mai profitabile sunt jocuri 2D. Unele titluri iconice din această categorie includ Angry Birds, Tiny Wings și Cut Rope. Conducerea succesului acestor jocuri are mai multe caracteristici comune: grafica frumoasă, efecte particulare, un motor de fizică, animație fără sudură și efecte sonore convingătoare.
Înainte de lansarea iOS 7 SDK, construirea de jocuri ca acestea a fost posibilă numai cu ajutorul unor cadre și motoare de la terți. Acum, odată cu introducerea Sprite Kit, dezvoltatorii nu trebuie să caute decât SDK-ul nativ pentru a găsi tot ce au nevoie pentru a putea construi jocuri de 2D și 2.5D. Funcționalitățile oferite de Sprite Kit includ Sprite, Forme, Particule (de exemplu foc, fum etc.), Animații, Simulare fizică, Audio, Video și Efecte vizuale. Xcode 5 oferă acum suport pentru pachetele de texturi și designul de particule.
Sprite Kit poate fi extras în mod logic în următoarele trei părți:
Există câteva beneficii foarte bune pentru a avea o platformă de jocuri 2D și 2.5D furnizată și întreținută de Apple. Luați în considerare următoarele aspecte:
Dezvoltarea nativă și instrumentele native se referă la performanță.
În ciuda faptului că dezvoltatorii doresc ca jocurile lor să ruleze pe cât mai multe platforme diferite, un joc nativ va avea aproape întotdeauna o performanță mai bună decât un joc non-nativ. În plus, dacă instrumentele pentru dezvoltarea acelor jocuri sunt native, se poate asigura că codul este integrat cu ecosistemul platformei.
După cum sa menționat mai sus, Sprite Kit și Xcode 5 combină multe dintre componentele esențiale pentru construirea de jocuri minunate. Aceasta înseamnă că dezvoltarea poate fi mai raționalizată, iar instrumentele vor fi mai fiabile și mai eficiente.
Scrierea unui joc folosind un cadru terț sau motor de joc este întotdeauna o sabie cu două tăișuri. Nu stim niciodata daca aceste unelte vor fi compatibile cu viitoare actualizari de platforme sau chiar daca jocul va functiona bine dupa o actualizare. Când lucrurile nu se pot rupe, nu este sigur cât va dura comunitatea pentru a repara bug-urile.
Cocos2D este un exemplu de proiect open source care trebuie să rezolve această problemă. Codul evoluează în mod constant și la fiecare lansare nouă trebuie făcute mai multe măsuri de siguranță pentru a garanta că aplicațiile construite cu Cocos2D vor rula în continuare pe cea mai nouă versiune de iOS și cele mai recente echipamente hardware.
Cu Sprite Kit, Apple a furnizat un set de instrumente pentru a se asigura că codul de joc va funcționa pe orice dispozitiv compatibil fără probleme. Rețineți că Sprite Kit nu este doar un cadru iOS. Dezvoltatorii pot începe să construiască jocuri Sprite Kit pentru OS X, de asemenea, și este un pariu sigur că jocurile Sprite Kit vor rula pe orice dispozitive viitoare iOS.
Ușurința de utilizare a fost un factor major în spatele succesului motoarelor de jocuri precum Cocos2D. În general, dezvoltatorii au descoperit că Cocos2D este mult mai ușor de implementat decât alte alternative native, cum ar fi OpenGL ES. Cu Cocos2D, toate apelurile API la nivel scăzut au fost transformate în metode simple.
Sprite Kit urmărește această abordare și oferă sute de metode care fac procesul de dezvoltare a jocului mult mai ușor. Sprite Kit este și prietenos. Dispune de API personalizat, bine conceput și are o documentație structurată completă. Apple a făcut o treabă remarcabilă de ascuțire a acestui instrument pentru a utiliza devleoperii de la terțe părți. Cel mai mare avantaj al tuturor este că este complet încărcat cu fiecare resursă de care aveți nevoie pentru a crea un joc. Fizica, efectele sonore, efectele particulelor, texturi, managementul scenelor - totul este inclus într-un singur pachet.
Rețineți că, la prezentarea inițială a Sprite Kit, Ricardo Quesada, dezvoltatorul plumb al Cocos2D a declarat următoarele pe Twitter:
Sprite Kit este foarte bun. Cu mai puține caracteristici decât Cocos2D, dar mai bine. Îmi place integrarea fizică.
Aceasta este o mare laudă venită de la una dintre mințile de frunte din spatele Cocos2D!
Caracteristică | Sprite Kit | Cocos2d |
Sursa deschisa | Nu | da |
Obiectiv-C sprijin nativ | da | da |
Grafică motor | da | da |
Animații | da | da |
Simularea fizicii | Da (integrat) | Nu (necesită Box2D sau Chipmunk) |
Efectele particulelor | da | da |
Xcode Integrare nativă | da | Nu |
Crearea Atlasului Automat | da | Nu |
Built-In Editor de particule | da | Nu |
shader | Nu | da |
aparat foto | Nu | da |
Deci, ce arată de fapt proiectele cu fiecare motor de joc? Pentru a răspunde la această întrebare, autorii au inclus codul sursă complet atât pentru un Sprite Kit cât și pentru un proiect Cocos2D. Puteți utiliza aceste proiecte ca o comparație la nivel înalt a fiecărui motor de joc.
În această secțiune vom detalia sarcini și concepte comune, arătând cum să le implementăm atât în Cocos2D, cât și în Sprite Kit.
CCLayer sau SkScene este obiectul principal folosit pentru desenarea altor obiecte. Vă puteți gândi la aceasta ca la vizualizarea implicită care va primi toate obiectele, animațiile și evenimentele de atingere.
Trecerea între scene în Cocos2D se face cu următorii pași:
GameScene * jocScene = [[GameScene alocare] init]; [[CCDirector sharedDirector] înlocuieșteScene: gameScene];
Rețineți că GameScene.h
fișierul trebuie să fie de CCLayer
și să aibă inițializatorul specific disponibil.
Scrisoare de joc interfață: CCLayer + (CCScene *);
În GameScene.m
, implementarea inițială este:
+(CCScene *) scena CCScene * scena = [nodul CCScene]; GameScene * layer = [nodul GameScene]; [scena addChild: strat]; scena revenirii; - (id) init if ((self = [super init])) // Codul dvs. aici returnați;
În Sprite Kit tranziția este similară:
GameScene * gameScene = [[GameScene alocare] initWithSize: CGSizeMake (1024, 768)]; [self.scene.view presentScene: gameScene];
GameScene
trebuie să fie din SKScene
categorie, și -(Id) initWithSize: (CGSize) dimensiunea
este inițializatorul personalizat. Un exemplu simplu:
-(id) initWithSize: dimensiunea (CGSize) if (self = [super initWithSize: size]) // codul vostru retur;
Obiectele Sprite sunt utilizate în mod normal pentru a afișa un fel de imagine. Poate avea mai multe proprietăți, cum ar fi: rotație, scală, poziție, cadre, ID-uri și multe altele. Implementarea Cocos2D și a Sprite Kit este similară. Implementarea Cocos2D este:
CCSprite * aSprite; aSprite = [CCSprite spriteWithFile: @ "player.png"]; aSprite.scale = .5; aSprite.position = ccp (_size.width / 1.30, _size.height / 1.25); [self addChild: aSprite];
În timp ce în Sprite Kit implementarea este:
SKSpriteNode * planShadow = [SKSpriteNode spriteNodeWithImageNamed: @ "player.png"]; planeShadow.scale = 0.5; planShadow.position = CGPointMake (CGRectGetMidX (auto.frame) + 100, CGRectGetMidY (auto.frame) +200); [auto addChild: planeShadow];
Elementele de etichetare sunt utilizate pentru a afișa textul. Poate avea mai multe proprietăți, inclusiv text, dimensiune text, culoare text, poziție și multe altele. Implementarea Cocos2D și a Sprite Kit este similară. Implementarea Cocos2D este:
CCLabelTTF * label = [CCLabelTTF etichetăWithString: @ "Hello World" fontName: @ "Marker Felt" fontSize: 64]; // adresați-vă directorului pentru dimensiunea ferestrei CGSize size = [[CCDirector sharedDirector] winSize]; label.position = ccp (size.width / 2, size.height / 2); [self addChild: etichetă];
Implementarea Sprite Kit este:
SKLabelNode * gameScene = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; [gameScene setText: @ "Joc nou"]; [jocScene setFontSize: 18]; gameScene setPoziție: CGPointMake (CGRectGetMidX (auto.frame) + 5, CGRectGetMidY (auto.frame) -40)]; [auto addChild: gameScene];
În Cocos2D, meniurile sunt create folosind două obiecte: CCMenu
și CCMenuItem
. Următorul exemplu prezintă un meniu cu 2 opțiuni în Cocos2D:
Dimensiunea CGSize = [[CCDirector sharedDirector] winSize]; [CCMenuItemFont setFontSize: 28]; CCMenuItem * itemNewGame = [CCMenuItemFont itemWithString: @ Blocul "Joc nou": ^ (expeditor id) // Codul dvs.]; CCMenuItem * itemOptions = [CCMenuItemFont itemWithString: @ Blocul "Opțiuni": ^ (expeditor id) NSLog (@ "Al doilea element"); ]; Meniul CCMenu * = [meniul CCMenuWithItems: itemNewGame, itemOptions, nil]; [meniu aliniate în ordine interioară pe orizontală: 20]; [setPosition meniu: ccp (size.width / 2, size.height / 2 - 50)]; [self addChild: meniu];
SpiteKit nu include nici un tip de obiect specific meniului. Trebuie să creați un handler de evenimente pentru un anumit obiect pentru al activa pentru introducerea de către utilizator. Deci, pentru a "crea" un meniu, trebuie să utilizați un obiect UIKit sau un obiect Sprite Kit.
Următorul exemplu folosește a SKLabelNode
ca element de meniu. În primul rând, definim SKLabelNode
:
SKLabelNode * gameScene = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; [gameScene setText: @ "Joc nou"]; [jocScene setFontSize: 18]; [jocScene setPoziție: CGPointMake (CGRectGetMidX (auto.frame) + 5, CGRectGetMidY (auto.frame) -40)]; [auto addChild: gameScene];
În interiorul -(void) touchesBegan: (NSSet *) atinge evenimentul Event: (UIEvent *)
vom crea metoda care va intercepta evenimentul tactil:
pentru (UITouch * atingeți în atingeri) Locația CGPoint = [atinge locațiaInNod: auto]; dacă ([jocScene conținePoint: locație]) // Scene de tranziție Animație SKTransition * reveal = [SKTransition revealWithDirection: SKTransitionDirectionDown duration: 1]; GameScene * gameScene = [[GameScene alocare] initWithSize: CGSizeMake (1024, 768)]; [self.scene.view presentScene: jocScene tranziție: dezvălui]; NSLog (@ "Scor joc de scena !!!!");
Codul menționat anterior face mai multe lucruri:
SKLabelNode
obiect.Principala diferență dintre acțiune și SKAction este că SKAction este un obiect complex cu mai multe proprietăți. Acțiunea în Cocos2D este doar o acțiune pe care programatorul trebuie să o definească, să o apeleze și să o trateze.
Cu kitul Sprite, SKAction oferă mai multe opțiuni dezvoltatorilor, cum ar fi rotația, redimensionarea, scalarea, repetarea, decolorarea, redarea sunetului și multe altele. Schaction poate fi vazut ca un obiect abstract care se ocupa cu orice fel de actiune, de la sunet, la sprite, la noduri.
În acest moment ne vom concentra asupra acțiunilor de mișcare.
În Cocos2D trebuie să definim un programator pentru a apela o metodă personalizată:
[programul propriu: @selector (intervalul addSprite :): 1];
Apoi definiți metoda personalizată pentru a face animația personalizată.
- (void) addSprite: (ccTime) dt CCSprite * aMovableSprite = [CCSprite spriteWithFile: @ "frankenstein.png"]; aMovableSprite.scale = .8; [auto addChild: aMovableSprite]; CGSize winSize = [CCDirector sharedDirector] .winSize; int minX = aMovableSprite.contentSize.width / 2; int maxx = winSize.width - aMovableSprite.contentSize.width / 2; int domeniuX = maxX - minX; int actualY = (arc4random ()% intervalX) + minX; CCCallBlockN * actionMoveDone = [CCCallBlockN actionWithBlock: ^ (CCNode * nod) NSLog (@ "Sprite gratuit!"); ]; NSMutableArray * arrayBezier = [[NSMutableArray alocare] init]; ccBezierConfig bezier; id bezierAction1; float splitDurație = 6 / 6,0; pentru (int i = 0; i< 6; i++) if(i % 2 == 0) bezier.controlPoint_1 = ccp(actualY+100,winSize.height-(100+(i*200))); bezier.controlPoint_2 = ccp(actualY+100,winSize.height-(100+(i*200))); bezier.endPosition = ccp(actualY,winSize.height-(200+(i*200))); bezierAction1 = [CCBezierTo actionWithDuration:splitDuration bezier:bezier]; else bezier.controlPoint_1 = ccp(actualY-100,winSize.height-(100+(i*200))); bezier.controlPoint_2 = ccp(actualY-100,winSize.height-(100+(i*200))); bezier.endPosition = ccp(actualY,winSize.height-(200+(i*200))); bezierAction1 = [CCBezierTo actionWithDuration:splitDuration bezier:bezier]; [arrayBezier addObject:bezierAction1]; [arrayBezier addObject:actionMoveDone]; id seq = [CCSequence actionsWithArray:arrayBezier]; [aMovableSprite runAction:seq];
În kitul Sprite, putem folosi SKAction pentru a controla ce se întâmplă cu un obiect la începutul și la sfârșitul mișcării. Următoarele linii arată cum să mutați un obiect într-o linie dreaptă:
SKSpriteNode * playerSprite = [SKSpriteNode spriteNodeWithImageNamed: @ "player.png"]; [playerSprite setScale: 0.4]; SKAction * mișcare = [deplasare SKActionTo: CGPointMake (900, 500) duration: 5]; SKAction * remove = [SKAction removeFromParent]; [playSprite runAction: [Succesiune: @ [mișcare, eliminare]]; [self addChild: playerSprite];
Cu toate acestea, putem defini o acțiune personalizată și puteți utiliza SKAction pentru a activa acea acțiune. Exemplul următor ilustrează o mișcare Bézier (similară versiunii Cocos2D a acțiunii). Rețineți că trebuie să definim un programator pentru a apela o metodă personalizată.
SKAction * așteptați = [Așteaptă așteptare pentru Durata: 1]; SKAction * callEnemies = [SKAction runBlock: ^ [auto sendNewSKSpriteNode]; ]; SKAction * updateSKSpriteNodeOnScreen = [secvența SKAction: @ [wait, callEnemies]]; [auto runAction: [SKAction repeatActionForever: updateSKSpriteNodeOnScreen]];
Metoda sendNewSKSpriteNode
va gestiona mișcarea obiectelor personalizate.
-(void) sendNewSKSpriteNode CGRect screenRect = [[UIScreen mainScreen] limite]; // Custom SKAption SKSpriteNode * inamic = [SKSpriteNode spriteNodeWithImageNamed: @ "frankenstein.png"]; enemy.scale = 0.6; CGMutablePathRef cgpath = CGPathCreateMutabil (); // valori aleatoare float xStart = [auto getRandomNumber între: 0 + enemy.size.width to: screenRect.size.width-enemy.size.width]; float xEnd = [auto getRandomNumber între: 0 + enemy.size.width to: screenRect.size.width-enemy.size.width]; // ControlPoint1 float cp1X = [auto getRandomNumber între: 0 + enemy.size.width to: screenRect.size.width-enemy.size.width]; float cp1Y = [auto getRandomNumber între: 0 + enemy.size.width to: screenRect.size.width-enemy.size.height]; // ControlPoint2 float cp2X = [auto getRandomNumber între: 0 + enemy.size.width to: screenRect.size.width-enemy.size.width]; float cp2Y = [auto getRandomNumber între: 0 până la: cp1Y]; CGPoint s = CGPointMake (xStart, 1024,0); CGPoint e = CGPointMake (xEnd, -100,0); CGPoint cp1 = CGPointMake (cp1X, cp1Y); CGPoint cp2 = CGPointMake (cp2X, cp2Y); CGPathMoveToPoint (cgpath, NULL, s.x, s.y); CGPathAddCurveToPoint (cgpath, NULL, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y); SKAction * planeDestroy = [SKAction followPath: cgpath asAffset: NU orientToPath: YES duration: 5]; [auto adăugaChild: inamic]; SKAction * remove2 = [SKAction removeFromParent]; [runAction inamic: [secvența SKAction: @ [planeDestroy, remove2]]]; CGPathRelease (cgpath);
Cocos2D nu are nici un fel de editor de particule. Trebuie să folosiți o aplicație externă pentru a crea particula și apoi să folosiți o aplicație specifică CCParticleExplosion
proprietăți pentru a-și schimba comportamentul. După ce ai particulă în proiectul tău Xcode poți să-l suni folosind:
CCParticleExplozion * _particleExplosion; Explosiunea particulelor = [[Alocarea de exploatare a particulelor CC] cu numărul total de particule: 800]; particleExplosion.texture = [[CCTextureCache sharedTextureCache] addImage: @ "texture.png"]; particleExplosion.life = 0.0f; particleExplosion.lifeVar = 0,708f; particleExplosion.startSize = 40; particleExplosion.startSizeVar = 38; particleExplosion.endSize = 14; particleExplosion.endSizeVar = 0; particleExplosion.angle = 360; particleExplosion.angleVar = 360; particleExplosion.speed = 243; particleExplosion.speedVar = 1; CGPoint g = CGPointMake (1,15, 1,58); particleExplosion.gravity = g; ccColor4F startC = 0,89f, 0,56f, 0,36f, 1,0f; particleExplosion.startColor = startC; ccColor4F endC = 1.0f, 0.0f, 0.0f, 1.0f; particleExplosion.endColor = endC; [auto addChild: _particleExplosion]; particleExplosion.position = ccp (_size.width / 5, _size.height / 5); [particuleExplosion resetSystem];
Emițătoarele sunt utilizate în kitul Sprite pentru generarea particulelor. Pentru a le folosi, trebuie să adăugați o particulă în proiect. Mergi la Nou -> Fișier -> Resurse -> Sprite Kit Particle File
. Apoi trebuie să-i numiți și să alegeți orice tip de particule (foc, magie, fum, zăpadă, printre altele). Acum veți vedea că două fișiere noi vor apărea în proiectul dvs. Xcode. Le veți implementa cu:
SKEmitterNode * smokeTrail; NSString * smokePath = [[NSBundle mainBundle] pathForResource: @ "MyParticle" dinType: @ "sks"]; smokeTrail = [NSKeyedUnarchiver unarchiveObjectWithFile: smokePath]; smokeTrail.position = CGPointMake (CGRectGetMidX (autoframe) + 40, CGRectGetMidY (auto.frame) -100); [self addChild: smokeTrail];
Clasa SKEmitterNode este extinsă și conține mai multe proprietăți. Vă sfătuim să o citiți pentru a învăța fiecare proprietate pe care o poate avea un nod de emisie.
Sunetul este o parte activă a oricărei aplicații de jocuri sau multimedia. În Cocos2D, putem realiza acest lucru cu doi pași. Primul este să includă SimpleAudioEngine
fișierul antet.
#import "SimpleAudioEngine.h"
Apoi folosiți următoarele rânduri pentru a apela fișierul muzical din cadrul proiectului nostru:
[[SimpleAudioEngine sharedEngine] playBackgroundMusic: bucla "sound.caf": YES]; [[SimpleAudioEngine sharedEngine] setEffectsVolume: 0,4f];
Uneori, Xcode nu include în mod automat fișierul muzical în "Resursele pentru pachetele de copiere". Dacă se întâmplă acest lucru, ar trebui să-l adăugați manual.
Cu Sprite Kit, includerea sunetelor este simplă:
SKAction * soundAction = [SKAction playSoundFileNamed: @ preview.mp3 "waitForCompletion: NO"; [auto runAction: soundAction];
Rețineți că pentru a realiza acest lucru cu Sprite Kit ați folosit încă o dată obiectul SKAction.
După cum puteți vedea din analiza de mai sus, Cocos2D și Sprite Kit au multe asemănări. Cocos2D utilizează mai multe straturi pentru fiecare obiect, în timp ce Sprite Kit încapsulează mai multe obiecte și utilizează clasa super NSObject pentru a atinge anumite obiective (cum ar fi butoanele sau meniurile).
În ceea ce privește ușurința în utilizare, Sprite Kit strălucește într-adevăr când doriți să utilizați sistemul Particle sau Performerul de acțiune. Cu toate acestea, atunci când lucrăm cu obiecte mai generale, ambele cadre sunt la aproximativ același nivel de dificultate.
Cu toate acestea, construirea unui joc cu Sprite Kit aduce multe beneficii cheie, inclusiv un motor complet integrat de fizică, instrumente simplificate de lucru în Xcode 5, compatibilitate atât cu iOS și OS X, cât și întreținerea oficială de către Apple.
Întrebarea este: ce veți utiliza pentru următorul proiect de joc 2D? Spuneți-ne în comentariile.