我有SKScene
个节点(SKSpriteNode
s,SKShapeNode
s等),我希望能够单独平移 和同时。我需要能够:
例如,如果我可以为每个节点添加UIPanGestureRecognizer
,这将很容易。但是,据我所知,UIGestureRecognizer
的唯一选择是将其添加到view
的{{1}}。我用一个识别器实现了这一点,并且在我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
(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
}
}
只是将touchNodeMap
es映射到Dictionary
的{{1}}。)
我的问题是,我在这里遗失了什么吗?有没有办法在每个节点上使用UITouch
?或者,有没有更好的方法来做我想做的事情?
答案 0 :(得分:0)
我遇到了同样的挑战,得到了@vacawama的非常好的帮助。请参阅此链接:How to implement multiple PanGestures (Draggable views)?
我这是你在寻找什么?