Sprite Kit vs Cocos2D

Sprite Kit er en av de mest spennende nye teknologiene som er tilgjengelige med iOS 7 SDK og Xcode 5, men hvordan sammenligner den med en etablert spillmotor som Cocos2D? Denne opplæringen vil gi en kort introduksjon til Sprite Kit før du tar et omfattende blikk på hvordan det stabler opp mot Cocos2D.


Introduserer Sprite Kit

Av alle tilgjengelige spill i App Store, er mange av de mest nedlastede og mest lønnsomme 2D-spillene. Noen ikoniske titler i denne kategorien inkluderer Angry Birds, Tiny Wings og Cut the Rope. Kjør suksessen til disse spillene er flere vanlige egenskaper: vakker grafikk, partikkeleffekter, en fysikkmotor, sømløs animasjon og overbevisende lydeffekter.

Før utgivelsen av iOS 7 SDK ble byggespill som disse bare mulig ved bruk av rammebetingelser og motorer fra tredjeparter. Nå, med introduksjonen av Sprite Kit, trenger utviklere ikke se lenger enn den innfødte SDK for å finne alt de trenger for å kunne bygge flotte 2D og 2.5D-spill. Funksjonaliteten som tilbys av Sprite Kit inkluderer Sprites, Shapes, Particles (for eksempel brann, røyk, etc.), animasjoner, fysikk Simulering, lyd, video og visuelle effekter. Xcode 5 gir nå også støtte til teksturpakker og partikkeldesign.

Sprite Kit kan logisk trekkes inn i følgende tre deler:

  • scener - Som i Cocos2D er scener det visuelle laget av spillet. Det er der du styrer bakgrunnen, objekter (som trær, biler, fly, avatarer osv.).
  • handlinger - Glatte animasjoner er en viktig del i et hvilket som helst spill. Apple utformet handlingssystemet på en intuitiv måte, og det gjør at du kan gjøre nesten alt. Noen av de vanligste handlingene som presenteres er: flytte, fade, skala, endre størrelse, rotere, animere med teksturer og grupphandlinger. Videre, hvis en bestemt handling ikke er definert, kan du alltid opprette en egendefinert blokk kode for å danne din egen handling og manipulere det objektet.
  • fysikk - Hvis du vil ha et spill som oppfører seg realistisk, må du legge til en fysikkmotor. Du vil ikke ha en kule som ikke følger en bestemt bane, en ball som ikke hopper når den treffer bakken, og andre slike amatoreffekter. Heldigvis kommer Sprite Kit med en fysikkmotor baket inn.

Hvorfor Sprite Kit?

Det er noen svært solide fordeler med å ha en 2D og 2.5D spillplattform levert og vedlikeholdt av Apple. Vurder følgende punkter:

Native Performance

Native utvikling og innfødte verktøy handler om ytelse.

Til tross for at utviklere vanligvis vil at spillene skal kjøre på så mange forskjellige plattformer som mulig, vil et innfødt spill nesten alltid ha bedre ytelse enn et ikke-morsomt spill. I tillegg, hvis verktøyene for å utvikle disse spillene er innfødte, kan man sikre at koden er integrert med plattformens økosystem.

Platform Integrering

Som nevnt ovenfor kombinerer Sprite Kit og Xcode 5 mange av de essensielle komponentene til å bygge gode spill. Dette betyr at utviklingen kan være mer strømlinjeformet og verktøyene vil være mer pålitelige og effektive.

Fremtidig bevisutvikling

Skrive et spill ved hjelp av en tredjeparts rammeverk eller spillmotor er alltid et tokantet sverd. Vi vet aldri om verktøyene vil være kompatible med fremtidige plattformoppdateringer, eller om spillet vil gå bra etter en oppdatering. Når ting bryter, er det usikkert hvor lenge det vil ta samfunnet å fikse feilene.

Cocos2D er et eksempel på et åpen kildekode-prosjekt som må håndtere dette problemet. Koden utvikler seg kontinuerlig, og i hver ny utgivelse må det utføres flere sikkerhetsstrinn for å garantere at applikasjoner som er bygget med Cocos2D, fortsatt vil kjøre på den nyeste versjonen av IOS og nyeste maskinvare.

