2

Mon jeu Swift utilise SpriteKit et SKPhysics pour animer une petite boule rouge qui entre souvent en collision avec d'autres physicsBodys au cours de la partie. Je veux créer un effet sonore de rebond naturel lorsque la balle entre en collision. J'ai actuellement une méthode assez désordonnée pour ce faire, et il y a un décalage important notable tout en employant ce qui disparaît quand désactiver les sons:Créer des effets sonores pour rebondir une balle dans 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") 
    } 
    } 
} 

Cela crée trois AVAudioPlayers avec son « Bounce.mp3 » et exécute le prepareToPlay () méthode sur eux. Ensuite, il les stocke dans un tableau appelé bounceSoundPlayers afin que je puisse les utiliser plus tard. Ensuite, j'ai une méthode didBeginContact qui est appelée chaque fois que quelque chose entre en collision avec quoi que ce soit:

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

Fondamentalement, ce que cette méthode n'est-il vérifie chaque collision, et si le ballon entre en collision avec le bon type de plate-forme ou d'un mur, il appelle la méthode playBounceSound (volume: CGFloat) avec un volume proportionnel à la force de la collision. Donc, si la balle entre légèrement en collision avec une plate-forme, le volume est plus silencieux que s'il s'agit d'une collision très forte. Voici la méthode 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} 
} 

Fondamentalement, ce que cette méthode fait est cycles à travers les trois AVAudioPlayers nous avons créé précédemment en utilisant un nombre entier d'index. Chaque fois qu'il est appelé, il indique à bouncePlayerIndex la fonction bounceSoundPlayer à jouer() sur le volume donné. Ensuite, il incrémente bouncePlayerIndex pour que la prochaine fois qu'il est appelé, il utilise un AVAudioPlayer différent. Si bouncePlayerIndex> 2, il revient à 0. L'utilisation de trois AVAudioPlayers me permet de jouer plusieurs rebonds simultanés - par exemple, un son rebond peut commencer avant la fin du dernier, comme quand la balle tombe sur une plate-forme et rebondit plus bas et plus fréquemment, jusqu'à ce qu'il cesse de rebondir.

Je suis sûr qu'il y a une meilleure façon de le faire qu'avec un tableau de AVAudioPlayers. S'il vous plaît aider.

+0

avez-vous vu ceci: http://largepixels.net/post/1020? – Confused

Répondre

0

Swift 3

C'est la meilleure façon que je l'ai trouvé à jouer des sons. Ils peuvent se chevaucher et vous pouvez en jouer autant que vous le souhaitez en même temps. Rapide et simple.

1.) Assurez-vous que vous importez le cadre

import AVFoundation 

2.) Créer la fonction

// 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.) Appelez la fonction où vous en avez besoin avec

shatterSound()