在SpriteKit

时间:2016-11-13 18:05:01

标签: swift sprite-kit avfoundation collision-detection avaudioplayer

My Swift游戏使用SpriteKit和SKPhysics为游戏过程中经常与其他physicsBodys碰撞的小红球制作动画。我想在球碰撞时创造一种自然的声音反弹声音效果。我目前有一个相当混乱的方法来做这个,并且当使用它时显着滞后显着消失当我禁用声音时消失:

var bounceSoundPlayers = [AVAudioPlayer!]()

func buildBounceSound() {
  let path = Bundle.main.path(forResource: "Bounce.mp3", ofType:nil)!
  let url = URL(fileURLWithPath: path)
  for _ in 0...2 {
    do {
      let sound = try AVAudioPlayer(contentsOf: url)
      sound.prepareToPlay()
      bounceSoundPlayers.append(sound)
    } catch {
      fatalError("couldn't load music file")
    }
  }
}

这会创建三个带声音的AVAudioPlayers" Bounce.mp3"并对它们运行prepareToPlay()方法。然后它将它们存储在一个名为bounceSoundPlayers的数组中,以便稍后使用它们。然后我有一个didBeginContact方法,只要有任何东西碰到任何东西就会被调用:

func didBegin(_ contact: SKPhysicsContact) {
  if contact.collisionImpulse > 0.45 && defaults.bool(forKey: "SFX") {
    if ((contact.bodyA.node!.name == "ball" && contact.bodyB.node!.name == "permeable platform") ||
      (contact.bodyB.node!.name == "ball" && contact.bodyA.node!.name == "permeable platform") ||
      (contact.bodyA.node!.name == "ball" && contact.bodyB.node!.name == "ring") ||
      (contact.bodyB.node!.name == "ball" && contact.bodyA.node!.name == "ring"))
      &&
      ball.collidingWithPermeable {
        playBounceSound(contact.collisionImpulse/8<=1 ? contact.collisionImpulse/8 : 1)
    }

    if (contact.bodyA.node!.name == "ball" && contact.bodyB.node!.name == "impermeable platform") ||
      (contact.bodyB.node!.name == "ball" && contact.bodyA.node!.name == "impermeable platform") ||
      (contact.bodyA.node!.name == "ball" && contact.bodyB.node!.name == "wall") ||
      (contact.bodyB.node!.name == "ball" && contact.bodyA.node!.name == "wall") {
      playBounceSound(contact.collisionImpulse/5<=1 ? contact.collisionImpulse/5 : 1)
    }
  }
}

基本上这个方法的作用是检查每次碰撞,如果球与正确类型的平台或墙碰撞,它会调用方法playBounceSound(volume:CGFloat),其体积与碰撞力成正比。因此,如果球轻轻地与平台碰撞,则音量比它真正强烈的碰撞时更安静。这是playBounceSound方法:

var bouncePlayerIndex = Int(0)

func playBounceSound(_ volume: CGFloat) {
  let previousIndex = bouncePlayerIndex - 1 >= 0 ? bouncePlayerIndex - 1 : 2
  if bounceSoundPlayer[previousIndex].isPlaying {
    if bounceSoundPlayer[previousIndex].currentTime > 0.1 {
      bounceSoundPlayer[bouncePlayerIndex].volume = Float(volume)
      bounceSoundPlayer[bouncePlayerIndex].play()
    }
  }
  else {
    bounceSoundPlayer[bouncePlayerIndex].volume = Float(volume)
    bounceSoundPlayer[bouncePlayerIndex].play()
  }

  bouncePlayerIndex += 1
  if bouncePlayerIndex > 2 {bouncePlayerIndex = 0}
}

基本上这个方法的作用是通过使用索引整数循环我们之前创建的三个AVAudioPlayers。每次调用它时,它都会告诉bounceSoundPlayer在给定音量的bouncePlayerIndex播放()。然后它增加bouncePlayerIndex,以便下次调用时,它使用不同的AVAudioPlayer。如果bouncePlayerIndex&gt; 2,它回到0.使用三个AVAudioPlayers允许我同时播放多个弹跳 - 即弹跳声可以在最后一个结束之前开始,例如当球落在平台上并弹跳高,然后降低和降低等等经常,直到它停止弹跳。

我确信这比使用AVAudioPlayers数组更好。请帮忙。

1 个答案:

答案 0 :(得分:0)

Swift 3

这是我发现播放声音的最佳方式。它们可以重叠,您可以同时播放任意数量的内容。快速而简单。

1。)确保导入框架

import AVFoundation

2。)创建功能

// my sound file is named shatter.mp3
func shatterSound() {
    if let soundURL = Bundle.main.url(forResource: "shatter", withExtension: "mp3") {
        var mySound: SystemSoundID = 0
        AudioServicesCreateSystemSoundID(soundURL as CFURL, &mySound)
        AudioServicesPlaySystemSound(mySound);
    }
}

3.使用

调用您需要的功能
shatterSound()