【问题标题】:How to make a reversed countdown or a count up timer in swift?如何快速进行倒计时或倒计时?
【发布时间】:2016-08-22 12:25:45
【问题描述】:

我正在开发一款 2d 平台游戏,我需要的是一个计数计时器,也就是进度条或进度计数节点。它应该像倒计时一样工作,只是它应该从 0 开始并无休止地上升。我将根据该数字的高低来确定游戏速度/难度。我知道要问问题所以你应该总是提供一些代码,但我知道如何进行反向倒计时。有人现在如何创建如下屏幕截图所示的类似内容吗?

编辑

我已经设法实现了我想要的。我刚刚创建了一个 SKLabelNode,它有一个 int 变量作为文本,并且在更新方法中增加了这样的 int 变量--score++--。但是分数标签的值增加得非常快,有没有人知道如何让它慢一点,然后随着游戏的进行慢慢变快?

提前谢谢你。

【问题讨论】:

  • 我将从标签值增加的条件开始。是基于时间(即每 30 秒增加一次)还是基于进度?还是完全基于其他东西?
  • @Ollie 抱歉回答迟了,我认为计时器是基于进度的。它只是一个上升的 SKLabelNode,在某个点之后它应该上升得更快,因为游戏向左滚动得更快(sidescroller)

标签: ios swift sprite-kit progress-bar countdown


【解决方案1】:

也许是这样的:

import SpriteKit

class Player:SKSpriteNode {

    override init(texture: SKTexture?, color: UIColor, size: CGSize) {
        super.init(texture: texture, color: color, size: size)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class GameScene: SKScene, SKPhysicsContactDelegate {

    var gameStarted = false
    var player = Player(texture: nil, color: UIColor.brownColor(), size: CGSize(width: 50, height: 100))

    var levelTimerLabel = SKLabelNode()
    var levelTimerValue: Int = 0 {
        didSet {

            if levelTimerValue == 10 { self.increaseScore(withDelay: 0.1)}
            levelTimerLabel.text = "\(levelTimerValue)m"
        }
    }

    override func didMoveToView(view: SKView) {

        self.player.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
        addChild(self.player)

        levelTimerLabel.zPosition = 200
        levelTimerLabel.position = CGPoint(x: CGRectGetMidX(frame), y: CGRectGetMidY(frame))
        levelTimerLabel.text = "\(levelTimerValue)m"
        addChild(levelTimerLabel)
    }

    //MARK: SCORELABEL METHOD
    func increaseScore(withDelay delay:NSTimeInterval = 0.5) {

        let block = SKAction.runBlock({[unowned self] in
            self.levelTimerValue += 1 // Swift 3 yo
        })

        let wait = SKAction.waitForDuration(delay)

        let sequence = SKAction.sequence([wait,block])

        self.runAction(SKAction.repeatActionForever(sequence), withKey: "countUp")

    }
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        if gameStarted == false {

            gameStarted = true
            startWorld()
            increaseScore()
        }
       player.physicsBody?.velocity = CGVectorMake(0, 0)
       player.physicsBody?.applyImpulse(CGVectorMake(0, 150))  // Jump Impulse
    }

    func startWorld(){

        print("startWold method invoked")
    }
}

当levelTimerValue 达到 10 时,countUp 操作将被替换为新操作,速度将提高 5 倍。我想这就是你想要达到的目标。我稍微修改了您的代码以避免强引用循环,删除了不需要的 update: 方法调用以及一些小事情。另请注意,现在您没有名为“wait”的 SKAction 属性。该操作现在在本地创建。

编辑:

根据您的 cmets,您可以像这样暂停计时器:

 func pauseTimer(){

        if let countUpAction = self.actionForKey("countUp") {

            countUpAction.speed = 0.0
        }

    }

取消暂停将是相同的...只需将 countUpAction.speed 设置为 1.0 如果您想暂停整个游戏,请查看this SO question。看看@Knight0fDragon 的回答。这是一个不错的方法,而且 IMO,它比完全暂停场景或视图更灵活。

我建议您不要使用字符串“countUp”,而是像这样创建一个常量:

let kCountUpActionKey = "countUp"

这样您在重复使用此操作键时不会出现拼写错误。

【讨论】:

  • 效果很好!非常感谢 :-) 如果您不介意,我有一个问题,我将在我的游戏中实现暂停状态,如何暂停倒数计时器并再次恢复?你为什么要创建一个玩家类?再次感谢您,我会将您的答案标记为正确。
  • @iCod3r 我进行了编辑以向您展示如何获取特定操作并暂停它。至于 Player 类......好吧,我为我做了这个,以便在内部测试它并忘记删除它:)
  • 也可以,谢谢!只剩下一个简单的问题(我知道我有很多问题,抱歉)我的 countUp 计时器从值“0.15”开始,然后当它达到 50m 时变为“0.14”,到 100m 时变为“0.13”等等。我的问题是,我怎样才能在比赛中找出计时器的价值?因此,如果玩家暂停游戏,假设在 200m 并且 countUp 计时器的值为“0.11”,重要的是当玩家恢复游戏时,countUp 计时器具有与暂停状态之前相同的值,因此游戏速度保持不变
  • 好吧,你有点跑题了。你原来的问题得到了回答。如果您有不同的问题,请随时提出新问题,希望有人会回答。总之,当玩家暂停游戏时,等待动作的持续时间参数的值与之前相同。为什么你认为有些事情会改变?无论如何,您真的应该问新问题,因为我们将进入单独的主题。祝你的游戏好运!
  • 哦,是的,对不起,你是对的!我把速度值误认为是等待动作/持续时间值。无论如何,我不再对这个话题有任何疑问。你太棒了,我希望我能多次支持你回答:-)谢谢!
【解决方案2】:

您可以使用 NSTimer 并每 x 秒更新一次值。游戏开始时创建你的 NSTimer

var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: #selector(MyGame.countUp), userInfo: nil, repeats: true)

然后在同一个类中创建一个函数,将值向上计数,例如1

func countUp() {
    self.myCountLabel.text == "\(1 + self.myCountLabel.text ?? 0)"
}

【讨论】:

  • 在 SpriteKit 中更合适的方式是使用 SKAction 或 update: 方法。 NSTimer 不受视图或场景暂停状态的影响,因此当用户接到电话或发生其他中断时,自动暂停/取消暂停将不起作用。
  • 但是,您可以在发生中断时使计时器无效。虽然我同意
  • 感谢您回答 Yannick,但就像 @Whirlwind 所说的 NSTimer 不受视图状态的影响,因此它不适合我。
  • @Yannick,它比这更复杂,你需要保留已经过去的时间,然后在返回时触发一个计时器以获取差异,然后重新启动正常计时器,主要的痛苦是正确。
  • @Whirlwind 我看了你的帖子并尝试实现它,我必须修改一些东西才能让它正常工作,以便它适合我的游戏。如果你不介意的话,我会在几个小时内向你报告,不幸的是我现在得走了。
猜你喜欢
  • 1970-01-01
  • 2016-01-28
  • 1970-01-01
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
  • 2016-12-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多