Med Sprite Kit har Apple gitt et sett med verktøy for å sikre at spillkoden fungerer på alle kompatible enheter uten problemer. Legg merke til at Sprite Kit ikke bare er et iOS-rammeverk. Utviklere kan også begynne å bygge Sprite Kit-spill for OS X, og det er en sikker innsats at Sprite Kit-spill vil kjøre på fremtidige iOS-enheter også.

Utvikler Friendly

Brukervennlighet var en viktig faktor bak suksessen til spillmotorer som Cocos2D. Generelt sett fant utviklere Cocos2D mye enklere å implementere enn andre innfødte alternativer som OpenGL ES. Med Cocos2D ble alle API-samtalene på lavt nivå omformet i enkle metoder.

Sprite Kit følger denne tilnærmingen, og tilbyr hundrevis av metoder som gjør spillet utviklingsprosessen mye lettere. Sprite Kit er også vennlig. Den har den egendefinerte, godt utformede Apple API og leveres med en komplett strukturert dokumentasjon. Apple har gjort en fremragende jobb med å skarpe dette verktøyet for tredjeparts devleopers å bruke. Den største fordelen av alt er at den kommer fullt lastet med hver ressurs som du trenger for å lage et spill. Fysikk, lydeffekter, partikkeleffekter, teksturer, scenehåndtering-alt er inkludert i en enkelt pakke.

Merk at ved den første presentasjonen av Sprite Kit, Ricardo Quesada, ledende utvikler av Cocos2D sa følgende på Twitter:

Sprite Kit er veldig bra. Med mindre funksjoner enn Cocos2D, men bedre. Jeg liker fysikkintegrasjonen.

Dette er høy ros som kommer fra en av de ledende tankene bak Cocos2D!


Sprite Kit & Cocos2D Funksjoner

Trekk Sprite Kit Cocos2D
Åpen kilde Nei Ja
Objective-C Native Support Ja Ja
Grafikkmotor Ja Ja
animasjoner Ja Ja
Fysikk Simulering Ja (integrert) Nei (Krever Box2D eller Chipmunk)
Partikkeleffekter Ja Ja
Xcode Native Integration Ja Nei
Automatisk atlasoppretting Ja Nei
Innebygd partikkelredaktør Ja Nei
shaders Nei Ja
Kamera Nei Ja

Prosjektjämförelse

Så, hvordan ser prosjekter med hver spillmotor faktisk ut? For å svare på dette spørsmålet, har forfatterne inkludert den komplette kildekoden for både et Sprite Kit og et Cocos2D-prosjekt. Du kan bruke disse prosjektene som et høyt nivå sammenligning av hver spillmotor.


Kildekode sammenligning

I denne delen vil vi faktisk slå sammen vanlige oppgaver og konsepter, og vise hvordan de implementeres i både Cocos2D og Sprite Kit.

CClayer vs SKScene

CCLayer eller SkScene er hovedobjektet som brukes til å tegne andre objekter. Du kan tenke på dette som standardvisning som vil motta alle objekter, animasjoner og berøre hendelser.

Overgangen mellom scener i Cocos2D er gjort med følgende trinn:

 GameScene * gameScene = [[GameScene alloker] init]; [[CCDirector sharedDirector] replaceScene: gameScene];

Legg merke til at GameScene.h filen må være av CCLayer kategori og har den spesifikke initialisatoren tilgjengelig.

 @interface GameScene: CCLayer  + (CCScene *) scene;

I GameScene.m, den første implementeringen er:

 +(CCScene *) scene CCScene * scene = [CCScene node]; GameScene * layer = [GameScene node]; [scene addChild: lag]; retur scene;  - (id) init hvis ((selv = [super init])) // Din kode her returner selv; 

I Sprite Kit er overgangen lik:

 GameScene * gameScene = [[GameScene alloker] initWithSize: CGSizeMake (1024, 768)]; [self.scene.view presentScene: gameScene]; 

De GameScene må være av SKScene kategori, og -(Id) initWithSize: (CGSize) størrelse er den egendefinerte initialiseringen. Et enkelt eksempel:

 -(id) initWithSize: (CGSize) størrelse hvis (selv = [super initWithSize: size]) // Din kode returner selv; 

CCSprite vs SKSpriteNode

