Sprite Kit vs. Cocos2D

Sprite Kit is een van de meest opwindende nieuwe technologieën die beschikbaar zijn met de iOS 7 SDK en Xcode 5, maar hoe verhoudt het zich tot een gevestigde game-engine zoals Cocos2D? Deze tutorial zal een korte inleiding tot de Sprite Kit geven voordat je een uitgebreid beeld krijgt van hoe het zich opstapelt tegen Cocos2D.


Introductie van Sprite Kit

Van alle beschikbare spellen in de App Store zijn veel van de meest gedownloade en meest winstgevende 2D-spellen. Enkele iconische titels in deze categorie zijn Angry Birds, Tiny Wings en Cut the Rope. Het succes van deze games is een aantal veelvoorkomende kenmerken: prachtige graphics, deeltjeseffecten, een physics-engine, naadloze animatie en meeslepende geluidseffecten.

Vóór de release van de iOS 7 SDK was het bouwen van dergelijke spellen alleen mogelijk met behulp van frameworks en engines van derden. Nu, met de introductie van Sprite Kit, hoeven ontwikkelaars niet verder te zoeken dan de native SDK om alles te vinden wat ze nodig hebben om fantastische 2D- en 2.5D-games te kunnen bouwen. De functionaliteit die door Sprite Kit wordt geboden, omvat Sprites, Shapes, Particles (bijvoorbeeld vuur, rook, enz.), Animaties, Physics Simulation, Audio, Video en Visual Effects. Xcode 5 biedt nu ook ondersteuning voor textuurpakketten en deeltjesontwerp.

