0

My final game over scene has an SKTransition back to the Main Menu. I am able to make a song play for the final game over scene, but I would like the song to continue into my Main Menu.

Here is a copy of the code I have at the moment.

import Foundation
import SpriteKit
import AVFoundation


class SceneThree: SKScene {

   var game = SKSpriteNode()

var new: AVAudioPlayer?

override func didMove(to view: SKView) {

    self.backgroundColor = SKColor.black

    playSound()

}

func playSound() {
    let url = Bundle.main.url(forResource: "new", withExtension: "caf")!

    do {
        new = try AVAudioPlayer(contentsOf: url)
        guard let new = new else { return }

        new.prepareToPlay()
        new.play()
    } catch let error {
        print(error.localizedDescription)
    }
}



override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    let gameScene = GameScene(fileNamed: "GameScene")
    gameScene?.scaleMode = .aspectFill
    self.view?.presentScene(gameScene!, transition: SKTransition.fade(withDuration: 4.5))



}
niX
  • 167
  • 8
  • Probably you should try to do it via NSNotificationCenter? – Bohdan Savych Dec 08 '16 at 08:53
  • Im really new to swift! can i add that in to this code? or will i have to redo this code. @BohdanSavych – niX Dec 08 '16 at 13:30
  • your AVAudioPlayer belongs to the scene, so when the scene is transitioned from and destroyed the audio player will be cleaned up too. Try putting the audio player a level up in your view controller – Weyland Yutani Dec 08 '16 at 16:33
  • This is a duplicate question of this one basically. Have a look there for your answer. This will allow you to play music in all scenes. http://stackoverflow.com/questions/40296793/cannot-stop-background-music-from-within-game-scenes-swift-3-spritekit/40361443#40361443 – crashoverride777 Dec 09 '16 at 19:01

1 Answers1

0

When you change scene the old one will get destroyed, which includes your AVPlayer property.

You can create a helper class for your music to avoid this.

class MusicManager {

    static let shared = MusicManager()

    var audioPlayer = AVAudioPlayer()


    private init() { } // private singleton init


    func setup() {
         do {
            audioPlayer =  try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "music", ofType: "mp3")!))
             audioPlayer.prepareToPlay()

        } catch {
           print (error)
        }
    }


    func play() {
        audioPlayer.play()
    }

    func stop() {
        audioPlayer.stop()
        audioPlayer.currentTime = 0 // I usually reset the song when I stop it. To pause it create another method and call the pause() method on the audioPlayer.
        audioPlayer.prepareToPlay()
    }
}

When your project launches just call the setup method

MusicManager.shared.setup()

Than from any where in your project you can say

MusicManager.shared.play()

to play the music.

To than stop it just call the stop method

MusicManager.shared.stop()

For a more feature rich example with multiple tracks check out my helper on GitHub

https://github.com/crashoverride777/SwiftyMusic

Hope this helps

crashoverride777
  • 10,581
  • 2
  • 32
  • 56
  • Hi @crashoverride777 thanks for your in detailed answer! I am new to programming. Correct me if this is right. I have added a new swift file to my project, added the class MusicManager and all of what you have in the first segment of code. Then in the scene I want the music to begin playing I have added MusicManager.shared.setup() in didMove(to view...) and MusicManager.shared.play()? – niX Dec 10 '16 at 06:17
  • I would add the setup method in app delegate didFinishLaunching method or your game view controller viewDidLoad so it get called as soon as your app launches. Than just call the play method when you want to play, e.g in your scene. Keep me posted – crashoverride777 Dec 10 '16 at 09:46