SKSpriteNode 从场景中移除后如何停止音频(Swift)?

Posted

技术标签:

【中文标题】SKSpriteNode 从场景中移除后如何停止音频(Swift)?【英文标题】:How to stop an audio of SKSpriteNode after its removed from the scene(Swift)? 【发布时间】:2016-03-28 19:45:45 【问题描述】:

这是我的代码:

 override func didMoveToView(view: SKView) 
    /* Setup your scene here */
    let backgroundImage = SKSpriteNode(imageNamed: "Background.jpeg")
    backgroundImage.size = self.frame.size
    backgroundImage.position = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
    backgroundImage.zPosition = 1
    self.addChild(backgroundImage)


    let addBugAction = SKAction.sequence([SKAction.runBlock(
        self.addBugsToScene()
    ), SKAction.waitForDuration(1)])
    self.runAction(SKAction.repeatActionForever(addBugAction))



func addBugsToScene() 

    let bug = SKSpriteNode(imageNamed: "Mos2.gif")
    bug.name = "Mosquito"


    //giving random position to and assigning to bugs
    let randomPoint = gettingRandomPosition(bug.size)
    bug.position = CGPoint(x: randomPoint.x, y: randomPoint.y)
    bug.zPosition = 12



    let blockOFaction = SKAction.runBlock(

        let randomMovingPoint = self.gettingRandomPosition(bug.size)

         let action = SKAction.moveTo(CGPoint(x: randomMovingPoint.x, y: randomMovingPoint.y), duration: 2)

        //action.speed = 3.0
        let movePlusSoundAction = SKAction.group([action,SKAction.playSoundFileNamed("MosquitoNoise.wav", waitForCompletion: false)])

        bug.runAction(movePlusSoundAction)

    )
    let waitAction = SKAction.waitForDuration(1)
    bug.runAction(SKAction.repeatActionForever(SKAction.sequence([blockOFaction, waitAction])))


    self.addChild(bug)





override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
            

   /* Called when a touch begins */

    for touch in touches 
        let location = touch.locationInNode(self)

        let touchedNode = self.nodeAtPoint(location)

        if touchedNode.name == "Mosquito"

            touchedNode.removeAllActions()

            //touchNode.runAction(SKAction.Stop())

            //removing the bug which is tapped
            touchedNode.removeFromParent()
        
    

当我触摸节点(bug)时,它将从场景中移除。在这里,我试图停止播放与该错误相关的音频。但即使从场景中移除节点后,音频也会继续播放。如何在节点从场景中移除后立即停止音频?

【问题讨论】:

顺便说一句,像在闭包中那样使用 self 并永远重复该动作,肯定会使您的场景无法正确取消初始化。要么使用捕获列表(类似于 [unowned self] ),要么在实际过渡到下一个场景之前删除该动作。始终检查您的场景的 deinit 是否被正确调用(对您创建的每个自定义类执行此操作)。 @Whirlwind 我对此一无所知.. 但会对其进行研究并将实施。再次感谢您帮助我改进代码。 【参考方案1】:

+ playSoundFileNamed:waitForCompletion: 只是播放声音。您无法控制正在播放的声音(无法暂停、取消暂停、停止等)。有人说您可以为声音动作分配一个键,然后通过移除该键来停止一个动作。到目前为止,这对我来说从来没有用过(在许多 ios 版本上都试过)。

另外,我用操作键尝试这个技巧的最后一个 iOS 版本是 9.1...所以,有机会你可以在 9.3 上尝试...

无论如何,这是来自文档:

使用 SKAction playSoundFileNamed:waitForCompletion: 仅作简称 杂费。使用 AVAudioPlayer 播放长时间运行的背景音乐。这 动作不可逆;反向动作与 原创动作。

所以,它只是播放简短的声音,仅此而已。

作为替代方案,您可以使用SKAudioNode,但它仅适用于 iOS9 及更高版本。

【讨论】:

我使用 SKAudioNode 实现了,现在它工作正常。谢谢!【参考方案2】:

这是我如何编码以获得结果。

我在 addBugToScene() 中添加了下面的代码

let mosquitoNoise = SKAudioNode(fileNamed: "MosquitoNoise.wav")
    mosquitoNoise.autoplayLooped = true
    mosquitoNoise.runAction(SKAction.changeVolumeTo(0.3, duration: 60))
    bug.addChild(mosquitoNoise)

//changes made here
 let movePlusSoundAction = SKAction.group([action,SKAction.runBlock(

            mosquitoNoise.runAction(SKAction.play())
            )])

        bug.runAction(movePlusSoundAction)

    )


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

    for touch in touches 
        let location = touch.locationInNode(self)

        let touchedNode = self.nodeAtPoint(location)

        if touchedNode.name == "Mosquito"

            //removes the SKAudioNode so audio will stop
            touchedNode.removeAllChildren()

            //removing the bug which is tapped
            touchedNode.removeFromParent()

        

【讨论】:

以上是关于SKSpriteNode 从场景中移除后如何停止音频(Swift)?的主要内容,如果未能解决你的问题,请参考以下文章

CALayer 帧值即使在从超级层中移除后也会导致动画

为啥元素从 DOM 中移除后仍可访问?

modalViewController 从 superview 中移除后 UIView 消失

Xcode 如何自动从其父节点中删除 skspritenode

在 KineticJS 中移除舞台

如何从 ScrollView 内的 RecyclerView 中移除焦点?