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.
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:
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 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.
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.
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å.
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!
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 |
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.
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 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;
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];
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];
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:
SKLabelNode
gjenstand.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);
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.
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.
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.