5

I am developing a game where the main sprite is a spinning wheel. I would like to associate audio to the spinning wheel that changes pitch as the wheel slows down. When the wheel stops spinning I would like the sound effect to stop. Can someone point me in the right direction?

In my game scene I have the following code:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    for touch in touches {
        let location = touch.location(in: self)
        //Start spinning the wheel
        if atPoint(location).name == "play_button" {
            player?.physicsBody?.angularVelocity = 0
            player?.rotatePlayer()

            //Click back button
        } else if atPoint(location).name == "back_button" {
            let play_scene = CharacterSelectScene(fileNamed: "CharacterSelect")
            play_scene?.scaleMode = .aspectFill
            self.view?.presentScene(play_scene!, transition: SKTransition.doorsOpenVertical(withDuration: 1))
        } else if atPoint(location).name == "settings_button" {
            let play_scene = SettingsScene(fileNamed: "SettingsScene")
            play_scene?.scaleMode = .aspectFill
            self.view?.presentScene(play_scene!, transition: SKTransition.doorsOpenVertical(withDuration: 1))
        }
    }
}

override func didSimulatePhysics() {
    let speed = player?.physicsBody?.angularVelocity
    if (speed != CGFloat(0.0)) {
        if (speed! <= CGFloat(0.1)){
            finishedRotation = true
        }
    }
}
override func didFinishUpdate() {
    if (finishedRotation == true) {
        let play_scene = QuestionScene(fileNamed: "QuestionScene")
        play_scene?.scaleMode = .aspectFill
        self.view?.presentScene(play_scene!, transition: SKTransition.doorsOpenVertical(withDuration: 1))
    }
}
func didBegin(_ contact: SKPhysicsContact) {
    let defaults = UserDefaults.standard
    var firstBody = SKPhysicsBody()
    var secondBody = SKPhysicsBody()
    if (contact.bodyA.node?.name == "pin") {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }
    if (firstBody.node?.name == "pin" && secondBody.node?.name == "geography") {
        let set_topic = secondBody.node?.name
        defaults.set(set_topic, forKey: "Topic")
    } else if (firstBody.node?.name == "pin" && secondBody.node?.name == "maths") {
        let set_topic = secondBody.node?.name
        defaults.set(set_topic, forKey: "Topic")
    } else if (firstBody.node?.name == "pin" && secondBody.node?.name == "history") {
        let set_topic = secondBody.node?.name
        defaults.set(set_topic, forKey: "Topic")
    } else if (firstBody.node?.name == "pin" && secondBody.node?.name == "science") {
        let set_topic = secondBody.node?.name
        defaults.set(set_topic, forKey: "Topic")
    }
}

The rotatePlayer method from the Player class is defined as below:

func rotatePlayer() {
    let random = GKRandomDistribution(lowestValue: 20, highestValue: 120)
    let r = random.nextInt()
    self.physicsBody?.angularVelocity = 0
    self.physicsBody?.angularVelocity = CGFloat(r)
    self.physicsBody?.angularDamping = 1.02

}
Nick
  • 555
  • 2
  • 4
  • 13
  • What does the Xcode documentation tell you about the rate property of AVAudioPlayer? – El Tomato Jun 04 '17 at 04:29
  • the documentation does not state much other than default rate and enabling the rate. How can I tie the rate into the speed of the spinning wheel to make it sound realistic? – Nick Jun 04 '17 at 04:32
  • Your question is breaking the rules of Stackoverflow because of a few things. 1) Lacks with info (eg. we don't know how your wheel works, so we can't say for sure how to map rate/pitch with a spinning speed), 2) What have you tried so far ? People eager to help can help, but nobody wants to write a complete solutions... Well, it happens, but still, that is not how this site is meant to work ;) Please see how to [ask a good question](https://stackoverflow.com/help/how-to-ask) – Whirlwind Jun 04 '17 at 14:09
  • About the pitch : https://developer.apple.com/reference/avfoundation/avaudiounittimepitch but that might not be what you are up to. As I said, you have to provide a lot of more info. Ideally, you provide MVP that can reproduce the issue. – Whirlwind Jun 04 '17 at 14:13
  • Thanks whirlwind. I will provide more detail shortly – Nick Jun 05 '17 at 03:15
  • As an aside, would it be better if your `random` variable in `rotatePlayer` function was `static`? Otherwise the `nextInt()` call simply returns the first int of a freshly created `GKRandomDistribution`. – mogelbuster Jun 08 '17 at 17:12

1 Answers1

2

I have resolved the issue and the code is listed below:

func playSound() {
    let url = Bundle.main.url(forResource: "clicker", withExtension: "m4a")!

    do {
        SoundEffect = try AVAudioPlayer(contentsOf: url)
        guard let players = SoundEffect else { return }

        players.prepareToPlay()
        players.play()
    } catch let error as NSError {
        print(error.description)
    }
}
func didEnd(_ contact: SKPhysicsContact) {

    let defaults = UserDefaults.standard
    var firstBody = SKPhysicsBody()
    var secondBody = SKPhysicsBody()
    if (contact.bodyA.node?.name == "pin") {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }
    if (firstBody.node?.name == "pin" && secondBody.node?.name == "geography") {
        let set_topic = secondBody.node?.name
        defaults.set(set_topic, forKey: "Topic")
        playSound()
    } else if (firstBody.node?.name == "pin" && secondBody.node?.name == "maths") {
        let set_topic = secondBody.node?.name
        defaults.set(set_topic, forKey: "Topic")
        playSound()
    } else if (firstBody.node?.name == "pin" && secondBody.node?.name == "history") {
        let set_topic = secondBody.node?.name
        defaults.set(set_topic, forKey: "Topic")
        playSound()
    } else if (firstBody.node?.name == "pin" && secondBody.node?.name == "science") {
        let set_topic = secondBody.node?.name
        defaults.set(set_topic, forKey: "Topic")
        playSound()
    }
}
Nick
  • 555
  • 2
  • 4
  • 13
  • This is however causing significant lag and freezing the game. Both on device and in simulator. – Nick Jun 08 '17 at 07:44
  • not sure what is causing the lag. Perhaps you are getting multiple calls of `didEnd` when you really only want 1. You can try setting a custom flag to skip `didEnd` until the next frame after it goes off once... see if that works. – Fluidity Jun 11 '17 at 16:30