Sprite-objekter brukes vanligvis til å vise noe slags bilde. Det kan ha flere egenskaper, for eksempel: rotasjon, skala, posisjon, rammer, ids og mer. Implementeringen av både Cocos2D og Sprite Kit er lik. Cocos2D-implementeringen er:

 CCSprite * aSprite; aSprite = [CCSprite spriteWithFile: @ "player.png"]; aSprite.scale = .5; aSprite.position = ccp (_size.width / 1,30, _size.height / 1,25); [self addChild: aSprite];

Mens i Sprite Kit er implementeringen:

 SKSpriteNode * planeShadow = [SKSpriteNode spriteNodeWithImageNamed: @ "player.png"]; planeShadow.scale = 0.5; planeShadow.position = CGPointMake (CGRectGetMidX (self.frame) + 100, CGRectGetMidY (self.frame) +200); [self addChild: planeShadow];

CCLabelTTF vs SKLabelNode

Etikettobjekter brukes til å vise tekst. Det kan ha flere egenskaper, inkludert tekst, tekststørrelse, tekstfarge, posisjon og mange andre. Implementeringen av både Cocos2D og Sprite Kit er lik. Cocos2D-implementeringen er:

 CCLabelTTF * label = [CCLabelTTF labelWithString: @ "Hello World" fontName: @ "Marker Felt" fontSize: 64]; // spør regissør for vinduet størrelse CGSize size = [[CCDirector sharedDirector] winSize]; label.position = ccp (size.width / 2, size.height / 2); [self addChild: label];

Sprite Kit implementeringen er:

 SKLabelNode * gameScene = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; [gameScene setText: @ "New Game"]; [gameScene setFontSize: 18]; gameScene setPosition: CGPointMake (CGRectGetMidX (self.frame) + 5, CGRectGetMidY (self.frame) -40)]; [self addChild: gameScene];

CCMenu og CCMenuTem vs Sprite Kit-menyen

