【问题标题】:Swift: NSTimer Alternative斯威夫特:NSTimer 替代品
【发布时间】:2014-12-30 07:40:01
【问题描述】:

我制作了一个飞扬的鸟克隆,但是在尝试实现暂停功能时,我遇到了我的 NSTimer 的问题,它正在生成管道。

var timer = NSTimer.scheduledTimerWithTimeInterval(moveSpeed, target: self, selector: Selector("makePipes"), userInfo: nil, repeats: true)

由于 NSTimers 无法暂停,我在 makePipes() 函数中实现了一个简单的 if 语句,检查游戏是否暂停,如果暂停,则不生成新管道。但是,由于在暂停状态期间计时器仍在触发,因此每个系列管道之间的间隙是不一致的。

此外,当从菜单转换到游戏状态时,计时器会在关闭时间触发,从而快速连续创建前两个管道。

是否有任何替代 NSTimer 来处理此功能?

【问题讨论】:

  • 哦,天哪,世界需要更多“flappy bird”克隆,我们必须赶上“2048”克隆的绝对数量。对不起,无法抗拒:-)
  • 为什么你不能停止计时器并在播放恢复时重新启动它?
  • 是的,正如@MidhunMP 所说,暂停时停止计时器并在恢复播放时安排新计时器

标签: ios xcode swift nstimer


【解决方案1】:

您可以在游戏暂停时停止调用func invalidate() 的计时器,然后在游戏未暂停时重新启动它。

更新:

您可以添加第二个计时器,该计时器在与下一次触发和暂停时间的差时触发,第二个计时器应该触发第一个计时器,然后将第一个计时器重置为初始时间。

步骤:

  1. 假设添加一个每 2 秒触发一次的计时器

  2. 游戏暂停时,从timer.fireDatetimeOfPause计算时间间隔,应该是intervalTillNextTrigger

  3. 添加第二个afterPauseTimer,在intervallTillNextTrigger 处触发且不应重复

  4. afterPauseTimer被调用时,用timer.fire()触发第一个定时器,使timer失效,因为timer.fire()不会中断它的正常触发时间表,再次添加timer,触发间隔为2秒并使afterPauseTimer无效。

见下面的代码:

//
//  ViewController.swift
//  swft ios
//
//  Created by Marius Fanu on 30/12/14.
//  Copyright (c) 2014 Marius Fanu. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    var timer: NSTimer!

    var isPaused = false
    var isAfterPause = false
    var intervalTillNextTrigger: NSTimeInterval = 0
    var afterPauseTimer: NSTimer!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        timer = NSTimer(timeInterval: 2, target: self, selector: Selector("timerTriggerd"), userInfo: nil, repeats: true)
        NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode)
        timer.fire()
    }

    @IBAction func pauseButtonPressed(sender: UIButton) {
        var now = NSDate()
        println("now = \(now)")

        if isPaused == true {
            if isAfterPause {
                isAfterPause = false
                afterPauseTimer = NSTimer(timeInterval: intervalTillNextTrigger, target: self, selector: Selector("timerAfterIntervalTrigger"), userInfo: nil, repeats: false)
                NSRunLoop.mainRunLoop().addTimer(afterPauseTimer, forMode: NSDefaultRunLoopMode)
            }

            timer = NSTimer(timeInterval: 2, target: self, selector: Selector("timerTriggerd"), userInfo: nil, repeats: true)
            NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode)
        }
        else {
            isAfterPause = true
            intervalTillNextTrigger = timer.fireDate.timeIntervalSinceDate(now)
            println("till next trigger \(intervalTillNextTrigger)")
            timer.invalidate()
            timer = nil
        }

        isPaused = !isPaused
    }

    func timerTriggerd() {
        NSLog("Triggerd!")
    }

    func timerAfterIntervalTrigger() {
        println("reset timer")
        timer.fire()
        timer.invalidate()
        timer = nil

        timer = NSTimer(timeInterval: 2, target: self, selector: Selector("timerTriggerd"), userInfo: nil, repeats: true)
        NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode)

        afterPauseTimer.invalidate()
        afterPauseTimer = nil
    }

}

【讨论】:

  • 会出现同样的问题。例如:每 2 秒触发一次。它几乎要开火了,假设距离开火还有 0.5 秒,距离上次开火还有 1.5 秒。我们暂停游戏,使计时器无效。然后我们启动一个新的计时器,在开火前再等待 2 秒,现在距离上次开火已经 3.5 秒,因此造成了不一致。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
  • 2017-03-24
  • 1970-01-01
  • 2016-02-08
  • 2017-11-13
  • 2015-08-19
  • 2014-09-11
相关资源
最近更新 更多