在SKAction动画之后无法禁用,然后重新启用触摸

时间:2017-04-13 08:41:46

标签: swift sprite-kit skaction

我正在制作一个互动的动画场景。我希望现场的所有触摸都能在进入时禁用。然后,一旦场景中的对象(子类节点)完成旋转/移动,我想重新启用屏幕上的所有触摸以允许交互。我使用此代码禁用了用户交互:

override func didMove(to view: SKView) {
    setupNodes()
    view?.isUserInteractionEnabled = false
    spinLocations()
}

这是场景文件中spinLocations的代码:

func spinLocations() {
    var allLocationArrays = [[String : CGPoint]]()
    var previousArray = hiddenLocationPositions
    for _ in 0...SearchConstant.numSpins {
        let freshArray = generateNewLocationArray(previous: previousArray)
        allLocationArrays.append(freshArray)
        previousArray = freshArray
    }
    for (item, _) in hiddenLocationPositions {
        let node = fgNode.childNode(withName: item) as! LocationNode
        node.spin(position: allLocationArrays) // this is function below
    }
    hiddenLocationPositions = previousArray
}

这是节点类中动画的代码:

func spin(position: [[String : CGPoint]]) {
    var allActions = [SKAction]()
    for array in position {
        let action = SKAction.move(to: array[self.name!]!, duration: 2.0)
        allActions.append(action)
    }
    let allActionsSeq = SKAction.sequence(allActions)
    self.run(SKAction.sequence([SKAction.wait(forDuration: 5.0), allActionsSeq, SKAction.run {
        self.position = position[position.count - 1][self.name!]!
        },]))
}

这是将触摸传递回此类主场景的代码:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let parent = self.parent else { return }
}

如您所见,此处未禁用触控。

我不想在SKAction添加“waitForDuration”runBlock来更改上一个操作后的查看状态;我希望程序确定动画何时完成执行,然后重新启用触摸。

为了做到这一点,我使用完成处理程序理论化可能会起作用,但它只会立即重新启用触摸(例如,处理旋转处理程序会导致再次检测到触摸)。以前,我还试图在runBlock中禁用该视图,但当然,这是即时运行的。如何确保在动画后重新检测到触摸而不使用“waitForDuration。”?

1 个答案:

答案 0 :(得分:3)

所以,这是一个简单的例子,展示了你如何:

1)完全禁用触摸

2)旋转节点

3)当节点完成旋转时,启用触摸

以下是代码(您可以复制/粘贴它以尝试它的工作方式):

class Object:SKSpriteNode{

    func spin(times:Int,completion:@escaping ()->()) {

       let duration = 3.0
       let angle = CGFloat(M_PI) * 2.0

       let oneRevolution = SKAction.rotate(byAngle: angle , duration: duration)
       let spin = SKAction.repeat(oneRevolution, count: times)

       let sequence = SKAction.sequence([spin,SKAction.run(completion)])

       run(sequence, withKey:"spinning")
    }

}

class WelcomeScene: SKScene {


    override func didMove(to view: SKView) {


        view.isUserInteractionEnabled = false
        print("Touches Disabled")

        let object = Object(texture: nil, color: .purple, size: CGSize(width: 200, height: 200))

        addChild(object)

        object.spin(times: 3, completion: {[weak self] in

            self?.view?.isUserInteractionEnabled = true
            print("Touches Enabled")
        })

    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touch detected")
    }

    deinit {
        print("Welcome scene deinited")
    }
}

在这里,你在加载场景时禁用触摸,开始旋转对象,然后将完成块传递给它......这里使用了那段代码:

let sequence = SKAction.sequence([spin,SKAction.run(completion)])

因此旋转后,该块将被执行。现在,有不同的方法可以做到这一点......就个人而言,我会使用委托,但我认为这可能不那么令人困惑......如果需要,我也可以为代表团写一个例子,但基本上,你会做什么,是将场景设置为自定义节点的委托,并通知它关于旋转已完成,因此场景可以告诉视图重新启用触摸。