2017-04-13 6 views
4

私はインタラクティブなアニメーションシーンで作業しています。私は入場時に無効にされるシーンのすべてのタッチをしたい。その後、シーン内のオブジェクト(サブクラス化されたノード)が回転/移動を終了すると、画面上のすべてのタッチを再び有効にして相互作用を許可します。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 } 
} 

ご覧のとおり、ここではタッチは無効になっていません。

runBlockに「waitForDuration」SKActionを追加して、前の操作後にビューのステータスを変更したくない場合。私は、アニメーションがいつ実行を終了したのかを判断し、タッチを再び有効にしたいと思っています。

これを実行するには、完了ハンドラを使用して理論化しましたが、ただちに接触を再有効化するだけです(たとえば、ハンドラを回転させて接触を再度検出させるなど)。以前は、runBlockのビューを無効にしようとしましたが、もちろん、それは即座に実行されます。 「waitForDuration」を使用せずにアニメーションに続いてタッチが再検出されるようにするにはどうすればよいですか?

+0

このコードはシーン以外のクラスのものです – Whirlwind

+0

"didMoveToView"はシーンからのものです。回転関数は、すべてのタッチをシーンに戻すノードクラスからのものです。 – illuminatedtype

+0

ええ、申し訳ありませんが、私は正確ではなかった、私はちょうどそれが他のクラスからのように見えたので、spin()メソッドについて質問するつもりでした。私はちょうどあなたのためにいくつかのコードを書くためにあなたの現在の設定を知る必要があった。私はもっ​​と一つのことを尋ねなければなりません...あなたは、ノードが場面に触れていると言いました。そのカスタムノードに 'userInteractionEnabled = false'がありますか? – Whirlwind

答えて

3

だから、これはあなたができる方法を示して簡単な例です:ノードがスピニングで行われたノード

3)スピン)

1)の無効化が完全に

2触れるが、有効にしますここで

は(あなたはそれがどのように動作するか試してみコピー/貼り付けることができ)コードで触れる:

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)]) 

だから、紡糸後、そのブロックがします実行される。さて、これを行うさまざまな方法があります...個人的には、私は代表団を使用しますが、これはあまり混乱しないと思った...私は、必要に応じて代表団の例を書くこともできますが、基本的には、カスタムノードのデリゲートとしてシーンを設定し、回転について通知するので、シーンはビューにタッチを再び有効にするように指示できます。

+0

ありがとうございます!これはうまくいった。 – illuminatedtype

+0

@illuminatedtypeあなたは大歓迎です。補完ハンドラを使用する場合は、常にメソッドの最後の引数にする必要があることに注意してください。これは、インラインブロックを使用するときにコードを読みやすくするため、ベストプラクティスです。また、メソッドごとに1つの補完ハンドラしか使用しないでください。 – Whirlwind

関連する問題