Передача данных между сценами SpriteKit (Swift) - PullRequest
0 голосов
/ 04 октября 2018

Я изучал старый учебник Рэя Вендерлиха: https://www.raywenderlich.com/1514-introduction-to-the-sprite-kit-scene-editor и столкнулся с проблемой.Я неоднократно сталкивался с этой проблемой и даже нашел «решение» на сайте stackoverflow: Передача данных между сценами (SpriteKit)

Это тот же код, что и в руководстве (снесколько твиков, как было написано в Swift 2).Мне кажется, это очень элегантное решение, не полное кода с использованием NSdefaults и т. Д.

Это вызов новой сцены, обратите внимание на объект soundToPlay :

func gameOver(didWin: Bool) {
   let menuScene = MenuScene(size: self.size)
   menuScene.scaleMode = .aspectFill
   menuScene.soundToPlay = didWin ? "fear_win.mp3" : "fear_lose.mp3"
   let transition = SKTransition.flipVertical(withDuration: 1.0)
   self.view?.presentScene(menuScene, transition: transition)
}

И это сцена, которую я называю:

import SpriteKit

class MenuScene: SKScene {

   var soundToPlay: String!

   override func sceneDidLoad() {

      self.backgroundColor = SKColor(red: 0, green:0, blue:0, alpha: 1)

      // Setup label
      let label = SKLabelNode(fontNamed: "AvenirNext-Bold")
      label.text = "Press anywhere to play again!"
      label.fontSize = 55
      label.horizontalAlignmentMode = .center
      label.position = CGPoint(x: self.frame.midX, y: self.frame.midY)

      addChild(label)

      // Play sound
      if let soundToPlay = soundToPlay {
         run(SKAction.playSoundFileNamed(soundToPlay, waitForCompletion: false))
      }
}

Данные никогда не передаются, и объект имеет значение nil

Я подозреваю, что это что-тоэто изменилось в Swift, так как учебник очень старый, как и предлагаемое «решение» по предыдущему stackoverflow вопросу.

Если это так, то какой сейчас лучший способ достичьэто?

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Проблема с вашим звуком заключается в том, что вы устанавливаете переменную после вызова sceneDidLoad (это происходит во время init), поэтому звук не будет воспроизводиться.

Чтобы исправить это, выполните этот код в * 1003.* method:

override func didMove(to view: SKView) {
    guard let soundToPlay = soundToPlay else {fatalError("Unable to find soundToPlay")}
    run(SKAction.playSoundFileNamed(soundToPlay, waitForCompletion: false))

}

Фактическая проблема с вашим сбоем здесь не видна.

SKTransition s прослушиваются при использовании SKLightNode, поэтому при вызове сцены с переходомсобирается разбиться.SKTransition s всегда были прослушаны с введением Metal, поэтому единственное, что вы можете сделать, это сообщить об этом Apple и молиться, чтобы они не сказали вам, что это намеренно.

На данный момент, следите завсех ваших источников света, и при переходе установите для свойства isEnabled значение false.

Возможно, вам потребуется создать снимок экрана вашей сцены до отключения источника света, чтобы он не выглядел глупо.

0 голосов
/ 04 октября 2018

Что вы делаете, когда вы перезагружаете сцену (let menuScene = MenuScene(size: self.size)), вы сбрасываете все переменные, которые были определены.

Что вы можете сделать, это использовать UserDefaults :

func gameOver(didWin: Bool) {
   let menuScene = MenuScene(size: self.size)
   menuScene.scaleMode = .aspectFill
   let soundToPlay = didWin ? "fear_win.mp3" : "fear_lose.mp3"
   UserDefaults.standard.set(soundToPlay, forKey: "soundToPlay")
   let transition = SKTransition.flipVertical(withDuration: 1.0)
   self.view?.presentScene(menuScene, transition: transition)
}

И:

import SpriteKit

class MenuScene: SKScene {
   var soundToPlay: String!
   override func sceneDidLoad() {

      self.backgroundColor = SKColor(red: 0, green:0, blue:0, alpha: 1)

      // Setup label
      let label = SKLabelNode(fontNamed: "AvenirNext-Bold")
      label.text = "Press anywhere to play again!"
      label.fontSize = 55
      label.horizontalAlignmentMode = .center
      label.position = CGPoint(x: self.frame.midX, y: self.frame.midY)

      addChild(label)

      // Play sound
      if let soundToPlay = UserDefaults.standard.string(forKey: "soundToPlay") {
         run(SKAction.playSoundFileNamed(soundToPlay, waitForCompletion: false))
      }
}

Затем вставьте это в функцию applicationWillTerminate вашего AppDelegate:

func applicationWillTerminate(_ application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    UserDefaults.standard.removeObject(forKey: "soundToPlay")
}

Если вы не добавите это в AppDelegate, тогдаsoundToPlay останется после полного закрытия приложения.

Я не знаю, является ли UserDefaults лучшим способом сделать это, но я боролся с этим, когда делал свое приложение iOS, и ятолько что сделал это.Так что, если у кого-то есть лучший ответ, пожалуйста, сообщите мне также!

...