【问题标题】:Understanding Spritekit run block, variable not as expected了解 Spritekit 运行块,变量不符合预期
【发布时间】:2017-03-17 14:28:45
【问题描述】:

我正在寻求帮助,以了解为什么我的 speedToPoint 变量在执行 wait 操作时始终为 1

这是我为使鸟飞到预定义矩形中的随机点而编写的 SKSpriteNode 扩展的一部分。 speedToPoint 也在 1 和 4 之间随机化,并用作 moveTo 操作的持续时间。但是,我还需要将 TimeInterval 用于操作序列中的等待块。

speedToPoint 确实在运行块中随机化(我已经确认)。如何在序列的下一部分的等待块中使用相同的随机数?

var speedToPoint:TimeInterval = 1

self.run(SKAction.repeatForever(
     SKAction.sequence([
        SKAction.run{
            speedToPoint = TimeInterval(Globals.sharedInstance.randomF(min: 1, max: 4))
            var pointX = Globals.sharedInstance.randomF(min: left,max: right)
            let pointY = Globals.sharedInstance.randomF(min: top,max:bottom)

        while abs(self.position.x.distance(to: pointX)) < 200 {
            pointX = Globals.sharedInstance.randomF(min: left,max: right)
        }

        self.xScale = pointX < self.position.x ? -1 : 1

        self.run(SKAction.move(to: CGPoint(x:pointX,y:pointY),duration: speedToPoint))
    },
    SKAction.wait(forDuration: speedToPoint)])
),withKey: "inFrame")

澄清一下,我真正想做的是让鸟飞到一个点,一旦它到达那个点,就飞到另一个点。我仍在围绕动作序列以及它们是否真的等待完成继续前进。从我读过的内容来看,它们确实如此,但不适用于任何move 动作。这就是为什么wait 在那里。也许还有其他方法?

【问题讨论】:

  • 我发现它与 run 块闭包有关,因为它异步运行,变量不会及时更改。我找到了一个适合我的解决方法,但我真的很好奇正确的方法

标签: swift sprite-kit skaction


【解决方案1】:

SKAction,一旦创建,就无法修改,它意味着可以重复使用,例如。您不能修改持续时间参数,或更改其他传递的参数。这意味着如果您需要更改它,您必须重新创建它。当然,您可以更改现有动作的速度属性,也可以暂停动作,但在修改现有动作时就差不多了。

要解决您的问题,您可以执行以下操作:

1) 创建一个将精灵移动到特定位置的动作

2) 操作完成后,您将创建一个新的执行相同操作的操作

您可以使用递归来做到这一点,就像这样(只需复制并粘贴代码以查看其工作原理):

import SpriteKit


class GameScene: SKScene, SKPhysicsContactDelegate {


    private var bird = SKSpriteNode(color: .purple, size: CGSize(width: 100, height: 100))

    override func didMove(to view: SKView) {

        addChild(bird)
        recursive()

    }

    func recursive(){

        let sequence = SKAction.sequence([

           SKAction.move(to: self.randomPoint(inRect: self.frame), duration: TimeInterval(self.random(between: 1, and: 3))),

            SKAction.run({[unowned self] in NSLog("Block executed"); self.recursive()})
            ])

        self.bird.run(sequence, withKey: "aKey")
    }

    func random(between minimum: CGFloat, and maximum: CGFloat) -> CGFloat{

    return CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(minimum - maximum) + min(minimum, maximum)
}

    func randomPoint(inRect rect:CGRect)->CGPoint{


        let x = random( between: -rect.size.width / 2.0 , and: rect.origin.x + rect.size.width/2.0)
        let y = random(between: -rect.size.height / 2.0 , and: rect.origin.y + rect.size.height/2.0)

        return CGPoint(x: x, y: y)


    }

}

要停止此操作,请移除与其关联的键。

【讨论】:

  • 这就是我最终做的,我不知道这叫递归函数。 [unowned self] 在运行块关闭中做了什么?有没有办法让它按照我原来的方式工作?我从来没有尝试改变一个动作,只是一个在动作中使用的变量。
  • @TheValyreanGroup 递归方法是一种调用自身的方法... [unowned self] 保护您免于创建强引用循环。关于您的其他问题...实际上您已尝试更改操作-您正在传递 speedToPoint 变量(作为等待操作的持续时间参数)并期望每次都有不同的值。这在您执行此操作的方式中是不可能的,因为操作一旦创建就无法修改,就像我在回答中所说的那样。希望这有意义并且有帮助。
  • 干草确实有道理。谢谢你。不太了解强引用循环部分,但我会做一些阅读。
猜你喜欢
  • 2021-04-09
  • 2020-08-02
相关资源
最近更新 更多