Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set up game loop in Swift

Tags:

ios

swift

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.

like image 543
matsmats Avatar asked Jun 08 '14 06:06

matsmats


People also ask

How do loops work in Swift?

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 .

Can you code games with Swift?

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.

What is the basic structure of a game loop?

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.


3 Answers

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)
like image 120
Brian Tracy Avatar answered Oct 04 '22 04:10

Brian Tracy


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.

like image 42
Nikolay Suvandzhiev Avatar answered Oct 04 '22 03:10

Nikolay Suvandzhiev


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.

like image 23
Dan Rosenstark Avatar answered Oct 04 '22 02:10

Dan Rosenstark