Как перетащить спрайт в Swift 3.0?

Все, что я пытаюсь сделать, это иметь возможность перетаскивать спрайт по экрану. Я пробовал следующий код:

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

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch in (touches ) {
        let location = touch.locationInNode(self)
        if ball.containsPoint(location) {
            ball.position = location    
}
}
}

Однако этот код работает, когда я перетаскиваю мяч довольно быстро, я думаю, он обнаруживает, что «мяч» больше не содержит точку «местоположение», и мяч останавливается, что означает, что я снова поднимаю мяч. Я хочу, чтобы мяч мог быстро реагировать на мои касания, чтобы мяч не переставал двигаться. Как бы я это сделал?


person Mr_Username    schedule 17.08.2016    source источник
comment
Потому что вам нужно думать об этом логически. Если вы двигаетесь быстро, ваш палец больше не касается мяча, когда он выполняет проверку. Вам нужно использовать touchesBegan для запуска состояния активации с помощью вашего кода containsPoint, затем вы используете touchesMoved, вы просто перемещаете шарик, если состояние активировано, вы не проверяете точку, затем на touchesEnded или touchesCanceled вы его деактивируете   -  person Knight0fDragon    schedule 17.08.2016


Ответы (3)


У меня есть реализация, в которой я создал подкласс UIImageView и назвал его «DraggableImage».

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        originalPosition = self.center
    }

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            let position = touch.location(in: self.superview)
            self.center = CGPoint(x: position.x, y: position.y)
        }
    }

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

        self.center = originalPosition
    }
person Ryan Collins    schedule 17.08.2016
comment
Как это вообще ответ, SKNodes и UIViews - это две разные вещи, и если вы двигаетесь быстро, у вас все равно должна быть проблема с этим Draggable Image touchesMoved, который не срабатывает, потому что вы вышли за рамки - person Knight0fDragon; 18.08.2016

Это правильный способ сделать это в Sprite Kit. Как я сказал в своем комментарии, вам нужно назначить движущемуся узлу состояние активации, в этом случае я использую переменную с именем movableNode, чтобы действовать как мое состояние активации. Когда вы касаетесь мяча, он активируется, назначая его movableNode. Затем, когда вы проводите пальцем, movableNode будет двигаться вместе с перетаскиванием. Затем, как только вы отпустите, вы войдете в деактивированное состояние, установив movableNode на ноль. Обратите внимание, что этот код будет работать только в приложениях с одним касанием, если вы хотите обрабатывать мультитач, вам нужно отслеживать, какое касание выполняет перетаскивание.

var movableNode : SKNode?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        let location = touch.locationInNode(self)
        if ball.containsPoint(location) {
            movableNode = ball
            movableNode!.position = location    
        }
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first where movableNode != nil {
        movableNode!.position = touch.locationInNode(self)
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first where movableNode != nil {
        movableNode!.position = touch.locationInNode(self)
        movableNode = nil
    }
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        movableNode = nil
    }
}
person Knight0fDragon    schedule 18.08.2016
comment
Если вы собираетесь проголосовать против, объясните, почему, это правильное решение - person Knight0fDragon; 22.08.2016

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

var movableNode : SKNode?
var ballStartX: CGFloat = 0.0
var ballStartY: CGFloat = 0.0

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        let location = touch.location(in: self)
        if (map?.contains(location))! {
            movableNode = ball
            ballStartX =  (movableNode?.position.x)! - location.x // Location X of your sprite when touch started
            ballStartY =  (movableNode?.position.y)! - location.y // Location Y of your sprite when touch started
        }
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first, movableNode != nil {
        let location = touch.location(in: self)
        movableNode!.position = CGPoint(x: location.x+ballStartX, y: location.y+ballStartY) // Move node around with distance to your finger
    }
}

override  func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let _ = touches.first, movableNode != nil {
        movableNode = nil
    }
}
 override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
    movableNode = nil
}
person MOzeb    schedule 25.11.2016
comment
Блестящий. Спасибо. - person Steve; 23.12.2016
comment
Таким образом, это в основном сделает мой узел подвижным только в том случае, если вы перетащите его правильно? Потому что, когда я касаюсь определенных частей дисплея, узел перемещается туда. Я не хочу, чтобы узел двигался, если я не перетаскиваю его куда-нибудь на экране. - person Dewan; 13.12.2017