Swift Spritekit:背景音乐没有播放

时间:2016-08-26 16:37:34

标签: swift background sprite-kit

我有两个场景,我希望背景音乐同时播放。问题是音乐仅在应用程序首次打开时播放。如果我按下按钮转到第二个场景,音乐在场景转换时播放,但在转换结束时停止。第二个场景没有音乐,如果我回到第一个场景那里也没有音乐。 音乐总是在场景之间的过渡期间播放(这就是为什么我使用了很长的过渡时间,只是为了确认(我不知道为什么)。

class GameScene: SKScene {

var backgroundMusic: SKAudioNode!

// # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # #



override func didMoveToView(view: SKView) {
    /* Setup your scene here */

    backgroundColor = SKColor.redColor()

    global.centerPoint = CGPoint(x:(CGRectGetMidX(self.frame)), y:(CGRectGetMidY(self.frame)))



    let myLabel = SKLabelNode(fontNamed:"Helvetica Bold")
    myLabel.text = "GameScene"
    myLabel.fontSize = 45
    myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) + 100)

    self.addChild(myLabel)

    createBtn()


    // # # # # # # # # # # # # # # # # # # # # # # # # # # #

    // MUSICA
    if let musicURL = NSBundle.mainBundle().URLForResource("music", withExtension: "wav") {

        backgroundMusic = SKAudioNode(URL: musicURL)

        addChild(backgroundMusic)

        print("backgroundMusic OK")

    } else {

        print("backgroundMusic file not found!")
    }



} // END override func didMoveToView



// # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # #

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    /* Called when a touch begins */

    let touch = touches //as!  Set<UITouch>
    let location = touch.first!.locationInNode(self)
    let node = self.nodeAtPoint(location)


    if (node.name == "btnOne") {

        let reveal = SKTransition.pushWithDirection(.Left, duration: 2.5)
        let scene = SceneTwo(size: size)
        self.view?.presentScene(scene, transition:reveal)


    }


} // END override func touchesBegan

对于第二个文件/场景,我使用相同的代码:

class SceneTwo: SKScene {

var backgroundMusicTwo: SKAudioNode!

// # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # #
// # # # # # # # # # # # # # # # # # # # # # # # # # # #



override func didMoveToView(view: SKView) {
    /* Setup your scene here */

    backgroundColor = SKColor.blueColor()

    global.centerPoint = CGPoint(x:(CGRectGetMidX(self.frame)), y:(CGRectGetMidY(self.frame)))



    let myLabel = SKLabelNode(fontNamed:"Helvetica Bold")
    myLabel.text = "SceneTwo"
    myLabel.fontSize = 45
    myLabel.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) + 100)

    self.addChild(myLabel)

    createBtn()

    // # # # # # # # # # # # # # # # # # # # # # # # # # # #

    // MUSICA
    if let musicURL = NSBundle.mainBundle().URLForResource("music", withExtension: "wav") {

        backgroundMusicTwo = SKAudioNode(URL: musicURL)

        addChild(backgroundMusicTwo)

        print("backgroundMusicTwo OK")

    } else {

        print("backgroundMusicTwo file not found!")
    }



} // END override func didMoveToView

2 个答案:

答案 0 :(得分:2)

我认为它不会播放的原因是因为一旦场景改变,音频节点将被释放。我不确定为什么它只在转换之间进行。我也从未使用过音频节点,但我确实创建了自己的自定义类来处理所有音频。

另外,我不会复制和粘贴代码。当你只有一个类来处理音频时,你在两个场景中都有相同的代码。这是一个使用我制作的名为JKAudioPlayer的自定义类的解决方案。只需创建一个新的Swift类并将代码粘贴到其中。由于稍后声明的音频对象不是场景的一部分,因此在转换时它将继续/允许播放音乐。

import Foundation
import SpriteKit
import AVFoundation
import AVFoundation.AVAudioSession

/**Manages a shared instance of JKAudioPlayer.*/
private let JKAudioInstance = JKAudioPlayer()

/**Provides an easy way to play sounds and music. Use sharedInstance method to access a single object for the entire game to manage the sound and music.*/
public class JKAudioPlayer {

    /**Used to access music.*/
    var musicPlayer: AVAudioPlayer!