I Cocos2D er menyene opprettet ved hjelp av to objekter: CCMenu og CCMenuItem. Følgende eksempel presenterer en meny med 2 alternativer i Cocos2D:

 CGSize size = [[CCDirector sharedDirector] winSize]; [CCMenuItemFont setFontSize: 28]; CCMenuItem * itemNewGame = [CCMenuItemFont itemWithString: @ "New Game" blokk: ^ (ID sender) // Din kode]; CCMenuItem * itemOptions = [CCMenuItemFont itemWithString: @ "Options" blokk: ^ (ID sender) NSLog (@ "Second item"); ]; CCMenu * meny = [CCMenu menuWithItems: itemNewGame, itemOptions, null]; [menyen alignItemsHorizontalallyWithPadding: 20]; [menysettPosisjon: ccp (size.width / 2, size.height / 2 - 50)]; [self addChild: meny];

SpiteKit inkluderer ikke noen type menyspesifikk objekt. Du må opprette en hendelsehandler til et bestemt objekt for å aktivere det for brukerinngang. Så, for å "lage" en meny må du bruke et UIKit-objekt eller et Sprite Kit-objekt.

Følgende eksempel bruker a SKLabelNode som et menyelement. Først definerer vi SKLabelNode:

 SKLabelNode * gameScene = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; [gameScene setText: @ "New Game"]; [gameScene setFontSize: 18]; [gameScene setPosition: CGPointMake (CGRectGetMidX (self.frame) + 5, CGRectGetMidY (self.frame) -40)]; [self addChild: gameScene];

Inne i -(void) berørerBegan: (NSSet *) berører medEvent: (UIEvent *) hendelse Metode vi vil opprette hendelseshåndterer som vil fange opp berøringshendelsen:

 for (UITouch * berøre) CGPoint location = [touch locationInNode: self]; hvis ([gameScene containsPoint: sted]) // Scene Transition Animation SKTransition * reveal = [SKTransition revealWithDirection: SKTransitionDirectionDown duration: 1]; GameScene * gameScene = [[GameScene alloker] initWithSize: CGSizeMake (1024, 768)]; [self.scene.view presentScene: gameScene overgang: avsløre]; NSLog (@ "Touched gameScene !!!!"); 

Den nevnte koden gjør flere ting:

  1. Aktiverer berøringshendelsene.
  2. Konverterer trykkposisjonen til den interne plasseringen.
  3. Tester om tappeplasseringen er inne i spilletScene SKLabelNode gjenstand.
  4. Oppretter en overgangsanimasjon.
  5. Endrer scenen.

Handling vs. SKAction

Hovedforskjellen mellom Action og SKAction er at SKAction er et komplekst objekt med flere egenskaper. Handling i Cocos2D er bare en handling som programmereren må definere, ringe og behandle.

Med Sprite Kit tilbyr SKAction flere alternativer til utviklerne, for eksempel rotasjon, endre størrelse, skala, gjenta, visne, spille lyd og mer. SKaction kan sees som et abstrakt objekt som omhandler enhver form for handling, fra lyd, til sprites, til noder.

Vi vil fokusere for øyeblikket på bevegelseshandlinger.

I Cocos2D må vi definere en planlegger for å ringe en tilpasset metode:

 [selvplanlegging: @selektor (addSprite :) intervall: 1];

Og definer deretter den egendefinerte metoden for å gjøre den egendefinerte animasjonen.

 - (void) addSprite: (ccTime) dt CCSprite * aMovableSprite = [CCSprite spriteWithFile: @ "frankenstein.png"]; aMovableSprite.scale = .8; [self addChild: aMovableSprite]; CGSize winSize = [CCDirector sharedDirector] .winSize; int minX = aMovableSprite.contentSize.width / 2; int maxX = winSize.width - aMovableSprite.contentSize.width / 2; int rangeX = maxX - minX; int actualY = (arc4random ()% rangeX) + minX; CCCallBlockN * actionMoveDone = [CCCallBlockN actionWithBlock: ^ (CCNode * node) NSLog (@ "Sprite free!"); ]; NSMutableArray * arrayBezier = [[NSMutableArray alloc] init]; ccBezierConfig bezier; id bezierAction1; float splitDuration = 6 / 6,0; for (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]; 

I Sprite Kit kan vi bruke SKAction til å kontrollere hva som skjer med en gjenstand i begynnelsen og på slutten av bevegelsen. De neste linjene viser hvordan du flytter et objekt i en rett linje:

 SKSpriteNode * playerSprite = [SKSpriteNode spriteNodeWithImageNamed: @ "player.png"]; [playerSprite setScale: 0.4]; SKAction * bevegelse = [SKAction moveTo: CGPointMake (900, 500) varighet: 5]; SKAction * remove = [SKAction removeFromParent]; [playerSprite runAction: [SKAction sekvens: @ [bevegelse, fjern]]]; [self addChild: playerSprite];

Vi kan imidlertid definere en tilpasset handling og bruke SKAction for å aktivere den aktuelle handlingen. Følgende eksempel eksemplifiserer en Bezier-bevegelse (ligner Cocos2D-versjonen av Handlingen). Legg merke til at vi må definere en planlegger for å ringe en tilpasset metode.

 SKAction * wait = [SKAction waitForDuration: 1]; SKAction * callEnemies = [SKAction runBlock: ^ self sendNewSKSpriteNode]; ]; SKAction * updateSKSpriteNodeOnScreen = [SKAction sekvens: @ [vent, callEnemies]]; [self runAction: [SKAction repeatActionForever: updateSKSpriteNodeOnScreen]];

Metoden sendNewSKSpriteNode vil håndtere den egendefinerte objektbevegelsen.

 -(ugyldig) sendNewSKSpriteNode CGRect screenRect = [[UIScreen mainScreen] bounds]; // Custom SKAction SKSpriteNode * fiende = [SKSpriteNode spriteNodeWithImageNamed: @ "frankenstein.png"]; enemy.scale = 0,6; CGMutablePathRef cgpath = CGPathCreateMutable (); // tilfeldige verdier float xStart = [self getRandomNumberBetween: 0 + enemy.size.width til: screenRect.size.width-enemy.size.width]; float xEnd = [self getRandomNumberBetween: 0 + enemy.size.width til: screenRect.size.width-enemy.size.width]; // ControlPoint1 float cp1X = [self getRandomNumberBetween: 0 + enemy.size.width til: screenRect.size.width-enemy.size.width]; float cp1Y = [self getRandomNumberBetween: 0 + enemy.size.width til: screenRect.size.width-enemy.size.height]; // ControlPoint2 float cp2X = [self getRandomNumberBetween: 0 + enemy.size.width til: screenRect.size.width-enemy.size.width]; float cp2Y = [self getRandomNumberBetween: 0 til: 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 asOffset: NO orientToPath: JA lengde: 5]; [self addChild: fiende]; SKAction * remove2 = [SKAction removeFromParent]; [fiendtlig runAction: [SKAction sekvens: @ [planetDestroy, remove2]]]; CGPathRelease (cgpath); 