Sprite Kit kan logisch worden geabstraheerd in de volgende drie delen:

  • scenes - Net als in Cocos2D zijn scènes de visuele laag van het spel. Hier beheert u de achtergrond, de objecten (zoals bomen, auto's, vliegtuigen, avatars, enz.).
  • acties - Gladde animaties zijn een vitaal onderdeel van elk spel. Apple heeft het actiesysteem op een intuïtieve manier ontworpen en je kunt er bijna alles mee doen. Enkele van de meest voorkomende acties die worden gepresenteerd zijn: verplaatsen, vervagen, schalen, vergroten / verkleinen, roteren, animeren met texturen en groepsacties. Verder, als een bepaalde actie niet is gedefinieerd, kunt u altijd een aangepast codeblok maken om uw eigen actie te vormen en dat object te manipuleren.
  • Fysica - Als je een game wilt hebben die zich realistisch gedraagt, moet je een physics-engine toevoegen. Je wilt geen kogel die een bepaald traject niet volgt, een bal die niet springt als hij de grond raakt, en andere dergelijke amateuristische effecten. Gelukkig wordt Sprite Kit geleverd met een ingebouwde physics-engine.

Waarom Sprite Kit?

Er zijn enkele zeer solide voordelen aan het hebben en onderhouden van een 2D- en 2.5D-spelplatform door Apple. Beschouw de volgende punten:

Native Performance

Native ontwikkeling en native tools hebben alles te maken met de prestaties.

Ondanks het feit dat ontwikkelaars meestal willen dat hun spellen op zoveel mogelijk verschillende platforms draaien, heeft een native game bijna altijd betere prestaties dan een niet-native game. Plus, als de tools om die spellen te ontwikkelen native zijn, kan men ervoor zorgen dat de code is geïntegreerd met het platformecosysteem.

Platformintegratie

Zoals hierboven vermeld, combineren Sprite Kit en Xcode 5 veel van de essentiële componenten om geweldige games te bouwen. Dit betekent dat de ontwikkeling meer gestroomlijnd kan worden en de hulpmiddelen betrouwbaarder en effectiever zullen zijn.

Future Proof Development

Een game schrijven met een framework of game-engine van een derde partij is altijd een tweesnijdend zwaard. We weten nooit of de tools compatibel zijn met toekomstige platformupdates, of zelfs als de game goed zal werken na een update. Wanneer dingen kapot gaan, is het onzeker hoe lang het duurt voordat de community de bugs repareert.

Cocos2D is een voorbeeld van een open-sourceproject dat dit probleem moet oplossen. De code is voortdurend aan het evolueren en bij elke nieuwe release moeten verschillende veiligheidsstappen worden uitgevoerd om te garanderen dat applicaties die met Cocos2D zijn gebouwd nog steeds op de nieuwste versie van iOS en de nieuwste hardware worden uitgevoerd.

Met Sprite Kit heeft Apple een set hulpprogramma's geleverd om ervoor te zorgen dat de gamecode probleemloos op elk compatibel apparaat werkt. Merk op dat Sprite Kit niet alleen een iOS-framework is. Ontwikkelaars kunnen ook beginnen met het bouwen van Sprite Kit-spellen voor OS X, en het is een goede gok dat Sprite Kit-spellen ook op elk toekomstig iOS-apparaat zullen draaien.

Ontwikkelaarsvriendelijk

Gebruiksgemak was een belangrijke factor achter het succes van game-engines zoals Cocos2D. Over het algemeen vonden ontwikkelaars dat Cocos2D veel eenvoudiger te implementeren was dan andere native alternatieven zoals OpenGL ES. Met Cocos2D werden alle low-level API-aanroepen getransformeerd in eenvoudige methoden.

Sprite Kit volgt deze aanpak en biedt honderden methoden die het ontwikkelingsproces van de game een stuk eenvoudiger maken. Sprite Kit is ook vriendelijk. Het heeft de aangepaste, goed ontworpen Apple API en wordt geleverd met een volledige gestructureerde documentatie. Apple heeft uitstekend werk verricht door deze tool voor externe ontwikkelaars aan te scherpen om te gebruiken. Het grootste voordeel van alles is dat het vol zit met alle bronnen die je nodig hebt om een ​​spel te maken. Natuurkunde, geluidseffecten, partikeleffecten, texturen, scènebeheer - alles is opgenomen in een enkele bundel.

Merk op dat, bij de eerste presentatie van Sprite Kit, Ricardo Quesada, de hoofdontwikkelaar van Cocos2D zei het volgende op Twitter:

Sprite Kit is erg goed. Met minder functies dan Cocos2D, maar beter. Ik hou van de fysica-integratie.

Dit is een grote lof voor een van de leidende geesten achter Cocos2D!


Sprite Kit & Cocos2D-functies

Voorzien zijn van Sprite Kit Cocos2D
Open source Nee Ja
Objectieve ondersteuning Ja Ja
Grafische engine Ja Ja
animaties Ja Ja
Physics Simulation Ja (geïntegreerd) Nee (vereist Box2D of Chipmunk)
Effecten van deeltjes Ja Ja
Xcode native integratie Ja Nee
Automatische Atlas-creatie Ja Nee
Ingebouwde deeltjeseditor Ja Nee
shaders Nee Ja
Camera Nee Ja

Projectvergelijking

Dus, hoe zien projecten met elke game-engine er eigenlijk uit? Om deze vraag te beantwoorden, hebben de auteurs de volledige broncode opgenomen voor zowel een Sprite Kit als een Cocos2D-project. Je kunt deze projecten gebruiken als een vergelijking op hoog niveau van elke game-engine.


Broncode vergelijking

In deze sectie zullen we veelvoorkomende taken en concepten uitsplitsen en laten zien hoe ze kunnen worden geïmplementeerd in zowel Cocos2D als Sprite Kit.

CClayer vs. SKScene

CCLayer of SkScene is het belangrijkste object dat wordt gebruikt om andere objecten te tekenen. Je kunt dit zien als de standaardweergave die alle objecten, animaties en aanraakgebeurtenissen zal ontvangen.

De overgang tussen scènes in Cocos2D gebeurt met de volgende stappen:

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

Merk op dat de GameScene.h bestand moet van de zijn CCLayer categorie en hebben de specifieke initializer beschikbaar.

 @interface GameScene: CCLayer  + (CCScene *) scène;

In GameScene.m, de eerste implementatie is:

 +(CCScene *) scène CCscene * scene = [CCScene node]; GameScene * -laag = [GameScene-knooppunt]; [scène addChild: laag]; terugkeer scène;  - (id) init if ((self = [super init])) // Uw code hier retourneert zichzelf; 

In Sprite Kit is de overgang vergelijkbaar:

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

De GameScene moet van de zijn SKScene categorie en de -(Id) initWithSize: (CGSize) formaat is de aangepaste initializer. Een eenvoudig voorbeeld:

 -(id) initWithSize: (CGSize) size if (self = [super initWithSize: size]) // Your code return self; 

CCSprite versus SKSpriteNode

Sprite-objecten worden normaal gesproken gebruikt om een ​​soort afbeelding weer te geven. Het kan verschillende eigenschappen hebben, zoals: rotatie, schaal, positie, frames, id's en meer. De implementatie van zowel Cocos2D als Sprite Kit is vergelijkbaar. De implementatie van Cocos2D is:

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

In Sprite Kit is de implementatie:

 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

Labelobjecten worden gebruikt om tekst weer te geven. Het kan verschillende eigenschappen hebben, waaronder tekst, tekstgrootte, tekstkleur, positie en vele andere. De implementatie van zowel Cocos2D als Sprite Kit is vergelijkbaar. De implementatie van Cocos2D is:

 CCLabelTTF * label = [CCLabelTTF labelWithString: @ "Hello World" fontName: @ "Marker Felt" fontSize: 64]; // vraag de regisseur naar de venstergrootte CGSize size = [[CCDirector sharedDirector] winSize]; label.position = ccp (size.width / 2, size.height / 2); [self addChild: label];

De Sprite Kit-implementatie is:

 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];

