Перемещайте SKSpriteNode с UIPanGestureRecognizer непрерывно - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь перемещать SKSpriteNode непрерывно в простом 2-мерном SKScene.Это включает в себя как перемещение массива, содержащего все фоновые узлы в противоположном направлении панорамирования UIGestureRecognizer, так и анимацию узла в одно и то же время.

Я уже реализовал движение, реализовав узлы и распознавательи вызывая его метод при панорамировании:

@objc func didPan(gesture: UIPanGestureRecognizer) {
    let pan = gesture.velocity(in: self.view)
    if gesture.state == .changed {
        for sprites in levelSprites {
            if pan.x > 0 && pan.x > pan.y {
                sprites.run(SKAction.moveTo(x: sprites.position.x - 40, duration: 0.5))
                self.player.run(SKAction(named: "WalkRight")!)
            } else if pan.x < 0 && pan.x < pan.y {
                sprites.run(SKAction.moveTo(x: sprites.position.x + 40, duration: 0.5))
                self.player.run(SKAction(named: "WalkLeft")!)
            } else if pan.y < 0 && pan.x > pan.y {
                sprites.run(SKAction.moveTo(y: sprites.position.y - 30, duration: 0.5))
                self.player.run(SKAction(named: "WalkUp")!)
            } else if pan.y > 0 && pan.x < pan.y {
                sprites.run(SKAction.moveTo(y: sprites.position.y + 30, duration: 0.5))
                self.player.run(SKAction(named: "WalkDown")!)
            }
        }
    }
}

Проблема, с которой я сталкиваюсь, состоит в том, что этот метод перемещает и анимирует спрайты только для значения, которое я установил, и ограниченного времени, которое я должен поддерживать, чтобы точно соответствоватьДлина анимации, когда я на самом деле хочу переместить их на время панорамирования.

Я специально ввел в действие распознаватель для панорамирования, а сцена также будет содержать джойстик для управления движением в дальнейшем.

Может быть, есть более простое решение того, чего я пытаюсь достичь, не используя UIGestureRecognizer?

1 Ответ

0 голосов
/ 31 мая 2018

didPan() вызывается несколько раз с состоянием .changed во время одного панорамирования от пользователя, но не с регулярной частотой.

Вместо этого вы должны объявить две глобальные переменные состояния, которые сохраняют текущую горизонтальнуюи вертикальные направления (слева направо или справа налево, например, для первого) и обновлять эти переменные каждый раз, когда вызывается didPan().

Вы должны запускать экземпляр SKAction только тогда, когда меняется направление, и эти экземпляры SKAction должны циклически выполняться бесконечно, а не иметь единовременную конкретную длительность 0,5 с (см. SKAction.repeatForever() в SceneKit API.руководство).

Кроме того, вы должны быть уверены, что удалили уже запущенное действие перемещения перед выполнением следующего действия перемещения.

Наконец, вызовите removeAllActions(), когда didPan() вызывается с состоянием .ended.

enum VerticalState{
   case .none
   case .topToBottom
   case .bottomToTop
}
enum HorizontalState{
   case .none
   case .leftToRight
   case .rightToLeft
}

var verticalState = VerticalState.none
var horizontalState = HorizontalState.none


@objc func didPan(gesture: UIPanGestureRecognizer) {
    let pan = gesture.velocity(in: self.view)
    if gesture.state == .changed {
        for sprites in levelSprites {
            if pan.x > 0 && pan.x > pan.y  && horizontalState <> .leftToRight{
                horizontalState = .none
                verticalState = .none
            } else if pan.x < 0 && pan.x < pan.y && horizontalState <> .rightToLeft{                
                horizontalState = .rightToLeft
                verticalState = .none
            } else if pan.y < 0 && pan.x > pan.y && verticalState <> .bottomToTop{                
                horizontalState = .none
                verticalState = .bottomToTop
            } else if pan.y > 0 && pan.x < pan.y && verticalState <> topToBottom{
                horizontalState = .none
                verticalState = .topToBottom
            }


            switch horizontalState
            {
               case .leftToRight:      
                   sprites.removeActionForKey("movement")    
                   self.player.removeActionForKey("movement")
                   sprites.run(SKAction.repeatForever(SKAction.moveBy(x: -40, y:0, duration: 0.5), forKey:"movement"))
                   self.player.run(SKAction(named: "WalkRight")!, forKey:"movement")
               case .rightToLeft:
                   sprites.removeActionForKey("movement")
                   self.player.removeActionForKey("movement")         
                                      sprites.run(SKAction.repeatForever(SKAction.moveBy(x: 40, y:0,, duration: 0.5), forKey:"movement"))
                   self.player.run(SKAction(named: "WalkLeft")!, forKey:"movement")
               case .none: 
                   break
            }
            switch verticalState
            {
               case .topToBottom:                
                   sprites.removeActionForKey("movement")
                   self.player.removeActionForKey("movement")         
                   sprites.run(SKAction.repeatForever(SKAction.moveBy(x: 0, y:-30, duration: 0.5), forKey:"movement"))
                self.player.run(SKAction(named: "WalkUp")!, forKey:"movement")
               case .bottomToTop:    
                   sprites.removeActionForKey("movement")      
                   self.player.removeActionForKey("movement")         
                   sprites.run(SKAction.repeatForever(SKAction.moveBy(x: 0, y:30,, duration: 0.5), forKey:"movement"))
                   self.player.run(SKAction(named: "WalkDown")!, forKey:"movement")
               case .none:
                   break
            }


        }
    }else if gesture.state == .ended {
         sprites.removeActionForKey("movement")      
         self.player.removeActionForKey("movement")  
    }
}
...