Das Sprite-Kit ist eine der aufregendsten neuen Technologien, die mit dem iOS 7 SDK und Xcode 5 verfügbar sind. Wie kann es jedoch mit einer etablierten Spiel-Engine wie Cocos2D verglichen werden? In diesem Tutorial erhalten Sie eine kurze Einführung in das Sprite Kit, bevor Sie einen umfassenden Überblick darüber erhalten, wie es gegen Cocos2D eingesetzt wird.
Von allen verfügbaren Spielen im App Store sind viele der am meisten heruntergeladenen und rentabelsten 2D-Spiele. Einige ikonische Titel in dieser Kategorie umfassen Angry Birds, Tiny Wings und Cut the Rope. Für den Erfolg dieser Spiele sind mehrere gemeinsame Merkmale verantwortlich: wunderschöne Grafiken, Partikeleffekte, eine Physik-Engine, nahtlose Animationen und fesselnde Soundeffekte.
Vor dem Release des iOS 7 SDK war das Erstellen von Spielen dieser Art nur mit Drittanbieter-Frameworks und-Engines möglich. Mit der Einführung des Sprite-Kits brauchen Entwickler nun nicht mehr nur das native SDK, um alles zu finden, was sie benötigen, um großartige 2D- und 2.5D-Spiele erstellen zu können. Die von Sprite Kit bereitgestellte Funktionalität umfasst Sprites, Shapes, Partikel (z. B. Feuer, Rauch usw.), Animationen, Physiksimulation, Audio, Video und visuelle Effekte. Xcode 5 bietet jetzt auch Unterstützung für Texturpacks und Partikeldesign.
Sprite Kit kann logisch in die folgenden drei Teile abstrahiert werden:
Eine von Apple bereitgestellte und gewartete 2D- und 2.5D-Spielplattform bietet einige sehr solide Vorteile. Berücksichtigen Sie die folgenden Punkte:
Bei der nativen Entwicklung und den nativen Tools geht es um Leistung.
Obwohl Entwickler normalerweise wünschen, dass ihre Spiele auf so vielen verschiedenen Plattformen wie möglich laufen, hat ein natives Spiel fast immer eine bessere Leistung als ein nicht-natives Spiel. Wenn die Tools zur Entwicklung dieser Spiele nativ sind, kann außerdem sichergestellt werden, dass der Code in das Plattform-Ökosystem integriert ist.
Wie bereits erwähnt, kombinieren Sprite Kit und Xcode 5 viele der wesentlichen Komponenten zum Erstellen großartiger Spiele. Dies bedeutet, dass die Entwicklung rationalisiert werden kann und die Werkzeuge zuverlässiger und effektiver sind.
Das Schreiben eines Spiels mit einem Drittanbieter-Framework oder einer Spiel-Engine ist immer ein zweischneidiges Schwert. Wir wissen nie, ob die Tools mit zukünftigen Plattformaktualisierungen kompatibel sind oder ob das Spiel nach einem Update gut läuft. Wenn Dinge kaputt gehen, ist es unsicher, wie lange die Community braucht, um die Fehler zu beheben.
Cocos2D ist ein Beispiel eines Open-Source-Projekts, das sich mit diesem Problem befassen muss. Der Code wird ständig weiterentwickelt. Bei jedem neuen Release müssen mehrere Sicherheitsschritte ausgeführt werden, um zu gewährleisten, dass mit Cocos2D erstellte Anwendungen weiterhin auf der neuesten Version von iOS und der neuesten Hardware ausgeführt werden.
Mit dem Sprite Kit stellt Apple eine Reihe von Tools bereit, mit denen sichergestellt wird, dass der Spielcode auf jedem kompatiblen Gerät problemlos funktioniert. Beachten Sie, dass das Sprite Kit nicht nur ein iOS-Framework ist. Entwickler können auch Sprite Kit-Spiele für OS X erstellen. Die Sprite Kit-Spiele können also auch auf zukünftigen iOS-Geräten ausgeführt werden.
Die Benutzerfreundlichkeit war ein wesentlicher Faktor für den Erfolg von Game-Engines wie Cocos2D. Im Allgemeinen fanden Entwickler die Implementierung von Cocos2D viel einfacher als andere native Alternativen wie OpenGL ES. Mit Cocos2D wurden alle einfachen API-Aufrufe in einfache Methoden umgewandelt.
Sprite Kit folgt diesem Ansatz und bietet Hunderte von Methoden, die den Spielentwicklungsprozess erheblich erleichtern. Sprite Kit ist auch freundlich. Es verfügt über die benutzerdefinierte, gut konzipierte Apple-API und wird mit einer vollständig strukturierten Dokumentation geliefert. Apple hat dieses Tool hervorragend für Entwickler von Drittanbietern geschärft. Der größte Vorteil ist, dass alle Ressourcen, die Sie zum Erstellen eines Spiels benötigen, voll geladen sind. Physik, Soundeffekte, Partikeleffekte, Texturen, Szenenmanagement - alles ist in einem einzigen Paket enthalten.
Beachten Sie, dass bei der ersten Präsentation von Sprite Kit Ricardo Quesada, der Hauptentwickler von Cocos2D sagte auf Twitter:
Sprite Kit ist sehr gut. Mit weniger Funktionen als Cocos2D, aber besser. Ich mag die Physikintegration.
Dies ist ein großes Lob von einem der führenden Köpfe hinter Cocos2D!
Merkmal | Sprite-Kit | Cocos2D |
Open Source | Nein | Ja |
Native Unterstützung für Objective-C | Ja | Ja |
Graphics Engine | Ja | Ja |
Animationen | Ja | Ja |
Physik-Simulation | Ja (integriert) | Nein (Box2D oder Chipmunk erforderlich) |
Partikeleffekte | Ja | Ja |
Native Integration von Xcode | Ja | Nein |
Automatische Atlas-Erstellung | Ja | Nein |
Eingebauter Partikeleditor | Ja | Nein |
Shader | Nein | Ja |
Kamera | Nein | Ja |
Wie sehen also Projekte mit jeder Game Engine aus? Um diese Frage zu beantworten, haben die Autoren den vollständigen Quellcode für ein Sprite-Kit und ein Cocos2D-Projekt beigefügt. Sie können diese Projekte als Vergleich aller Game-Engines auf hoher Ebene verwenden.
In diesem Abschnitt werden allgemeine Aufgaben und Konzepte beschrieben, die zeigen, wie diese in Cocos2D und Sprite Kit implementiert werden.
CCLayer oder SkScene ist das Hauptobjekt zum Zeichnen anderer Objekte. Sie können sich dies als Standardansicht vorstellen, in der alle Objekte, Animationen und Berührungsereignisse angezeigt werden.
Der Übergang zwischen Szenen in Cocos2D wird mit den folgenden Schritten ausgeführt:
GameScene * gameScene = [[GameScene-Zuordnung] init]; [[CCDirector sharedDirector] replaceScene: gameScene];
Notiere dass der GameScene.h
Datei muss von der sein CCLayer
Kategorie und haben den spezifischen Initialisierer zur Verfügung.
@ Schnittstelle GameScene: CCLayer + (CCScene *) Szene;
Im GameScene.m
, Die erste Implementierung ist:
+(CCScene *) Szene CCScene * Szene = [CCScene-Knoten]; GameScene * Layer = [GameScene-Knoten]; [scene addChild: layer]; Rückkehr Szene; - (id) init if ((self = [super init]))) // Ihr Code hier return self;
In Sprite Kit ist der Übergang ähnlich:
GameScene * gameScene = [[GameScene-Zuordnung] initWithSize: CGSizeMake (1024, 768)]; [self.scene.view presentScene: gameScene];
Das GameScene
muss von der sein SKScene
Kategorie und die -(id) initWithSize: (CGSize) -Größe
ist der benutzerdefinierte Initialisierer. Ein einfaches Beispiel:
-(id) initWithSize: (CGSize) size if (self = [super initWithSize: size]) // Ihr Code return self;
Sprite-Objekte werden normalerweise zur Anzeige von Bildern verwendet. Es kann verschiedene Eigenschaften haben, z. B. Drehung, Skalierung, Position, Rahmen, IDs und mehr. Die Implementierung von Cocos2D und Sprite Kit ist ähnlich. Die Implementierung von Cocos2D ist:
CCSprite * aSprite; aSprite = [CCSprite spriteWithFile: @ "player.png"]; aSprite.scale = .5; aSprite.position = ccp (_size.width / 1.30, _size.height / 1.25); [self addChild: aSprite];
Während in Sprite Kit ist die Implementierung:
SKSpriteNode * planeShadow = [SKSpriteNode spriteNodeWithImageNamed: @ "player.png"]; planeShadow.scale = 0,5; planeShadow.position = CGPointMake (CGRectGetMidX (self.frame) + 100, CGRectGetMidY (self.frame) +200); [self addChild: planeShadow];
Beschriftungsobjekte werden zur Anzeige von Text verwendet. Es kann verschiedene Eigenschaften haben, darunter Text, Textgröße, Textfarbe, Position und viele andere. Die Implementierung von Cocos2D und Sprite Kit ist ähnlich. Die Implementierung von Cocos2D ist:
CCLabelTTF * label = [CCLabelTTF labelWithString: @ "Hello World" fontName: @ "Marker Filz" fontSize: 64]; // Regisseur nach der Fenstergröße fragen CGSize size = [[CCDirector sharedDirector] winSize]; label.position = ccp (Größe, Breite / 2, Größe, Höhe / 2); [self addChild: label];
Die Sprite Kit-Implementierung lautet:
SKLabelNode * gameScene = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; [gameScene setText: @ "Neues Spiel"]; [gameScene setFontSize: 18]; gameScene setPosition: CGPointMake (CGRectGetMidX (self.frame) + 5, CGRectGetMidY (self.frame) -40)]; [self addChild: gameScene];
In Cocos2D werden die Menüs mit zwei Objekten erstellt: CCMenu
und CCMenuItem
. Das folgende Beispiel zeigt ein Menü mit 2 Optionen in Cocos2D:
CGSize size = [[CCDirector sharedDirector] winSize]; [CCMenuItemFont setFontSize: 28]; CCMenuItem * itemNewGame = [CCMenuItemFont itemWithString: @ Block "Neues Spiel": ^ (id sender) // Ihr Code]; CCMenuItem * itemOptions = [CCMenuItemFont itemWithString: @ "Options" -Block: ^ (ID-Absender) NSLog (@ "Second Item"); ]; CCMenu * menu = [CCMenu menuWithItems: itemNewGame, itemOptions, nil]; [menu alignItemsHorizontallyWithPadding: 20]; [menu setPosition: ccp (size.width / 2, size.height / 2 - 50)]; [self addChild: menu];
SpiteKit enthält keine Arten von objektspezifischen Objekten. Sie müssen einen Event-Handler für ein bestimmtes Objekt erstellen, um es für Benutzereingaben zu aktivieren. Um ein Menü "erstellen" zu können, müssen Sie daher ein UIKit-Objekt oder ein Sprite-Kit-Objekt verwenden.
Das folgende Beispiel verwendet a SKLabelNode
als Menüpunkt. Zuerst definieren wir die SKLabelNode
:
SKLabelNode * gameScene = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; [gameScene setText: @ "Neues Spiel"]; [gameScene setFontSize: 18]; [gameScene setPosition: CGPointMake (CGRectGetMidX (Eigenrahmen) + 5, CGRectGetMidY (Eigenrahmen) -40)]; [self addChild: gameScene];
In der -(void) touchesBegan: (NSSet *) berührt das Ereignis withEvent: (UIEvent *)
Methode erstellen wir den Event-Handler, der das Touch-Ereignis abfängt:
für (UITouch * touch in touches) CGPoint location = [touch locationInNode: self]; if ([gameScene containsPoint: location]) // Szenenübergangsanimation SKTransition * enthüllen = [SKTransition enthülltWithDirection: SKTransitionDirectionDown duration: 1]; GameScene * gameScene = [[GameScene-Zuordnung] initWithSize: CGSizeMake (1024, 768)]; [self.scene.view presentScene: gameScene Übergang: enthüllen]; NSLog (@ "Touched gameScene !!!!");
Der vorgenannte Code bewirkt mehrere Dinge:
SKLabelNode
Objekt.Der Hauptunterschied zwischen Action und SKAction besteht darin, dass SKAction ein komplexes Objekt mit mehreren Eigenschaften ist. Aktion in Cocos2D ist nur eine Aktion, die der Programmierer definieren, aufrufen und behandeln muss.
Mit dem Sprite-Kit bietet SKAction den Entwicklern verschiedene Optionen, z. B. Drehen, Ändern der Größe, Skalieren, Wiederholen, Überblenden, Wiedergeben von Sounds und mehr. SKaction kann als abstraktes Objekt betrachtet werden, das sich mit jeder Art von Aktion befasst, vom Sound über Sprites bis hin zu Knoten.
Wir konzentrieren uns im Moment auf Bewegungsaktionen.
In Cocos2D müssen wir einen Scheduler definieren, um eine benutzerdefinierte Methode aufzurufen:
[self schedule: @selector (addSprite :) Intervall: 1];
Definieren Sie dann die benutzerdefinierte Methode, um die benutzerdefinierte Animation auszuführen.
- (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-Zuordnung] init]; ccBezierConfig bezier; ID bezierAction1; float splitDuration = 6 / 6,0; für (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 können Sie mit SKAction steuern, was mit einem Objekt am Anfang und am Ende der Bewegung passiert. Die nächsten Zeilen zeigen, wie Sie ein Objekt in einer geraden Linie verschieben können:
SKSpriteNode * playerSprite = [SKSpriteNode spriteNodeWithImageNamed: @ "player.png"]; [playerSprite setScale: 0.4]; SKAction * movement = [SKAction moveTo: CGPointMake (900, 500) Dauer: 5]; SKAction * remove = [SKAction removeFromParent]; [playerSprite runAction: [SKAction-Sequenz: @ [Bewegung, Entfernen]]]; [self addChild: playerSprite];
Wir können jedoch eine benutzerdefinierte Aktion definieren und diese Aktion mit SKAction aktivieren. Das folgende Beispiel zeigt ein Beispiel für eine Bézier-Bewegung (ähnlich der Cocos2D-Version von Action). Beachten Sie, dass wir einen Scheduler definieren müssen, um eine benutzerdefinierte Methode aufzurufen.
SKAction * wait = [SKAction waitForDuration: 1]; SKAction * callEnemies = [SKAction runBlock: ^ [self sendNewSKSpriteNode]; ]; SKAction * updateSKSpriteNodeOnScreen = [SKAction-Sequenz: @ [warten, callEnemies]]; [self runAction: [SKAction repeatActionForever: updateSKSpriteNodeOnScreen]];
Die Methode sendNewSKSpriteNode
behandelt die Bewegung des benutzerdefinierten Objekts.
-(void) sendNewSKSpriteNode CGRect screenRect = [[UIScreen-MainScreen] -Begrenzungen]; // Benutzerdefinierte SKAction SKSpriteNode * enemy = [SKSpriteNode spriteNodeWithImageNamed: @ "frankenstein.png"]; Feindschuppe = 0,6; CGMutablePathRef cgpath = CGPathCreateMutable (); // zufällige Werte float xStart = [self getRandomNumberBetween: 0 + enemy.size.width bis: screenRect.size.width-enemy.size.width]; float xEnd = [self getRandomNumberBetween: 0 + enemy.size.width bis: screenRect.size.width-enemy.size.width]; // ControlPoint1 float cp1X = [self getRandomNumberBetween: 0 + enemy.size.width bis: screenRect.size.width-enemy.size.width]; float cp1Y = [self getRandomNumberBetween: 0 + enemy.size.width bis: screenRect.size.width-enemy.size.height]; // ControlPoint2 Float cp2X = [self getRandomNumberBetween: 0 + enemy.size.width bis: screenRect.size.width-enemy.size.width]; float cp2Y = [self getRandomNumberBetween: 0 bis: 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: Feind]; SKAction * remove2 = [SKAction removeFromParent]; [Feind runAction: [SKAction-Sequenz: @ [planeDestroy, remove2]]]; CGPathRelease (cgpath);
Cocos2D hat keinen Partikeleditor. Man muss eine externe App verwenden, um das Partikel zu erstellen und dann spezifisch zu verwenden CCParticleExplosion
Eigenschaften, um sein Verhalten zu ändern. Nachdem Sie das Partikel in Ihrem Xcode-Projekt haben, können Sie es mit folgendem Befehl aufrufen:
CCParticleExplosion * _particleExplosion; particleExplosion = [[CCParticleExplosion allocation] 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]; partikelExplosion.position = ccp (_size.width / 5, _size.height / 5); [particleExplosion resetSystem];
Emitter werden im Sprite Kit zur Partikelerzeugung verwendet. Um sie verwenden zu können, müssen Sie Ihrem Projekt ein Partikel hinzufügen. Gehe zu Neu -> Datei -> Ressource -> Sprite Kit Particle File
. Als Nächstes sollten Sie es benennen und eine beliebige Art von Teilchen auswählen (Feuer, Magie, Rauch, Schnee usw.). Nun sehen Sie, dass zwei neue Dateien in Ihrem Xcode-Projekt angezeigt werden. Sie implementieren sie mit:
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];
Die SKEmitterNode-Klasse ist umfangreich und enthält mehrere Eigenschaften. Wir empfehlen Ihnen, es zu lesen, um zu erfahren, welche Eigenschaften ein Emitterknoten haben kann.
Sound ist ein aktiver Bestandteil eines Spiels oder einer Multimedia-Anwendung. In Cocos2D können wir dies mit zwei Schritten erreichen. Die erste besteht darin, die SimpleAudioEngine
Header-Datei.
#import "SimpleAudioEngine.h"
Dann rufen Sie mit den folgenden Zeilen die Musikdatei in unserem Projekt auf:
[[SimpleAudioEngine sharedEngine] playBackgroundMusic: @ "sound.caf" -Schleife: JA]; [[SimpleAudioEngine sharedEngine] setEffectsVolume: 0.4f];
Manchmal schließt Xcode die Musikdatei nicht automatisch in die "Bundle-Ressourcen kopieren" ein. In diesem Fall sollten Sie es manuell hinzufügen.
Mit dem Sprite Kit sind die Einschlüsse von Sounds einfach:
SKAction * soundAction = [SKAction playSoundFileNamed: @ "preview.mp3" waitForCompletion: NO]; [self runAction: soundAction];
Beachten Sie, dass Sie dazu mit dem Sprite Kit erneut das Objekt SKAction verwendet haben.
Wie Sie aus der obigen Analyse sehen können, weisen Cocos2D und Sprite Kit viele Ähnlichkeiten auf. Cocos2D verwendet mehrere Ebenen für jedes Objekt, während Sprite Kit mehr Objekte einkapselt und die Superklasse NSObject verwendet, um bestimmte Ziele (wie Schaltflächen oder Menüs) zu erreichen..
In puncto Benutzerfreundlichkeit ist Sprite Kit besonders gut geeignet, wenn Sie das Particle-System oder den Action-Performer verwenden möchten. Wenn Sie jedoch mit allgemeineren Objekten arbeiten, haben beide Frameworks ungefähr denselben Schwierigkeitsgrad.
Das Erstellen eines Spiels mit Sprite Kit bringt jedoch viele wichtige Vorteile mit sich, darunter eine vollständig integrierte Physik-Engine, optimierte Workflow-Tools in Xcode 5, die Kompatibilität mit iOS und OS X und die offizielle Wartung durch Apple.
Die Frage ist: Was werden Sie für Ihr nächstes 2D-Spielprojekt verwenden? Lass es uns in den Kommentaren wissen.