SpriteKit: передача данных между сценами
Я застрял, пытаясь передать данные между сценами "SKScene" в SpriteKit. Например, я хотел бы передать счет с уровня A на уровень B.
возможно, решение архивирование, но я хотел бы реализовать что-то более простое, как то, как мы используем с контроллерами view.
любая подсказка в этом отношении будет очень признательна.
6 ответов
если вы собираетесь передавать счет на много разных сцен, вы можете сохранить его в NSUserDefaults
или какой-то доступный механизм хранения. Однако, если вы хотите передать данные между объектами SpriteKit, каждый SKNode
(включая SKScene
) имеет свойство словаря под названием userData
что вы можете использовать для чего угодно вы так желаете. Вот пример того, как вы можете передать счет между сценами:
- (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];
}
сохраните счет в экземпляре контроллера вида или подклассе SKView и сохраните его там. Это сохранит любой объект на время существования представления.
Если вам нужно, чтобы баллы сохранялись между перезапусками приложений, используйте NSUserDefaults
.
Комплект Кобольд на самом деле делает вещи, как это легко, без пользовательских подклассов. Представление (и любой узел может иметь)KKModel
объект, который является хранилищем ключей / значений для обоих интегральных типов (float, int и т. д KKMutableNumber
) и произвольные объекты.
так можно сохранить и открыть свои рекорды объекта из любого узла привязав его к виду:
[self.kkView.model setObject:highscores forKey:@"highscores"];
свойство kkView является сокращением для записи (KKView*)self.view
.
здесь абсолютно не нужно использовать или использовать преимущества в использовании singletons для объектов, время жизни которых привязано либо к сцене, либо к виду. Они принадлежат либо сцене, либо виду, периоду.
этот подход работал для меня, и я думаю, что это правильно. Пока это самый простой и быстрый способ передачи данных между сценами, которые я нашел.
1. Основная информация о userData:
1.1. Удерживайте apple "Command key" и нажмите левую кнопку мыши (в Xcode) в строке "userData" (например. "личность.userData ;"). Вы получите следующую информацию:
// 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. Посетите apple docs: userData
1.3 userdata-это NSMutableDictionary, по сути, это специальный массив. Рядом со значением он содержит ключ, который привязан к значению. С помощью этого ключа можно найти значения. Это может быть полезно также:Apple docs: NSMuttableDictionary
2. Решение:
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];
здесь я ссылаюсь на userData secondScene, добавив объект, который является моим счетом . Для тестовой цели это всего 6. Я добавлю переменную экземпляра score. Вы можете добавить то, что вы хотите, так как он принимает объекты типа "id". Ключ очень важен. Вы будете использовать его в secondScene.m для доступа к значению объекта since. Убедитесь, что вы не напечатали его неправильно.
[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 является моим вторым. Я создал его в Xcode с "File-New File ... as: SKScene . Он будет содержать пользовательские данные ниже.
2.2. secondScene
//secondScene.m ( ex. in my :"@implementation WBMGameEndsScene")
эти следующие строки кода проверяют, правильно ли добавлено значение:
-(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"]);
}
выход консоли:
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
если я что-то не так, пожалуйста, исправьте меня :). Технические характеристики: iOS 7.0, Xcode версии 5.1 (5B130a), OS X 10.9.2
где / как вы переходите между сценами? Если бы вы могли показать только код, в котором вы создаете свою новую сцену, это помогло бы. Возможно, я упускаю суть вопроса, но если у вас есть "менеджер сцены" /навигатор, чтобы сделать это, просто сохраните счет в локальном var временно и передайте это в свою новую сцену.
в документации Apple указано, что userData-это способ хранения данных узла здесь в Лучшие Практики Sprite Kit
использовать userData свойство на узлах для хранения игровых данных, особенно если вы не реализуете свои собственные подклассы.
поэтому я бы принял ответ @doctorBroctor как правильный для использования Sprite Kit изначально.
, ты должен помнить инициализируйте userData для целевого узла перед установкой значения, как @LearnCocos2d указывает в этой ответ. Вы можете сделать это внутри метода initWithSize: подкласса SKScene, в который вы собираетесь перейти. // First Scene
NSUserDefaults.standardUserDefaults().setInteger(12345, forKey:"SCORE")
// Second Scene
if let myScore: AnyObject = NSUserDefaults.standardUserDefaults().objectForKey("SCORE") {
println(myScore)
finalScore = myScore as IntegerLiteralType
}