在至少一个同类精灵在舞台上时播放声音循环

Posted

技术标签:

【中文标题】在至少一个同类精灵在舞台上时播放声音循环【英文标题】:Play a sound loop while at least one sprite of its class is on stage 【发布时间】:2016-09-01 09:12:31 【问题描述】:

我正在开发一款游戏,其中有一些不同种类的怪物(一种 = SKSpriteNode 的一个子类)穿过场景。 每一种都被赋予了特定的声音。

一个例子是我可以在特定的时间点拥有:

5个怪物A 2个怪物B 0 怪物 C

我在任何时候都想要为场景(A,B)中的每个班级(而不是每个精灵!)循环播放声音,并停止为缺席的每个班级播放声音场景(C)。

我的第一个想法是将特定的声音存储到每个怪物类中,并为每个精灵添加一个 SKAction,以循环播放其类的声音。 但这会在场景中循环播放与精灵一样多的声音,这与我的预期不符。

您对为此采用的最佳方法有什么想法吗? 是否有可能实现一种观察者,它能够通知类的实例何时在场景中,何时不在?

非常感谢您的帮助!

【问题讨论】:

你的声音是SKAction吗?如果是,则为每个类使用一个“静态函数 = ...”来使用一次 谢谢西蒙娜。是的,它是一个 SKAction。根据您的提议,即使我使用了一次该函数,我也需要知道何时启动声音循环以及何时停止它(根据至少一个类实例的存在与否)。 @LaurentMaquet 您能否指定您的项目中的 ios 最小兼容性是什么?是 iOS 8.x 吗? 我什至不会去静态函数,创建一个包含怪物类型的父节点,并从父节点播放声音 当然SKAction不是为播放循环音乐而设计的,你应该使用AVFoundation,或者如果>= 9.0 SKAudioNode 【参考方案1】:

正如@Knight0fDragon 所说,“SKAction 不是为播放循环音乐而设计的”

也许你可以这样做:(我没有测试它,现在我在windows机器上)

Class MonsterA : SKSpriteNode 

    static var monsterAInScene = Set<Monster>()
    static let audioAction: SKAction = SKAction.playSoundFileNamed("MonsterA-audio") //Change to AVAudio for loop
    static let audioNode: SKNode()

    init (scene:SKScene) 
          //Your init
          if let MonsterA.monsterAInScene.count == 0 
             //play audio
             scene.addChild(MonsterA.audioNode)
             MonsterA.playAudio()
          

          MonsterA.monsterAInScene.insert(self)
    

    static func playAudio() 
         //Play audio code
         if MonsterA.audioNode.actionFroKey("audio") != nil return
         MonsterA.audioNode.runaction(MonsterA.audioAction, forKey "audio")

    
    override removeFromParent() 
        MonsterA.monsterAInScene.remove(self)
        if let MonsterA.monsterAInScene.count == 0 
            //stop audio code
            MonsterA.audioNode.removeActionWithKey("audio")
            MonsterA.audioNode.removeFromParent()
        
        super.removeFromParent()
    

@Knight0fDragon 和@Alessandro Ornano 比我更专业,他们可以建议是否是最好的方法。

【讨论】:

我们与 Knight0fDragon 就音频进行了交谈。你可以在这里找到它:***.com/a/38408288/1894067。恕我直言,AVAudioFoundation 仍然可以为游戏带来很多好处,但如果您的项目开始使用 iOS 9.x 版本,我更喜欢使用,与 Knight0fDragon SKAudioNode 一致。但我从未尝试过通过 SKAction 循环播放音乐。 我做了一个自定义类 SKAudio,当应用程序从非活动状态变为活动状态时,SKAudioNode 仍然崩溃,SKAudioNode 上的暂停似乎有一个错误。 link @SimonePistecchia 啊哈是你的问题吗? SKNode 的暂停从 iOS 9 开始中断(由于某种原因,它改变了所有子节点的暂停状态)您需要做的是扩展所有可能的 SKNode 子类,然后覆盖暂停,记住子节点的暂停状态,更改暂停,然后重置子项的暂停状态。实施起来真的很痛苦。此外,您不能使用 SKNode,您需要子类化一个特殊版本来处理暂停(除非有人可以告诉我如何覆盖 SKNode 上的暂停) @All 感谢您的时间和想法。我现在正在努力! @Knight0fDragon 感谢您的技巧。但是此时最好使用 AVAudio 而不是子类化我的所有节点,对吗?【参考方案2】:

我终于按照 KnightOfDragon 的建议采用了 SKAudioNode。

在 GameScene 类的开头,我添加了一个观察者来检查每种怪物的实际数量(这里是种类 A):

var monsterASound = SKAudioNode()

var currentNumberOfMonsterA = 0 
    didSet 
        if currentNumberOfMonsterA > 0 
            monsterASound.runAction(SKAction.play())
         else
            monsterASound.runAction(SKAction.stop())
        
    

currentNumberOfMonsterA 每次添加/移除怪物时都会更新

//Add a monster A
self.currentNumberOfMonsterA += 1

//Removing a monster A
self.currentNumberOfMonsterA -= 1

//Destroying a monster A
self.currentNumberOfMonsterA -= 1

然后在 didMoveToView 中,我已将 SKAudioNode 添加到场景中

self.monsterASound = SKAudioNode(URL: NSBundle.mainBundle().URLForResource("monsterA", withExtension: "wav")!)
self.monsterASound.runAction(SKAction.stop())
addChild(helicoSound)

【讨论】:

以上是关于在至少一个同类精灵在舞台上时播放声音循环的主要内容,如果未能解决你的问题,请参考以下文章

如何在Android中无间隙地循环播放声音?

如何通过暂停前一个实例再次播放相同的声音?

ROBLOX 中本地玩家的声音脚本

Android声音播放延迟到while循环结束

播放任何声音文件(或至少是常见的音频文件)

为啥我的 Java 应用程序没有在每个循环中播放声音?