Sprite Kit est l’une des nouvelles technologies les plus intéressantes disponibles avec iOS 7 SDK et Xcode 5, mais comment se compare-t-il à un moteur de jeu établi tel que Cocos2D? Ce tutoriel fournira une brève introduction à Sprite Kit avant d’examiner en détail comment il se compare à Cocos2D..
Parmi les jeux disponibles sur l'App Store, la plupart des jeux les plus téléchargés et les plus rentables sont des jeux en 2D. Certains titres emblématiques de cette catégorie incluent Angry Birds, Tiny Wings et Cut the Rope. Le succès de ces jeux repose sur plusieurs caractéristiques communes: de superbes graphismes, des effets de particules, un moteur physique, une animation homogène et des effets sonores convaincants..
Avant la sortie du SDK iOS 7, la création de tels jeux n'était possible qu'avec l'utilisation de frameworks et de moteurs tiers. Maintenant, avec l'introduction de Sprite Kit, les développeurs n'ont plus qu'à chercher dans le SDK natif pour trouver tout ce dont ils ont besoin pour pouvoir créer de superbes jeux en 2D et 2.5D. La fonctionnalité fournie par Sprite Kit comprend les images-objets, les formes, les particules (feu, fumée, etc.), les animations, la simulation physique, les effets audio, vidéo et visuels. Xcode 5 prend désormais également en charge les packs de textures et la conception de particules.
Sprite Kit peut être logiquement résumé dans les trois parties suivantes:
Avoir une plate-forme de jeu 2D et 2.5D fournie et maintenue par Apple présente de très solides avantages. Considérez les points suivants:
Le développement et les outils natifs sont une question de performance.
Bien que les développeurs souhaitent généralement que leurs jeux fonctionnent sur autant de plates-formes différentes que possible, un jeu natif aura presque toujours de meilleures performances qu'un jeu non natif. De plus, si les outils pour développer ces jeux sont natifs, vous pouvez vous assurer que le code est intégré à l'écosystème de la plateforme..
Comme mentionné ci-dessus, Sprite Kit et Xcode 5 combinent de nombreux composants essentiels à la création de jeux de qualité. Cela signifie que le développement peut être simplifié et que les outils seront plus fiables et efficaces.
Écrire un jeu en utilisant un framework tiers ou un moteur de jeu est toujours une arme à deux tranchants. Nous ne savons jamais si les outils seront compatibles avec les futures mises à jour de la plateforme, ou même si le jeu fonctionnera bien après une mise à jour. Quand les choses se cassent, on ne sait pas combien de temps il faudra à la communauté pour réparer les bugs..
Cocos2D est un exemple de projet open-source qui doit traiter ce problème. Le code évolue constamment et à chaque nouvelle version, plusieurs étapes de sécurité doivent être effectuées afin de garantir que les applications construites avec Cocos2D seront toujours exécutées sur la dernière version d'iOS et sur le dernier matériel..
Avec Sprite Kit, Apple fournit un ensemble d’outils permettant de s’assurer que le code de jeu fonctionnera sans problème sur tous les appareils compatibles. Notez que Sprite Kit n'est pas simplement un framework iOS. Les développeurs peuvent également commencer à créer des jeux Sprite Kit pour OS X. Il est fort à parier que les jeux Sprite Kit fonctionneront également sur tous les futurs appareils iOS..
La facilité d'utilisation était l'un des principaux facteurs du succès des moteurs de jeu tels que Cocos2D. De manière générale, les développeurs ont trouvé Cocos2D beaucoup plus facile à mettre en œuvre que d’autres alternatives natives telles que OpenGL ES. Avec Cocos2D, tous les appels d'API de bas niveau ont été transformés en méthodes simples.
Sprite Kit suit cette approche et propose des centaines de méthodes qui facilitent grandement le processus de développement de jeux. Sprite Kit est également sympathique. Il possède une API Apple personnalisée et bien conçue, ainsi qu'une documentation complète et structurée. Apple a fait un travail remarquable en améliorant cet outil pour que les développeurs tiers puissent l’utiliser. Le plus gros avantage de tous est qu'il est fourni avec toutes les ressources dont vous avez besoin pour créer un jeu. Physique, effets sonores, effets de particules, textures, gestion de scène - tout est inclus dans un seul paquet.
Notez que, lors de la présentation initiale de Sprite Kit, Ricardo Quesada, le développeur principal de Cocos2D a déclaré ce qui suit sur Twitter:
Sprite Kit est très bon. Avec moins de fonctionnalités que Cocos2D, mais mieux. J'aime l'intégration de la physique.
C’est un éloge venant de l’un des principaux esprits derrière Cocos2D.!
Fonctionnalité | Kit Sprite | Cocos2D |
Open source | Non | Oui |
Prise en charge native d'Objective-C | Oui | Oui |
Moteur graphique | Oui | Oui |
Animations | Oui | Oui |
Simulation Physique | Oui (intégré) | Non (nécessite Box2D ou Chipmunk) |
Effets de particules | Oui | Oui |
Intégration native Xcode | Oui | Non |
Création automatique d'atlas | Oui | Non |
Éditeur de particules intégré | Oui | Non |
Shaders | Non | Oui |
Caméra | Non | Oui |
Alors, à quoi ressemblent les projets de chaque moteur de jeu? Pour répondre à cette question, les auteurs ont inclus le code source complet d'un projet Sprite Kit et d'un projet Cocos2D. Vous pouvez utiliser ces projets comme comparaison de haut niveau de chaque moteur de jeu..
Dans cette section, nous détaillerons les tâches et les concepts courants et montrerons comment les implémenter à la fois dans Cocos2D et dans Sprite Kit..
CCLayer ou SkScene est l'objet principal utilisé pour dessiner d'autres objets. Vous pouvez considérer cela comme la vue par défaut qui recevra tous les objets, animations et événements tactiles..
La transition entre les scènes dans Cocos2D s’effectue comme suit:
GameScene * gameScene = [[GameScene alloc] init]; [[CCDirector sharedDirector] replaceScene: gameScene];
Notez que le GameScene.h
le fichier doit être du CCLayer
catégorie et avoir l'initialiseur spécifique disponible.
@interface GameScene: CCLayer + (CCScene *) scène;
Dans GameScene.m
, l'implémentation initiale est:
+(CCScene *) scene CCScene * scene = [noeud CCScene]; GameScene * layer = [noeud GameScene]; [scène addChild: layer]; scène de retour; - (id) init if ((self = [super init])) // Votre code ici return self;
Dans Sprite Kit, la transition est similaire:
GameScene * gameScene = [[GameScene alloc] initWithSize: CGSizeMake (1024, 768)]; [self.scene.view presentScene: gameScene];
le GameScene
doit être du SKScene
catégorie, et la -(id) initWithSize: taille (CGSize)
est l'initialiseur personnalisé. Un exemple simple:
-(id) initWithSize: (CGSize) taille if (self = [super initWithSize: size]) // Votre code return self;
Les objets Sprite sont normalement utilisés pour afficher un type d’image. Il peut avoir plusieurs propriétés, telles que: rotation, échelle, position, cadres, identifiants, etc. Les implémentations de Cocos2D et de Sprite Kit sont similaires. L'implémentation de Cocos2D est:
CCSprite * aSprite; aSprite = [CCSprite spriteWithFile: @ "player.png"]; aSprite.scale = .5; aSprite.position = ccp (_size.width / 1.30, _size.height / 1.25); [auto addChild: aSprite];
Dans Sprite Kit, l’implémentation est la suivante:
SKSpriteNode * planeShadow = [SKSpriteNode spriteNodeWithImageNamed: @ "player.png"]; planeShadow.scale = 0,5; planeShadow.position = CGPointMake (CGRectGetMidX (self.frame) + 100, CGRectGetMidY (self.frame) +200); [auto addChild: planeShadow];
Les objets d'étiquette sont utilisés pour afficher du texte. Il peut avoir plusieurs propriétés, notamment le texte, la taille du texte, la couleur du texte, la position, etc. Les implémentations de Cocos2D et de Sprite Kit sont similaires. L'implémentation de Cocos2D est:
CCLabelTTF * label = [CCLabelTTF labelWithString: @ "Bonjour le monde" nom de la police: @ "Feutre du marqueur" fontSize: 64]; // demande au directeur la taille de la fenêtre CGSize size = [[CCDirector sharedDirector] winSize]; label.position = ccp (size.width / 2, size.height / 2); [auto addChild: label];
L'implémentation du kit Sprite est:
SKLabelNode * gameScene = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; [gameScene setText: @ "Nouveau jeu"]; [gameScene setFontSize: 18]; gameScene setPosition: CGPointMake (CGRectGetMidX (self.frame) + 5, CGRectGetMidY (self.frame) -40)]; [auto addChild: gameScene];
Dans Cocos2D, les menus sont créés à l'aide de deux objets: CCMenu
et CCMenuItem
. L'exemple suivant présente un menu avec 2 options dans Cocos2D:
CGSize size = [[[CCDirector sharedDirector] winSize]; [CCMenuItemFont setFontSize: 28]; CCMenuItem * itemNewGame = [CCMenuItemFont itemWithString: @ Bloc "Nouveau jeu": ^ (expéditeur id) // Votre code]; CCMenuItem * itemOptions = [CCMenuItemFont itemWithString: @ Bloc "Options": ^ (expéditeur id) NSLog (@ "Deuxième élément"); ]; CCMenu * menu = [CCMenu menuWithItems: itemNewGame, itemOptions, nil]; [menu alignItemsHorizontallyWithPadding: 20]; [menu setPosition: ccp (size.width / 2, size.height / 2 - 50)]; [auto addChild: menu];
SpiteKit n'inclut aucun type d'objet spécifique au menu. Vous devez créer un gestionnaire d'événements pour un objet spécifique afin de l'activer pour la saisie de l'utilisateur. Donc, pour "créer" un menu, vous devez utiliser un objet UIKit ou un objet Sprite Kit..
L'exemple suivant utilise un SKLabelNode
comme élément de menu. Tout d'abord, nous définissons le SKLabelNode
:
SKLabelNode * gameScene = [SKLabelNode labelNodeWithFontNamed: @ "Chalkduster"]; [gameScene setText: @ "Nouveau jeu"]; [gameScene setFontSize: 18]; [gameScene setPosition: CGPointMake (CGRectGetMidX (self.frame) + 5, CGRectGetMidY (self.frame) -40)]; [auto addChild: gameScene];
À l'intérieur de -(void) toucheBegan: (NSSet *) touche avecEvent: (UIEvent *) événement
méthode nous allons créer le gestionnaire d’événement qui interceptera l’événement touch:
pour (UITouch * contacts tactiles) CGPoint location = [touch locationInNode: self]; if ([gameScene contientPoint: emplacement]) // Animation de transition de scène SKTransition * révéler = [SKTransition révélerAvecDirection: SKTransitionDirectionDown durée: 1]; GameScene * gameScene = [[GameScene alloc] initWithSize: CGSizeMake (1024, 768)]; [self.scene.view presentScene: gameScene transition: révéler]; NSLog (@ "Touched gameScene !!!!");
Le code susmentionné fait plusieurs choses:
SKLabelNode
objet.La principale différence entre Action et SKAction est que SKAction est un objet complexe ayant plusieurs propriétés. Une action dans Cocos2D est uniquement une action que le programmeur doit définir, appeler et traiter..
Avec Sprite Kit, SKAction offre aux développeurs plusieurs options, telles que la rotation, le redimensionnement, la mise à l’échelle, la répétition, le fondu, la lecture du son, etc. SKaction peut être vu comme un objet abstrait qui traite de tout type d’action, du son au sprites, en passant par les nœuds..
Nous allons nous concentrer pour le moment sur les actions de mouvement.
Dans Cocos2D, nous devons définir un planificateur pour appeler une méthode personnalisée:
[auto schedule: @selector (addSprite :) intervalle: 1];
Et ensuite définir la méthode personnalisée pour faire l'animation personnalisée.
- (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 rangeX = maxX - minX; int actualY = (arc4random ()% rangeX) + minX; CCCallBlockN * actionMoveDone = [CCCallBlockN actionWithBlock: ^ (noeud CCNode *) NSLog (@ "Sprite free!"); ]; NSMutableArray * arrayBezier = [[NSMutableArray alloc] init]; ccBezierConfig bezier; id bezierAction1; float splitDuration = 6 / 6.0; pour (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];
Dans Sprite Kit, nous pouvons utiliser SKAction pour contrôler le sort d’un objet au début et à la fin du mouvement. Les lignes suivantes montrent comment déplacer un objet en ligne droite:
SKSpriteNode * playerSprite = [SKSpriteNode spriteNodeWithImageNamed: @ "player.png"]; [playerSprite setScale: 0.4]; SKAction * mouvement = [SKAction moveTo: CGPointMake (900, 500) durée: 5]; SKAction * remove = [SKAction removeFromParent]; [playerSprite runAction: [séquence SKAction: @ [mouvement, supprimer]]]; [auto addChild: playerSprite];
Cependant, nous pouvons définir une action personnalisée et utiliser SKAction pour l'activer. L'exemple suivant illustre un mouvement Bézier (similaire à la version Cocos2D de Action). Notez que nous devons définir un planificateur pour appeler une méthode personnalisée.
SKAction * wait = [SKAction waitForDuration: 1]; SKAction * callEnemies = [SKAction runBlock: ^ [self sendNewSKSpriteNode]; ]; SKAction * updateSKSpriteNodeOnScreen = [Séquence de SKAction: @ [wait, callEnemies]]; [self runAction: [SKAction repeatActionForever: updateSKSpriteNodeOnScreen]];
La méthode sendNewSKSpriteNode
va gérer le mouvement d'objet personnalisé.
-(void) sendNewSKSpriteNode CGRect screenRect = [[UIScreen mainScreen]]]; // Personnalisation de SKAction SKSpriteNode * ennemis = [SKSpriteNode spriteNodeWithImageNamed: @ "frankenstein.png"]; ennemi.échelle = 0,6; CGMutablePathRef cgpath = CGPathCreateMutable (); // valeurs aléatoires float xStart = [self getRandomNumberBetween: 0 + ennemis.size.width à: screenRect.size.width-ennemis.size.width]; float xEnd = [self getRandomNumberBetween: 0 + ennemis.size.width à: screenRect.size.width-ennemis.size.width]; // ControlPoint1 float cp1X = [self getRandomNumberBetween: 0 + ennemis.size.width à: screenRect.size.width-ennemis.size.width]; float cp1Y = [self getRandomNumberBetween: 0 + ennemis.size.width à: screenRect.size.width-ennemis.size.height]; // ControlPoint2 float cp2X = [self getRandomNumberBetween: 0 + ennemis.size.width à: screenRect.size.width-ennemis.size.width]; float cp2Y = [self getRandomNumberBetween: 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 durée: 5]; [auto addChild: ennemi]; SKAction * remove2 = [SKAction removeFromParent]; [ennemi runAction: [séquence SKAction: @ [planeDestroy, remove2]]]; CGPathRelease (cgpath);
Cocos2D ne dispose d'aucun éditeur de particules. Il faut utiliser une application externe pour créer la particule, puis utiliser des outils spécifiques. CCParticleExplosion
propriétés pour changer son comportement. Une fois que vous avez la particule dans votre projet Xcode, vous pouvez l'appeler en utilisant:
CCParticleExplosion * _particleExplosion; particuleExplosion = [[CCParticleExplosion alloc] initWithTotalParticles: 800]; particleExplosion.texture = [[CCTextureCache sharedTextureCache] addImage: @ "texture.png"]; particleExplosion.life = 0.0f; particleExplosion.lifeVar = 0.708f; particuleExplosion.startSize = 40; particuleExplosion.startSizeVar = 38; particuleExplosion.endSize = 14; particuleExplosion.endSizeVar = 0; particuleExplosion.angle = 360; particleExplosion.angleVar = 360; particuleExplosion.speed = 243; particuleExplosion.speedVar = 1; CGPoint g = CGPointMake (1,15, 1,58); particuleExplosion.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); [particleExplosion resetSystem];
Les émetteurs sont utilisés dans le kit Sprite pour la génération de particules. Pour les utiliser, vous devez ajouter une particule à votre projet. Aller à Nouveau -> Fichier -> Ressource -> Fichier de particules du kit Sprite
. Ensuite, vous devez le nommer et choisir n'importe quel type de particule (feu, magie, fumée, neige, entre autres). Vous verrez maintenant que deux nouveaux fichiers apparaîtront sur votre projet Xcode. Vous les implémenterez avec:
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); [auto addChild: smokeTrail];
La classe SKEmitterNode est étendue et contient plusieurs propriétés. Nous vous conseillons de le lire afin d'apprendre chaque propriété qu'un nœud émetteur peut avoir.
Le son est une partie active de tout jeu ou application multimédia. Dans Cocos2D, nous pouvons y parvenir en deux étapes. La première consiste à inclure le SimpleAudioEngine
En tête de fichier.
#import "SimpleAudioEngine.h"
Ensuite, vous utilisez les lignes suivantes pour appeler le fichier de musique dans notre projet:
[[SimpleAudioEngine sharedEngine] playBackgroundMusic: @ boucle "sound.caf": OUI]; [[SimpleAudioEngine sharedEngine] setEffectsVolume: 0.4f];
Parfois, Xcode n'inclut pas automatiquement le fichier de musique dans "Copier les ressources du paquet". Si cela se produit, vous devez l'ajouter manuellement.
Avec Sprite Kit, les inclusions de sons sont simples:
SKAction * soundAction = [SKAction playSoundFileNamed: @ "preview.mp3" waitForCompletion: NO]; [self runAction: soundAction];
Notez que pour accomplir cela avec Sprite Kit, vous avez de nouveau utilisé l'objet SKAction..
Comme vous pouvez le constater d'après l'analyse ci-dessus, Cocos2D et Sprite Kit présentent de nombreuses similitudes. Cocos2D utilise plusieurs couches pour chaque objet, tandis que Sprite Kit encapsule plus d'objets et utilise la super classe NSObject pour atteindre certains objectifs (comme des boutons ou des menus)..
En termes de convivialité, Sprite Kit brille vraiment lorsque vous souhaitez utiliser le système de particules ou l’Agent de performance. Cependant, lorsqu’on travaille avec des objets plus généraux, les deux frameworks sont à peu près au même niveau de difficulté.
Néanmoins, la création d’un jeu avec Sprite Kit présente de nombreux avantages, notamment un moteur physique totalement intégré, des outils de flux de travail simplifiés dans Xcode 5, la compatibilité avec iOS et OS X et la maintenance officielle par Apple..
La question est la suivante: lequel utiliserez-vous pour votre prochain projet de jeu en 2D? Faites le nous savoir dans les commentaires.