Menu CCMenu en CCMenuItem vs. Sprite Kit

In Cocos2D worden de menu's gemaakt met behulp van twee objecten: CCMenu en CCMenuItem. Het volgende voorbeeld presenteert een menu met 2 opties in Cocos2D:

 CGSize size = [[CCDirector sharedDirector] winSize]; [CCMenuItemFont setFontSize: 28]; CCMenuItem * itemNewGame = [CCMenuItemFont itemWithString: @ "New Game" -blok: ^ (id-afzender) // Uw code]; CCMenuItem * itemOptions = [CCMenuItemFont itemWithString: @ "Opties" block: ^ (id afzender) NSLog (@ "Tweede item"); ]; CCMenu * menu = [CCMenu menuWithItems: itemNewGame, itemOptions, nil]; [menu alignItemsHorizontallyWithPadding: 20]; [menuset Positie: ccp (size.width / 2, size.height / 2 - 50)]; [self addChild: menu];

SpiteKit bevat geen type menu-specifiek object. U moet een gebeurtenishandler voor een specifiek object maken om het voor gebruikersinvoer te activeren. Dus, om een ​​menu te "creëren", moet u een UIKit-object of een Sprite Kit-object gebruiken.

Het volgende voorbeeld gebruikt a SKLabelNode als een menu-item. Eerst definiëren we de 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];

Binnen in de -(ongeldig) raaktBegan: (NSSet *) raakt aan metEvent: (UIEvent *) -gebeurtenis methode zullen we de gebeurtenishandler maken die de aanraakgebeurtenis zal onderscheppen:

 for (UITouch * touch in touch) CGPoint location = [touch locationInNode: self]; if ([gameScene containsPoint: location]) // Scene Transition Animation SKTransition * reveal = [SKTransition revealWithDirection: SKTransitionDirectionDown duration: 1]; GameScene * gameScene = [[GameScene alloc] initWithSize: CGSizeMake (1024, 768)]; [self.scene.view presentScene: gameScene transition: reveal]; NSLog (@ "Touched gameScene !!!!"); 

De bovengenoemde code doet verschillende dingen:

  1. Activeert de aanraakgebeurtenissen.
  2. Converteert de tiklocatie naar de interne locatie.
  3. Test of de taplocatie zich in de gameScene bevindt SKLabelNode voorwerp.
  4. Creëert een overgangsanimatie.
  5. Verandert de scène.

Actie vs. SKAction

Het belangrijkste verschil tussen Action en SKAction is dat SKAction een complex object is met verschillende eigenschappen. Actie in Cocos2D is slechts een actie die de programmeur moet definiëren, callen en behandelen.

Met Sprite Kit biedt SKAction verschillende opties voor de ontwikkelaars, zoals rotatie, formaat wijzigen, schaal, herhalen, vervagen, geluid afspelen en meer. SKaction kan worden gezien als een abstract object dat zich bezighoudt met elke vorm van actie, van geluid, tot sprites, tot knooppunten.

We zullen ons vooralsnog concentreren op bewegingsacties.

In Cocos2D moeten we een planner definiëren om een ​​aangepaste methode aan te roepen:

 [zelf planning: @selector (addSprite :) interval: 1];