    /** Allows the audio to be shared with other music (such as music being played from your music app). If this setting is false, music you play from your music player will stop when this app's music starts. Default set by Apple is false. */
    static var canShareAudio = false {
        didSet {
            canShareAudio ? try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient) : try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
        }
    }

    /**Creates an instance of the JAAudio class so the user doesn't have to make their own instance and allows use of the functions. */
    public class func sharedInstance() -> JKAudioPlayer {
        return JKAudioInstance
    }

/**Plays music. You can ignore the "type" property if you include the full name with extension in the "filename" property. Set "canShareAudio" to true if you want other music to be able to play at the same time (default by Apple is false).*/
    public func playMusic(fileName: String, withExtension type: String = "") {
        if let url = NSBundle.mainBundle().URLForResource(fileName, withExtension: type) {
            musicPlayer = try? AVAudioPlayer(contentsOfURL: url)
            musicPlayer.numberOfLoops = -1
            musicPlayer.prepareToPlay()
            musicPlayer.play()
        }
    }

    /**Stops the music. Use the "resumeMusic" method to turn it back on. */
    public func stopMusic() {
        if musicPlayer != nil && musicPlayer!.playing {
            musicPlayer.currentTime = 0
            musicPlayer.stop()
        }
    }

    /**Pauses the music. Use the "resumeMusic" method to turn it back on. */
    public func pauseMusic() {
        if musicPlayer != nil && musicPlayer!.playing {
            musicPlayer.pause()
        }
    }

    /**Resumes the music after being stopped or paused. */
    public func resumeMusic() {
        if musicPlayer != nil && !musicPlayer!.playing {
            musicPlayer.play()
        }
    }

    /**Plays a sound only once. Must be used inside a runAction(...) method.*/
    public func playSound(fileName: String) -> SKAction? {
        return SKAction.playSoundFileNamed(fileName, waitForCompletion: false)
    }
}

要使用它,请创建一个可以访问音频的全局变量。

let audio = JKAudioPlayer.sharedInstance()

然后,当您想播放音乐时,可以在场景类的didMoveToView函数中轻松调用它。

audio.playMusic("MusicName")

你也可以通过调用这样的暂停/停止/恢复音乐功能来控制它:

audio.stopMusic()

如果您希望用户能够在后台播放自己的音乐,例如从他们的iTunes资料库中播放他们的音乐,那么您可以在GameViewController的viewDidLoad函数中将canShareAudio设置为true。

audio.canShareAudio = true

答案 1 :(得分:0)

这里是Swift 3测试和工作的代码,您需要将文件的扩展名放在最后,否则无法找到声音文件

在新的Swift文件中复制和粘贴

import Foundation
import SpriteKit
import AVFoundation

    public let audio = JKAudioPlayer.sharedInstance()


    private let JKAudioInstance = JKAudioPlayer()


    public class JKAudioPlayer {


    var musicPlayer: AVAudioPlayer!


    static var canShareAudio = false {
        didSet {
        canShareAudio ? try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient) : try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
        }
    }

    public class func sharedInstance() -> JKAudioPlayer {
        return JKAudioInstance
    }
    public func playMusic(fileName: String, withExtension type: String = "") {
        if let url = Bundle.main.url(forResource: fileName, withExtension: type) {
            musicPlayer = try? AVAudioPlayer(contentsOf: url)
            musicPlayer.numberOfLoops = -1
            musicPlayer.prepareToPlay()
            musicPlayer.play()
        }
    }


    public func stopMusic() {
        if musicPlayer != nil && musicPlayer!.isPlaying {
            musicPlayer.currentTime = 0
            musicPlayer.stop()
        }
    }


    public func pauseMusic() {
        if musicPlayer != nil && musicPlayer!.isPlaying {
            musicPlayer.pause()
        }
    }

    public func resumeMusic() {
        if musicPlayer != nil && !musicPlayer!.isPlaying {
            musicPlayer.play()
        }
    }

    public func playSound(fileName: String) -> SKAction? {
        return SKAction.playSoundFileNamed(fileName, waitForCompletion: false)
    }
}

播放任何文件只需简单地放入

audio.playMusic(fileName: "NameOfFile")

并停止播放您需要停止播放的音乐

audio.stopMusic()