在swift中创建秒表

在swift中创建秒表,swift,timer,sprite-kit,Swift,Timer,Sprite Kit,我试图寻找其他答案,但我找不到适用于我的情景的答案。我正在用swift写一个游戏,我想创建一个秒表来决定玩家玩多长时间。当用户触地时,秒表将启动,当某个动作发生时,计时器停止并重置。我想使用分、秒、毫秒,即00:00.00 目前,时间函数类的工作。它不是从0开始的,它是从当前秒开始的,我知道那是我开始的时间,但我不知道如何从0开始。它也只在我触摸屏幕时更新,我需要它从00:00.00开始计数,并自行更新,直到启动取消操作 谢谢你抽出时间 以下是我到目前为止的情况: class GameScene

我试图寻找其他答案,但我找不到适用于我的情景的答案。我正在用swift写一个游戏,我想创建一个秒表来决定玩家玩多长时间。当用户触地时,秒表将启动,当某个动作发生时,计时器停止并重置。我想使用分、秒、毫秒,即00:00.00

目前,时间函数类的工作。它不是从0开始的,它是从当前秒开始的,我知道那是我开始的时间,但我不知道如何从0开始。它也只在我触摸屏幕时更新,我需要它从00:00.00开始计数,并自行更新,直到启动取消操作

谢谢你抽出时间

以下是我到目前为止的情况:

class GameScene: SKScene {

var activeTimer = SKLabelNode()
//var bestTime = SKLabelNode()

var startTime = TimeInterval()
//var currentTime = TimeInterval()
//var countingTime = TimeInterval()
var updateTimerAction = SKAction()


override func didMove(to view: SKView) {

    activeTimer = self.childNode(withName: "active_timer") as! SKLabelNode
    //bestTime = self.childNode(withName: "best_time") as! SKLabelNode

    startTime = TimeInterval(Calendar.current.component(.second, from:Date()))
    updateTimerAction = SKAction.sequence([SKAction.run(updateTimer), SKAction.wait(forDuration: 1.0)])
}


func startGame() {
    // Other code
    startGameTimer()
}

func resetGame() {
    // Other code
    stopGameTimer()
}

func startGameTimer() {
    run(SKAction.repeatForever(updateTimerAction), withKey: "timer")
}

func updateTimer() {
    activeTimer.text = stringFromTimeInterval(interval: startTime) as String
}

func stringFromTimeInterval(interval: TimeInterval) -> NSString {

    let ti = NSInteger(interval)

    let ms = Int((interval.truncatingRemainder(dividingBy: 1)) * 1000)

    let seconds = ti % 60
    let minutes = (ti / 60) % 60

    return NSString(format: "%0.2d:%0.2d.%0.2d",minutes,seconds,ms)
}


func stopGameTimer() {
    removeAction(forKey: "timer")
}

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

    startGame()

    for touch in touches {
        // other code
    }
}

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

    for touch in touches {
        // other code
    }
}


override func update(_ currentTime: TimeInterval) {

    updateTimer()

    if <action>  {
        // stop timer and reset game
        resetGame()
    }
}

与其使用TimeInterval对象,不如使用Timer对象,该对象调用一个函数,该函数在每1秒后相应地从0开始递增标签或内部变量的值,或者可以使其变小。要停止时钟,只需调用Timer对象的invalidate函数。
查看文档了解更多信息:

以下代码行来自于我大约3周前提交给Mac App Store的一款实际macOS游戏。它将一个数字倒计时到0。在你的情况下,改变

self.currentSeconds -= 1

timeBackNode是一个空节点,它包含SKLabelNode对象timeNode0和timeNode1。因此,当游戏以didMove开始时创建它


这就是我最后要做的。虽然El Tomato的答案似乎有效,但考虑到我的代码设置,我走了一条稍微不同的路线。在与其他一些朋友交谈之后,由于我的应用程序的设计,我选择使用计时器。如果我在使用计时器对象时遇到任何问题,我将更新此问题

以下代码一触即开始,以:00:00.00格式更新,并在触发操作时停止。此时间将暂停,直到再次触摸,然后计时器将从零开始

class GameScene: SKScene {

var seconds = 0
var timer = Timer()
var timeStarted = Bool()
var activeTimer = SKLabelNode()
//var bestTime = SKLabelNode()

override func didMove(to view: SKView) {

    activeTimer = self.childNode(withName: "active_timer") as! SKLabelNode
    //bestTime = self.childNode(withName: "best_time") as! SKLabelNode
    timeStarted = false

}

func startGame() {

    startGameTimer()
    timeStarted = true
}

func resetGame() {

    timeStarted = false
    stopGameTimer()
    seconds = 0
}

func startGameTimer() {
    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
}

func updateTimer() {
    seconds += 1
    activeTimer.text = timeString(time: TimeInterval(seconds))
}

func timeString(time:TimeInterval) -> String {
    let hours = Int(time) / 3600
    let minutes = Int(time) / 60 % 60
    let seconds = Int(time) % 60
    return String(format:"%02i:%02i.%02i", hours, minutes, seconds)
}


func stopGameTimer() {
    timer.invalidate()
    removeAction(forKey: "timer")
}

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