En definieer vervolgens de aangepaste methode om de aangepaste animatie te maken.

 - (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 bereikX = 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; voor (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]; 

In Sprite Kit kunnen we SKAction gebruiken om te bepalen wat er met een object gebeurt aan het begin en aan het einde van de beweging. De volgende regels laten zien hoe elk object in een rechte lijn moet worden verplaatst:

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

We kunnen echter een aangepaste actie definiëren en SKAction gebruiken om die actie te activeren. Het volgende voorbeeld is een voorbeeld van een Bézier-beweging (vergelijkbaar met de Cocos2D-versie van Action). Merk op dat we een planner moeten definiëren om een ​​aangepaste methode aan te roepen.

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

De methode sendNewSKSpriteNode zal de beweging van het aangepaste object afhandelen.

 -(void) sendNewSKSpriteNode CGRect screenRect = [[UIScreen mainScreen] bounds]; // Custom SKAction SKSpriteNode * enemy = [SKSpriteNode spriteNodeWithImageNamed: @ "frankenstein.png"]; vijand.scale = 0.6; CGMutablePathRef cgpath = CGPathCreateMutable (); // willekeurige waarden zwevend xStart = [self getRandomNumberBtween: 0 + enemy.size.width to: screenRect.size.width-enemy.size.width]; float xEnd = [self getRandomNumberBtween: 0 + enemy.size.width to: screenRect.size.width-enemy.size.width]; // ControlPoint1 float cp1X = [self getRandomNumberBtween: 0 + enemy.size.width to: screenRect.size.width-enemy.size.width]; float cp1Y = [self getRandomNumberBtween: 0 + enemy.size.width to: screenRect.size.width-enemy.size.height]; // ControlPoint2 float cp2X = [self getRandomNumberBtween: 0 + enemy.size.width to: screenRect.size.width-enemy.size.width]; float cp2Y = [self getRandomNumberBleween: 0 to: 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: YES duration: 5]; [self addChild: vijand]; SKAction * remove2 = [SKAction removeFromParent]; [vijandelijke runActie: [SKAction-reeks: @ [planeDestroy, remove2]]]; CGPathRelease (cgpath); 

CCParticleExplosion vs. Emitter

Cocos2D heeft geen deeltjeseditor. Men moet een externe app gebruiken om het deeltje te maken en vervolgens specifiek te gebruiken CCParticleExplosion eigenschappen om het gedrag te veranderen. Nadat je het deeltje in je Xcode-project hebt, kun je het noemen met behulp van:

 CCParticleExplosion * _particleExplosion; particleExplosion = [[CCParticleExplosion alloc] initWithTotalParticles: 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; [self addChild: _particleExplosion]; particleExplosion.position = ccp (_size.width / 5, _size.height / 5); [particleExplosion resetSystem];

Emitters worden gebruikt in Sprite Kit voor het genereren van deeltjes. Om ze te gebruiken, moet je een deeltje toevoegen aan je project. Ga naar Nieuw -> Bestand -> Bron -> Sprite Kit Particle File. Vervolgens moet je het een naam geven en elk type deeltje kiezen (vuur, magie, rook, sneeuw, onder anderen). Nu zult u zien dat er twee nieuwe bestanden in uw Xcode-project verschijnen. U implementeert ze met:

 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];

De klasse SKEmitterNode is uitgebreid en bevat verschillende eigenschappen. We adviseren u om het te lezen om elke eigenschap te leren die een emitterknooppunt kan hebben.

SimpleAudioEngine vs. Sprite Kit Sound

Geluid is een actief onderdeel van elke game- of multimediatoepassing. In Cocos2D kunnen we dat met twee stappen bereiken. De eerste is om de SimpleAudioEngine header-bestand.

 #import "SimpleAudioEngine.h"

Vervolgens gebruik je de volgende regels om het muziekbestand binnen ons project te bellen:

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

Soms neemt Xcode het muziekbestand niet automatisch op in de "Bronnen kopiëren". Als dat gebeurt, moet je dit handmatig toevoegen.

Met Sprite Kit is de insluitsels van geluiden duidelijk:

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

Merk op dat om dit met Sprite Kit te bereiken je opnieuw het SKAction-object hebt gebruikt.


Conclusie

Zoals je kunt zien in de bovenstaande analyse, hebben Cocos2D en Sprite Kit veel overeenkomsten. Cocos2D gebruikt verschillende lagen voor elk object, terwijl Sprite Kit meer objecten inkapselt en de NSObject-superklasse gebruikt om bepaalde doelen te bereiken (zoals knoppen of menu's).

Qua gebruikersvriendelijkheid schittert Sprite Kit echt als je het Particle-systeem of de Action-performer wilt gebruiken. Bij het werken met meer algemene objecten hebben beide frameworks echter ongeveer dezelfde moeilijkheidsgraad.

Toch biedt het bouwen van een game met Sprite Kit vele belangrijke voordelen, waaronder een volledig geïntegreerde physics engine, gestroomlijnde workflowtools in Xcode 5, compatibiliteit met zowel iOS als OS X en officieel onderhoud door Apple.

De vraag is: welke gebruik je voor je volgende 2D-gameproject? Laat het ons weten in de comments.