У меня есть SKScene
с кучей узлов (SKSpriteNode
с, SKShapeNode
с, и т.д.), что я хотел бы иметь возможность панорамирования по отдельности и одновременно. Мне нужно уметь:Несколько панорамирование жесты в SpriteKit сцене
- Прикоснитесь к одному узлу и переместите его вокруг.
- При перемещении одного узла коснитесь нескольких других узлов и перемещайте их.
Если бы я мог добавить UIPanGestureRecognizer
для каждого узла, это было бы легко. Но, насколько я могу судить, мой единственный вариант с UIGestureRecognizer
заключается в том, чтобы добавить его в view
SKScene
. Я реализовал это с помощью одного распознавателя, и жонглирование всеми касаниями и узлами связанного с распознаванием действия на моем SKScene
было немного больно. Вот что я сделал для распознавателя:
class MultiplePanGestureRecognizer: UIGestureRecognizer {
var currentTouches: Array<UITouch> = []
override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesBegan(touches, withEvent: event)
for touch in touches {
currentTouches.append(touch as UITouch)
}
state = .Began
}
override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesMoved(touches, withEvent: event)
state = .Changed
}
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesEnded(touches, withEvent: event)
removeCancelledOrEndedTouches(touches)
}
override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!) {
super.touchesCancelled(touches, withEvent: event)
removeCancelledOrEndedTouches(touches)
}
// Add new touches to currentTouches
func addUntrackedTouchesFromSet(touches: NSSet!) {
for touch in touches {
let index = find(currentTouches, touch as UITouch)
if index == nil {
currentTouches.append(touch as UITouch)
}
}
}
// Remove received touches from currentTouches array
func removeCancelledOrEndedTouches(touches: NSSet!) {
for touch in touches {
if let index = find(currentTouches, touch as UITouch) {
currentTouches.removeAtIndex(index)
}
}
// End the gesture if there are no touches remaining in currentTouches
if currentTouches.count == 0 {
state = .Ended
}
}
override func reset() {
super.reset()
currentTouches = []
}
}
В принципе, я просто держать все штрихи доступны на currentTouches
свойство жест распознаватель, так что я могу получить доступ все их в прикрепленном действии. Это означает, что я должен манипулировать тем, что касается ударов узлов и т. Д., В SKScene
. Первоначально я попытался перезапустить жест, установив его состояние на .Began
в touchesBegan:withEvent:
распознавателя жестов. Однако ручной сброс состояния распознавателя на .Began
не вызвал действие, поэтому я был вынужден разрешить новые касания в состоянии .Changed
в моем распознавателе, а затем жонглировать всем в действии.
Для справки, вот метод в моем SKScene
, который добавляется в качестве действия распознаватель в: (. touchNodeMap
является просто Dictionary
, который отображает UITouch
эс в SKNode
с)
func handleMultiplePan(recognizer: MultiplePanGestureRecognizer) {
switch recognizer.state {
case .Began, .Changed:
// Remove those touches from tracking that are no longer being
// recognized
touchNodeMap.prune(recognizer.currentTouches)
// Iterate over the recognizer's currentTouches
for touch in recognizer.currentTouches {
// Is it over a child node of the scene?
if let node = getChildNodeForTouch(touch) {
// If so, add it to the touchNodeMap
touchNodeMap.add(touch, withNode: node)
}
}
// Iterate over currentlyPanningTouches and move nodes accordingly
for (touch, node) in touchNodeMap {
let location = touch.locationInNode(self)
let previousLocation = touch.previousLocationInNode(self)
let deltaX = location.x - previousLocation.x
let deltaY = location.y - previousLocation.y
node.position = CGPointMake(node.position.x + deltaX, node.position.y + deltaY)
}
// Get node for most recent touch
let (_, mostRecentNode) = touchNodeMap.mostRecentTouchAndNode()
// Remove and re-add it to the scene
if mostRecentNode != nil {
mostRecentNode!.removeFromParent()
addChild(mostRecentNode!)
}
default:
break
}
}
Мой вопрос , я что-то упустил? Есть ли способ использовать UIGestureRecognizer
с по каждому узлу? Или, есть ли лучший способ сделать то, что я пытаюсь сделать?
Вы видели [учебник] (http://www.raywenderlich.com/44270/sprite-kit-tutorial-how-to-drag-and-drop-sprites) на сайте Рэя Вендерлиха? Похоже, это отличное место для начала. – Moshe
@Moshe, по моему вопросу, мне нужно иметь возможность перемещать * несколько * узлов * одновременно *. – GarlicFries