如何在Swift中设置游戏循环?

时间:2022-06-28 02:49:17

To set up a game loop in Objective-C I learnt that I should set up a CADisplayLink

为了在Objective-C中建立一个游戏循环,我知道我应该建立一个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.

我试过这个但找不到任何例子。

3 个解决方案

#1


24  

Pretty much just a direct translation from Objective-C to Swift with a few tweaks.

这只是从Objective-C到Swift的直接翻译。

import QuartzCore
var updater = CADisplayLink(target: self, selector: Selector("gameLoop"))
updater.frameInterval = 1
updater.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)

#2


6  

Swift 3.x version of Brian Tracy's answer:

斯威夫特3。布莱恩·特雷西的回答有x种版本:

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.

除了Swift 3的语法更改外,还要注意iOS 10 API从frameInterval(仍然有效,但产生了一个不赞成的警告)更改为preferredFramesPerSecond。

#3


5  

Here's my GameLoop class (Swift 3)

这是我的游戏类(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.

如果您正在更新后台GCD队列上的某些内容,并希望将这些更改拉到主队列(和runloop),则应该使用Dispatch Source来获取数据。

#1


24  

Pretty much just a direct translation from Objective-C to Swift with a few tweaks.

这只是从Objective-C到Swift的直接翻译。

import QuartzCore
var updater = CADisplayLink(target: self, selector: Selector("gameLoop"))
updater.frameInterval = 1
updater.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)

#2


6  

Swift 3.x version of Brian Tracy's answer:

斯威夫特3。布莱恩·特雷西的回答有x种版本:

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.

除了Swift 3的语法更改外,还要注意iOS 10 API从frameInterval(仍然有效,但产生了一个不赞成的警告)更改为preferredFramesPerSecond。

#3


5  

Here's my GameLoop class (Swift 3)

这是我的游戏类(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.

如果您正在更新后台GCD队列上的某些内容,并希望将这些更改拉到主队列(和runloop),则应该使用Dispatch Source来获取数据。