2016-08-17 34 views
7

Wszystko, co próbuję zrobić, to móc przeciągać i upuszczać ikonkę na ekranie. Próbowałem następujący kod:Jak przeciągnąć i upuścić ikonkę w 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  
} 
} 
} 

Kod ten nie działa jednak, kiedy przeciągnij piłkę dość szybko, myślę, że okaże się, że „piłka” nie zawiera już punkt „Location” i piłka zatrzymuje się, co oznacza, że ​​znowu wybieram piłkę. Chcę, aby piłka była w stanie szybko reagować na moje dotknięcia, aby piłka nie przestała się poruszać. Jak to zrobić?

+1

Ponieważ musisz myśleć o tym logicznie, jeśli poruszasz się szybko, palec nie dotyka już piłki, gdy wykonuje test. Musisz użyć touchchesBegan, aby rozpocząć stan aktywacji przy użyciu Twojego kodu zawierającego containPoint, potem użyjesz dotknięć, po prostu przesuniesz piłkę, jeśli stan jest aktywny, nie sprawdzasz punktu, a następnie na dotknięciachUsuń lub dotknijKanał, wyłącz go, – Knight0fDragon

Odpowiedz

-3

mam implementację gdzie mam do podklasy UIImageView i nazwał go "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 
    } 
+0

Jak to się dzieje? to nawet odpowiedź, SKNodes i UIViews to dwie różne rzeczy, a jeśli szybko się ruszysz, powinieneś mieć problem z tym, że Draggable Image touchesMoved nie jest zwalniany, ponieważ przekroczyłeś ramy – Knight0fDragon

10

Jest to poprawny sposób to zrobić w Sprite Kit. Jak już wspomniałem w swoim komentarzu, musisz przypisać ruchomy węzeł do stanu aktywacji, w tym przypadku używam zmiennej o nazwie movableNode, aby zadziałał mój stan aktywacji. Po dotknięciu piłki aktywuje się ją, przypisując ją do movableNode. Następnie podczas przeciągania palca, ruchomy węzeł zostanie przeciągnięty, a po zwolnieniu wprowadzisz stan dezaktywacji, ustawiając wartość movableNode na zero. Zauważ, że ten kod działa tylko w aplikacjach z jednym dotknięciem, jeśli chcesz obsługiwać multitouch, musisz śledzić, który dotyk przeciąga.

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 
    } 
} 
+0

Jeśli zamierzasz zagłosować, wyjaśnij dlaczego , to jest poprawne rozwiązanie. – Knight0fDragon

6

Rozwiązanie KnightOFDragon działa dobrze. Dodałem tylko kilka linii, jeśli nie chcesz przesunąć położenia środka ikonki do położenia, w którym twój palec dotknął ekranu i chciałbyś przenieść duszek z jego pierwotnej pozycji środkowej.

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 
} 
+0

Brilliant. Dziękuję Ci. – Steve

+0

Więc to w zasadzie tylko sprawi, że mój węzeł będzie ruchomy tylko wtedy, gdy przeciągniesz go w prawo? Ponieważ po dotknięciu niektórych części ekranu węzeł się tam przemieszcza. Nie chcę, aby węzeł się przesuwał, chyba że przeciągnę go gdzieś po ekranie. – Dewan