2

내 Swift 게임은 SpriteKit 및 SKPhysics를 사용하여 게임 중에 다른 물리학 자와 자주 충돌하는 작은 빨간 공을 움직입니다. 공이 충돌 할 때마다 자연스러운 소리가 나는 바운스 효과음을 내고 싶습니다. 나는 현재이 작업을 수행하는 다소 무질서한 방법이 있고, 거기를 사용하는 동안 상당한 지연 내가 소리를 사용하지 않는 경우 사라집니다 눈에 띄는입니다 :SpriteKit에서 공을 튀는 효과음 만들기

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") 
    } 
    } 
} 

이는 소리 "Bounce.mp3"세 AVAudioPlayers를 생성하고합니다 (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 (볼륨 : CGFloat) 메서드를 호출합니다. 따라서 공이 플랫폼과 가볍게 충돌하면 실제 충돌보다 소리가 작습니다.

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을 통해 사이클입니다 : 여기에 playBounceSound 방법입니다. 호출 될 때마다 주어진 볼륨에서 bouncePlayerIndex의 bounceSoundPlayer에게 play()를 지시합니다. 그런 다음 bouncePlayerIndex를 증가시켜 다음에 호출 할 때 다른 AVAudioPlayer를 사용합니다. bouncePlayerIndex> 2이면 0으로 되돌아갑니다. 3 개의 AVAudioPlayers를 사용하면 여러 개의 바운스를 동시에 재생할 수 있습니다. 즉, 바운스 사운드는 플랫폼에있는 공이 튀고 높이가 올라간 다음 낮아지고 뒤쪽이 튀어 오르는 것처럼 끝날 때까지 시작될 수 있습니다. 낮추고 더 자주, 튀는 것을 멈출 때까지.

AVAudioPlayers 배열보다이 방법이 더 좋습니다. 도와주세요.

+0

당신은 이것을 보았습니까 : http://largepixels.net/post/1020? – Confused

답변

0

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() 
관련 문제