【问题标题】:How do you trigger actions with NSTimer in Spritekit?你如何在 Spritekit 中使用 NSTimer 触发动作?
【发布时间】:2016-04-15 21:01:20
【问题描述】:

一旦通过运行计时器触摸屏幕,我正试图让我的“播放器”(中间的一个圆圈)增大尺寸。

一旦计时器超过 0 秒,它的大小就会增加。一旦计时器超过 3 秒,它就会减小到原来的刻度大小,一旦计时器超过 7 秒,它就会重置并永远重复。

我做错了什么?

import SpriteKit

class GameScene: SKScene {

    var Center = SKSpriteNode()
    var Player = SKSpriteNode()
    var timer = NSTimer()
    var seconds = 0

    override func didMoveToView(view: SKView) {

        Center = SKSpriteNode(imageNamed: "Center")
        Center.size = CGSize(width: 80, height: 80)
        Center.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(Center)

        Player = SKSpriteNode(imageNamed: "Player")
        Player.size = CGSize(width: 80, height: 80)
        Player.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
        self.addChild(Player)

    }


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

        timer = NSTimer.scheduledTimerWithTimeInterval(4.0, target: self, selector: #selector(GameScene.playerScaleUp), userInfo: nil, repeats: true)

       }

    func playerScaleUp(){
        if seconds > 0{
            Player.runAction(SKAction.scaleBy(4, duration: 2))

        }

    }

    func playerScaleDown(){
        if seconds > 3{
            Player.runAction(SKAction.scaleBy(-4, duration: 2))

        }
    }

    func resetScale(){
        if seconds > 7{
            timer.invalidate()

        }
    }

    override func update(currentTime: CFTimeInterval) {



    }

}

【问题讨论】:

    标签: swift sprite-kit swift2


    【解决方案1】:

    这可以通过几种不同的方式完成:

    1) 使用SKActions(我的示例使用)

    2) 使用update: 方法及其传递的currentTime 参数

    3) 不推荐使用NSTimer,因为它不受场景、视图或节点暂停状态的影响,因此可能会在将来给您带来麻烦。在StackOverflow answer 中阅读更多信息

    4) 好吧,可能还有更多,但我会在这里停下来。

    我的示例使用SKAction。这意味着我并没有真正检查经过了多少时间,而是将动作组织成序列(动作按顺序执行)和组(动作并行组织)。意味着我使用SKActions 就像我在玩LEGO's :)

    这是代码...我故意留下调试代码,因为它可以帮助您了解如何在不同情况下使用SKActions

    class GameScene: SKScene, SKPhysicsContactDelegate {
    
        let player = SKSpriteNode(color: .blackColor(), size: CGSize(width: 50, height: 50))
    
        var timePassed = 0.0 {
            didSet {
                self.label.text = String(format: "%.1f",timePassed)
            }
        }
    
        let label = SKLabelNode(fontNamed: "ArialMT")
    
        override func didMoveToView(view: SKView) {
    
            /* Debugging - Not really needed, I added it just because of a better example */
            let wait = SKAction.waitForDuration(0.1)
    
            let updateLabel = SKAction.runBlock({[unowned self] in self.timePassed += wait.duration})
    
            self.label.position = CGPoint(x: frame.midX, y: frame.midY+100.0)
            addChild(self.label)
            let timerSequence = SKAction.sequence([updateLabel, wait])
            self.runAction(SKAction.repeatActionForever(timerSequence), withKey: "counting")
    
            //This is used later, at the end of scaleUpAndDownSequence to reset the timer
            let resetTimer = SKAction.runBlock({[unowned self] in self.timePassed = 0.0})
    
    
            /* End Debugging */
    
    
            self.player.position = CGPoint(x: frame.midX, y: frame.midY)
            addChild(self.player)
    
            let waitBeforeScaleToOriginalSize = SKAction.waitForDuration(3.0)
            let waitBeforeRestart = SKAction.waitForDuration(4.0)
    
            let scaleUp = SKAction.scaleTo(2.0, duration: 1)
            let scaleDown = SKAction.scaleTo(1.0, duration: 1)
    
            let scaleUpGroup = SKAction.group([waitBeforeScaleToOriginalSize, scaleUp])
            let scaleDownGroup = SKAction.group([scaleDown, waitBeforeRestart])
    
            //One cycle, scale up, scale down, reset timer
            let scaleUpAndDownSequence = SKAction.sequence([scaleUpGroup, scaleDownGroup, resetTimer])
    
            let loop = SKAction.repeatActionForever(scaleUpAndDownSequence)
    
            self.player.runAction(loop, withKey: "scalingUpAndDown")
        }
    }
    

    所以在这里,我有两组动作:

    1) 扩展组

    2) scaleDownGroup

    scaleUpGroup 动作组中有两个动作:scaleUp 动作和表示在缩减动作发生之前要等待多长时间的动作。因为我们希望立即扩大规模,所以我们与waitBeforeScaleToOriginalSize 并行运行它。

    scaleDownGroup 的逻辑相同。当scaleUpGroup 完成时(其持续时间由longest action in the group 确定),我们启动scaleDownGroup,它将播放器缩小到默认大小,并等待一定的时间来重复整个过程。

    结果如下:

    我在触摸时启动动画(我已删除该代码),如您所见,放大动画立即开始,然后在 3 秒后播放器缩小到其原始大小,并在 4 秒后整个动画重复(玩家再次放大等)。

    【讨论】:

    • @ddramond 欢迎您 :) 如果此答案帮助您解决了您的问题,请将其标记为已接受。阅读this,您可能会发现这很有用。
    猜你喜欢
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多