1

I am trying to increase the difficulty of my game by increasing the gravity as the player's score goes up. I am not exactly sure how to implement that and as I tried using the solution here: Any way to speed up gameplay gradually in Swift?

However, I am not sure how to implement it into my game so that it gradually increases gravity

Here's my code:

override func update(_ currentTime: TimeInterval) {
    // Altered the gravity drastically
    // self.physicsWorld.gravity = CGVector(dx: 0, dy: CGFloat(self.score))
}

3 Answers3

1

Schedule Timer and increase gravity periodically like this

override func didMove(to view: SKView) {

    let increasingDifficultyPeriod = TimeInterval(60)

    Timer.scheduledTimer(withTimeInterval: increasingDifficultyPeriod,
                         repeats: true)
    { _ in
        // increase currentGravity property here
        self.physicsWorld.gravity.dy -= CGFloat(0.1)
    } 
}
Yakiv Kovalskyi
  • 1,737
  • 1
  • 15
  • 29
  • can you explain to me what's going on in the { _ in }? Or maybe a pointer to where I can look up to understand that part of the code? Sorry I am new to swift – porkchopbento Jan 17 '18 at 00:47
  • It's a block which is executed everytime the timer fires (in this case every 60 seconds). This is called a closure and you can read more about this [here](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html). Nevertheless you should use `SKAction` instead of `Timer` for those things, like @Whirlwind mentioned in his answer. – Marcel Jan 17 '18 at 02:08
1

I would stay away from Timer here because of a few reasons... What happens with that solution if the game is paused (eg scene or view is paused)? Will timer continue running when different interruptions occur (eg phone call, or having app going into background from whatever reason...). Will this timer pause automatically in those cases, and will it unpause (also automatically) when app returns to the foreground?

The short answer is : "Just stay away from it and use SKAction :)"

The long answer is:

The timer will not pause / unpause automatically. It is not paired with a game loop like SKAction. When user returns to the game, instead of having a gravity like it was before the interruption, the gravity will have unexpected value which will likely make some mess in your game. So, as I mentioned, you need a custom pause feature for a Timer class to handle these situations. But, unlike in the case of Timer class, all of this is handled with SKActions automatically.

You can use update method as well, but I prefer actions, so here is how you can do it with actions:

import SpriteKit
import GameplayKit

class GameScene: SKScene {

    let kStep:CGFloat = 0.01
    let kIncreaseActionKey = "kIncreaseActionkey"

    override func sceneDidLoad() {

        let increase = SKAction.run {[unowned self] in

            //Optionally, you can check here if you want to increase the gravity further
            self.physicsWorld.gravity.dy -= self.kStep
            print("Gravity is now \(self.physicsWorld.gravity)")
        }

        let wait = SKAction.wait(forDuration: 1)//wait one second before increasing gravity

        let sequence = SKAction.sequence([wait, increase])
        let loop = SKAction.repeatForever(sequence)
        self.run(loop, withKey: kIncreaseActionKey)
    }

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

        if self.action(forKey: kIncreaseActionKey) != nil{
            self.removeAction(forKey: kIncreaseActionKey)
        }
    }
}
Whirlwind
  • 14,286
  • 11
  • 68
  • 157
0

Why not changing the gravity at the same time the score changes? Best is to compute the new gravity value when the score changes and assign it to the world in didFinishUpdate.

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69