CCParticleExplosion vs Emitter

Cocos2D har ingen form for partikkelredaktør. Man må bruke en ekstern app for å lage partikkelen og deretter bruke spesifikk CCParticleExplosion egenskaper for å endre sin oppførsel. Etter at du har partikkelen i Xcode-prosjektet, kan du ringe det ved å bruke:

 CCParticleExplosion * _particleExplosion; particleExplosion = [[CCParticleExplosion alloc] initWithTotalParticles: 800]; particleExplosion.texture = [[CCTextureCache sharedTextureCache] addImage: @ "texture.png"]; particleExplosion.life = 0.0f; partikkelExplosion.lifeVar = 0,708f; partikkelExplosion.startSize = 40; particleExplosion.startSizeVar = 38; partikkelExplosion.endSize = 14; particleExplosion.endSizeVar = 0; partikkelExplosion.angle = 360; particleExplosion.angleVar = 360; partikkelExplosion.speed = 243; partikkelExplosion.speedVar = 1; CGPoint g = CGPointMake (1,15, 1,58); partikkelExplosion.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; [self addChild: _particleExplosion]; particleExplosion.position = ccp (_size.width / 5, _size.height / 5); [particleExplosion resetSystem];

Emittere brukes i Sprite Kit for partikkelgenerering. For å kunne bruke dem må du legge til en partikkel i prosjektet. Gå til Ny -> Fil -> Ressurs -> Sprite Kit Particle File. Deretter skal du nevne det og velge hvilken type partikkel (brann, magi, røyk, snø, blant andre). Nå ser du at to nye filer vil vises på Xcode-prosjektet ditt. Du skal implementere dem med:

 SKEmitterNode * smokeTrail; NSString * smokePath = [[NSBundle mainBundle] pathForResource: @ "MyParticle" ofType: @ "sks"]; smokeTrail = [NSKeyedUnarchiver unarchiveObjectWithFile: smokePath]; smokeTrail.position = CGPointMake (CGRectGetMidX (self.frame) + 40, CGRectGetMidY (self.frame) -100); [self addChild: smokeTrail];

Klassen SKEmitterNode er omfattende og inneholder flere egenskaper. Vi anbefaler deg å lese det for å lære alle eiendommer som en emitterknut kan ha.

SimpleAudioEngine vs Sprite Kit Sound

Lyd er en aktiv del av et spill eller multimedieprogram. I Cocos2D kan vi oppnå det med to trinn. Den første er å inkludere SimpleAudioEngine header fil.

 #import "SimpleAudioEngine.h"

Deretter bruker du følgende linjer for å ringe musikkfilen i prosjektet vårt:

 [[SimpleAudioEngine sharedEngine] playBackgroundMusic: @ "sound.caf" loop: YES]; [[SimpleAudioEngine sharedEngine] setEffectsVolume: 0.4f];

Noen ganger inkluderer Xcode ikke automatisk musikkfilen i "Copy Bundle Resources". Hvis det skjer, bør du legge til det manuelt.

Med Sprite Kit er inkluderingen av lyder rettferdig:

 SKAction * soundAction = [SKAction playSoundFileNamed: @ "preview.mp3" waitForCompletion: NO]; [selvdrift: soundAction];

Merk at for å oppnå dette med Sprite Kit brukte du en gang til SKAction-objektet.


Konklusjon

Som du kan se fra analysen ovenfor, har Cocos2D og Sprite Kit mange likheter. Cocos2D bruker flere lag for hvert objekt, mens Sprite Kit inkapsler flere objekter og bruker NSObject superklassen for å oppnå bestemte mål (som knapper eller menyer).

Med hensyn til brukervennlighet skinner Sprite Kit virkelig når du vil bruke partikkelsystemet eller actionutøveren. Men når man arbeider med flere generelle objekter, er begge rammene på omtrent det samme vanskelighetsnivået.

Likevel, å bygge et spill med Sprite Kit gir mange viktige fordeler, inkludert en fullt integrert fysikkmotor, strømlinjeformede arbeidsflytverktøy i Xcode 5, kompatibilitet med både iOS og OS X, og offisielt vedlikehold av Apple.

Spørsmålet er: hvilke vil du bruke til ditt neste 2D-spillprosjekt? Gi oss beskjed i kommentarene.