    if !timeStarted {
        startGame()
    }

    for touch in touches {
        // other code
    }
}

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

    for touch in touches {
        // other code
    }
}


override func update(_ currentTime: TimeInterval) {

    if timeStarted {
        updateTimer()
    }

    if <action>  {
    // stop timer and reset game
    resetGame()
    }
}
}

我的印象是,我不想在游戏场景中使用以前的计时器。根据这个问题,这是正确的,虽然计时器可以并且将适用于简单的游戏,但它最终会在SpriteKit中引起一些问题。最好使用SKAction.wait等this@Fluidity我认为他不是这么说的。他告诉我们应该使用计时器对象。你说我们不应该使用计时器对象。我说我不在SKScene中使用计时器对象。@我相信你在SKScene中不使用计时器对象是正确的,但是你会用什么来代替呢?你可以用SKAction创建一个倒计时或倒计时计时器等待,序列,重复。
var currentSeconds = Int() // currentSeconds
var timeNode0 = SKLabelNode() // timeNode0
var timeNode1 = SKLabelNode() // timeNode1
func setupTimeGoal() {
    enumerateChildNodes(withName: "//TimerBack", using: { timeBackNode, _ in
        let goal = self.timeDict["num"] as! Int
        self.currentSeconds = goal // In your case, goal is 0 since you are going to count up.
        self.timeNode0 = SKLabelNode(fontNamed: "Your font's font name")
        self.timeNode0.text = self.makeTimeWithSeconds(secs: goal)
        self.timeNode0.fontSize = 26
        self.timeNode0.fontColor = SKColor.black
        self.timeNode0.horizontalAlignmentMode = .center
        self.timeNode0.position = CGPoint(x: 1, y: -22)
        timeBackNode.addChild(self.timeNode0)

        self.timeNode1 = SKLabelNode(fontNamed: "Your font's font name")
        self.timeNode1.text = self.makeTimeWithSeconds(secs: goal) // this function translate a counting number into a time code like 00:00:00
        self.timeNode1.fontSize = 26
        self.timeNode1.fontColor = SKColor.cyan
        self.timeNode1.horizontalAlignmentMode = .center
        self.timeNode1.position = CGPoint(x: 0, y: -23)
        timeBackNode.addChild(self.timeNode1)
    })
}

func repeatTime() {
    let waitAction = SKAction.wait(forDuration: 1.0)
    let completionAction = SKAction.run {
        if self.currentSeconds == 0 && self.gameState == .playing {
            self.removeAction(forKey: "RepeatTime")
            self.proceedLoss()
            return
        }
        self.currentSeconds -= 1
        self.timeNode0.text = self.makeTimeWithSeconds(secs: self.currentSeconds)
        self.timeNode1.text = self.makeTimeWithSeconds(secs: self.currentSeconds)
    }
    let seqAction = SKAction.sequence([waitAction, completionAction])
    let repeatAction = SKAction.repeatForever(seqAction)
    self.run(repeatAction, withKey: "RepeatTime")
}
class GameScene: SKScene {

var seconds = 0
var timer = Timer()
var timeStarted = Bool()
var activeTimer = SKLabelNode()
//var bestTime = SKLabelNode()

override func didMove(to view: SKView) {

    activeTimer = self.childNode(withName: "active_timer") as! SKLabelNode
    //bestTime = self.childNode(withName: "best_time") as! SKLabelNode
    timeStarted = false

}

func startGame() {

    startGameTimer()
    timeStarted = true
}

func resetGame() {

    timeStarted = false
    stopGameTimer()
    seconds = 0
}

func startGameTimer() {
    timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(updateTimer)), userInfo: nil, repeats: true)
}

func updateTimer() {
    seconds += 1
    activeTimer.text = timeString(time: TimeInterval(seconds))
}

func timeString(time:TimeInterval) -> String {
    let hours = Int(time) / 3600
    let minutes = Int(time) / 60 % 60
    let seconds = Int(time) % 60
    return String(format:"%02i:%02i.%02i", hours, minutes, seconds)
}


func stopGameTimer() {
    timer.invalidate()
    removeAction(forKey: "timer")
}

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

    if !timeStarted {
        startGame()
    }

    for touch in touches {
        // other code
    }
}

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

    for touch in touches {
        // other code
    }
}


override func update(_ currentTime: TimeInterval) {

    if timeStarted {
        updateTimer()
    }

    if <action>  {
    // stop timer and reset game
    resetGame()
    }
}
}