SpriteKit: Passage de données entre les scènes

Je suis coincé en essayant de transmettre des données entre les scènes "SKScene" dans SpriteKit. Par exemple, je voudrais passer le score du niveau A au niveau B.

Peut-être que la solution est l'archivage mais je voudrais mettre en œuvre quelque chose de plus simple comme la façon dont nous utilisons les controllers de vue.

Toute idée à cet égard sera très appréciée.

Si vous allez faire passer le score à un grand nombre de scènes différentes, vous pouvez le stocker dans NSUserDefaults ou dans un mécanisme de stockage accessible. Cependant, si vous cherchez à transmettre des données entre des objects SpriteKit, chaque SKNode (y compris SKScene ) possède une propriété de dictionary appelée userData que vous pouvez utiliser pour tout ce que vous désirez. Voici un exemple de comment vous pourriez passer le score entre les scènes:

  - (void)changeScene { SKView *spriteView = (SKView *) self.view; SKScene *currentScene = [spriteView scene]; SKScene *newScene = [MySceneClass scene]; [newScene.userData setObject:[currentScene.userData objectForKey:@"score"] forKey:@"score"]; [spriteView presentScene:newScene]; } 

Stockez le score dans votre instance de controller de vue, ou sous-classz le SKView et stockez-le là. Cela conservera tout object pour la durée de vie de la vue.

Si vous souhaitez que les scores soient conservés entre les redémarrages de l'application, utilisez NSUserDefaults .

Kobold Kit rend vraiment des choses comme ça facile sans sous-classs personnalisées. La vue a (et n'importe quel noeud peut avoir) un object KKModel qui est un stockage de key / valeur pour les deux types intégrales (float, int, etc via KKMutableNumber ) et les objects arbitraires.

Vous pouvez donc persister et accéder à votre object highscores depuis n'importe quel noeud en l'attachant à la vue:

 [self.kkView.model setObject:highscores forKey:@"highscores"]; 

La propriété kkView est un raccourci pour écrire (KKView*)self.view .

Il n'est absolument pas nécessaire d'utiliser ou de bénéficier de l'utilisation de singletons pour les objects dont la durée de vie est liée à la scène ou à la vue. Ils appartiennent à la scène ou à la vue, point final.

Cette approche a fonctionné pour moi et je pense que c'est correct. Jusqu'à présent, c'est le moyen le plus simple et le plus rapide de transmettre des données entre les scènes que j'ai trouvées.

1. Informations de base sur userData:

1.1. Maintenez la pomme "Command key" et appuyez sur le button gauche de la souris (dans Xcode) sur la string "userData" (par exemple " self.userData ;"). Vous obtiendrez les informations suivantes:

 // An optional dictionary that can be used to hold user data pretaining to the node. Defaults to nil. @property (SK_NONATOMIC_IOSONLY, retain) NSMutableDictionary *userData; 

1.2. Visitez les docs apple: userData

1.3 userData est un NSMutableDictionary qui est essentiellement un tableau spécial. À côté de la valeur, il contient une key qui est liée à la valeur. Avec cette key, vous pouvez find des valeurs. Cela pourrait être utile aussi: docs apple: NSMuttableDictionary

2. La solution:

2.1. firstScene

 //somewhere in firstScene.m //how the tranisiton from firstScene to secondScene is going to look and how long it is goint to take SKTransition *reveal = [SKTransition moveInWithDirection:SKTransitionDirectionDown duration:0.5]; SKView * skView = (SKView *)self.view; SKScene *secondScene = [WBMGameEndsScene sceneWithSize:skView.bounds.size]; //You need to initialize the NSMD since it is by default nil. secondScene.userData = [NSMutableDictionary dictionary]; 

Ici, je me réfère aux userData de la secondeScene en ajoutant un object qui est mon score. À des fins de test, il est juste 6. Je vais append ma variable d'instance de score. Vous pouvez append ce que vous voulez car il accepte les objects de type "id". La key est importante. Vous l'utiliserez dans le secondScene.m pour accéder à la valeur de l'object depuis. Vérifiez que vous ne le tapez pas mal.

 [secondScene .userData setObject:@"6" forKey:@"score"]; //Testing NSLog(@"Is it finally working -- %@",[secondScene .userData objectForKey:@"score"]); //The secondScene will scale to fit the whole SKView secondScene.scaleMode = SKSceneScaleModeAspectFill; //present the secondScene [self.scene.view presentScene: secondScene transition:reveal]; 

* WBMGameEndsScene est mon secondScene. Je l'ai créé dans Xcode avec "File – New File …" comme: SKScene. Il contiendra datatables d'user montrées plus tard.

2.2. secondScene

 //secondScene.m ( ex. in my :"@implementation WBMGameEndsScene") 

Ces lignes de code suivantes vérifient si la valeur a été correctement ajoutée:

 -(void)didMoveToView:(SKView *)view { NSLog(@"-- -(void)willMoveFromView:(SKView *)view --"); NSLog(@"Working score is : %@",[self.userData valueForKey:@"score"]); NSLog(@"Working score is : %@",[self.userData objectForKey:@"score"]); } 

La sortie de la console est:

 2014-03-12 15:29:06.804 AppTest[4841:60b] -(id)initWithSize:(CGSize)size 2014-03-12 15:29:06.806 AppTest[4841:60b] scoreLabel 2014-03-12 15:29:06.812 AppTest[4841:60b] successMessage 2014-03-12 15:29:06.815 AppTest[4841:60b] Is it finally working -- 6 2014-03-12 15:29:06.815 AppTest[4841:60b] -- -(void)willMoveFromView:(SKView *)view -- 2014-03-12 15:29:06.816 AppTest[4841:60b] Working score is : 6 2014-03-12 15:29:06.816 AppTest[4841:60b] Working score is : 6 

Si j'ai quelque chose de mal, corrigez-moi s'il vous plaît :). Spécifications: iOS 7.0, Xcode Version 5.1 (5B130a), OS X 10.9.2

Où / comment faites-vous la transition entre les scènes? Si vous pouviez montrer juste le code où vous créez votre nouvelle scène qui aiderait. Il se peut que je manque le sharepoint la question, mais si vous avez un 'gestionnaire de scène' / browser de quelque sorte pour cela, il vous suffit de sauvegarder temporairement le score dans une variable locale et de le passer dans votre nouvelle scène.

La documentation d'Apple indique que userData est le moyen de stockage des données spécifiques aux nœuds dans les meilleures pratiques de Sprite Kit

Utilisez la propriété userData sur les noeuds pour stocker datatables spécifiques au jeu, en particulier si vous ne mettez pas en œuvre vos propres sous-classs.

Par conséquent, j'accepterais la réponse de @ doctorBroctor comme la bonne pour quand utiliser Sprite Kit nativement.

Cependant, vous devez vous callbacker d'initialiser userData pour le noeud cible avant de définir une valeur comme indiqué par @ LearnCocos2d dans cette réponse. Vous pouvez le faire à l'intérieur de la méthode initWithSize: de la sous-class SKScene que vous êtes sur le point d'effectuer.

  // First Scene NSUserDefaults.standardUserDefaults().setInteger(12345, forKey:"SCORE") // Second Scene if let myScore: AnyObject = NSUserDefaults.standardUserDefaults().objectForKey("SCORE") { println(myScore) finalScore = myScore as IntegerLiteralType }