To set up a game loop in Objective-C I learnt that I should set up a CADisplayLink
updater = [CADisplayLink displayLinkWithTarget:self selector:@selector(gameLoop) ];
[updater setFrameInterval: 1];
[updater addToRunLoop: [NSRunLoop currentRunLoop] forMode: NSRunLoopCommonModes];
How do I do this in Swift?
I have tried to Google this but I cannot find any examples of this.
Swift for-in Loop In Swift, the for-in loop is used to run a block of code for a certain number of times. It is used to iterate over any sequences such as an array, range, string, etc. Here, val accesses each item of sequence on each iteration. Loop continues until we reach the last item in the sequence .
Swift is the perfect choice for game development. Developers are intrigued by Swift and want to make use of new features to develop their best games yet. Packed with best practices and easy-to-use examples, this book leads you step by step through the development of your first Swift game.
The game structure The game loop is a sequence of processes that run continuously as long as the game is running. The three main processes that occur in the game loop are input, update, and render. The input process is how the player controls the game.
Pretty much just a direct translation from Objective-C to Swift with a few tweaks.
import QuartzCore
var updater = CADisplayLink(target: self, selector: Selector("gameLoop"))
updater.frameInterval = 1
updater.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)
Swift 3.x version of Brian Tracy's answer:
let updater = CADisplayLink(target: self, selector: #selector(self.gameLoop))
updater.preferredFramesPerSecond = 60
updater.add(to: RunLoop.current, forMode: RunLoopMode.commonModes)
Apart from the syntax changes of Swift 3, also note the iOS 10 API change from frameInterval
(which still works, but produces a deprecated warning) to preferredFramesPerSecond
.
Here's my GameLoop
class (Swift 3)
import UIKit
class GameLoop : NSObject {
var doSomething: () -> ()!
var displayLink : CADisplayLink!
init(doSomething: @escaping () -> ()) {
self.doSomething = doSomething
super.init()
start()
}
// you could overwrite this too
func handleTimer() {
doSomething()
}
func start() {
displayLink = CADisplayLink(target: self, selector: #selector(handleTimer))
/*
* If set to zero, the
* display link will fire at the native cadence of the display hardware.
* The display link will make a best-effort attempt at issuing callbacks
* at the requested rate.
*/
displayLink.preferredFramesPerSecond = 0
displayLink.add(to: .main, forMode: .commonModes)
}
func stop() {
displayLink.invalidate()
displayLink.remove(from: .main, forMode: .commonModes)
displayLink = nil
}
}
If you're updating something on a background GCD queue and want to pull those changes to the Main queue (and runloop), you should use Dispatch Source for Data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With