如何防止额外的触摸干扰拖动位置

How to prevent additional touch from interfering with drag location

我正在寻求帮助以解决我已经困扰了一段时间但找不到答案的问题。

我有一个 SpriteKit 儿童游戏应用程序,用户可以在其中在屏幕上拖动对象 (SKspriteNodes)。这是在 "touches" 事件中控制的,如下所示:

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    super.touchesBegan(touches, withEvent: event)

    let touch = touches.first as! UITouch
    let touchLocation = touch.locationInNode(self)

    if piece01.containsPoint(touchLocation) && piece01Placed == false && aPieceIsBeingGrabbed == false {
        piece01Grabbed = true
        aPieceIsBeingGrabbed = true
        self.piece01.zPosition = 4.0
        }
    }

   override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
    super.touchesMoved(touches, withEvent: event)

    let touch = touches.first as! UITouch
    let touchLocation = touch.locationInNode(self)

    if piece01Grabbed && piece01Placed == false {
        self.piece01.position = CGPointMake(touchLocation.x + worldScale * 120, touchLocation.y - worldScale * 80)

    }
}

我的问题是,如果用户在拖动 sprite 时触摸屏幕的另一部分,则会出现故障,Sprite 在两个触摸位置之间来回弹跳,无法决定留在哪个位置。

有谁知道我怎样才能防止这种情况发生,以便 Sprite 始终遵循最初抓住它的触摸?提前致谢!

实现此目的的最简单方法之一是使用它(无需实施 touchesBegan):

override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent)
{
    for touch in (touches as! Set<UITouch>)
    {
        let location = touch.locationInNode(self)

        for childNode in children
        {
            if (childNode is SKSpriteNode)
            {
                let node = childNode as! SKSpriteNode

                if (CGRectContainsPoint(node.frame.expand(50.0), location))
                {
                    node.position = location
                }
            }
        }
    }
}

其中expand扩展只是用来增加允许触摸的边界,定义为:

extension CGRect
{
    func expand(percent: CGFloat) -> CGRect
    {
        let deltaWidth = (percent / 100.0) * self.width
        let deltaHeight = (percent / 100.0) * self.height
        return CGRect(x: self.origin.x, y: self.origin.y, width: self.width + deltaWidth, height: self.height + deltaHeight)
    }
}

您可能想要添加更多逻辑来处理重叠等等,但这应该是一个很好的起点。

希望对您有所帮助

MaceDevs 上面的答案根据我的问题是正确的,并且可以像我最初问的那样处理 touchesMoved 事件。但是,我发现使用手势识别器来处理拖动事件更容易。

所以为了解决这个问题,我最终放弃了 "touches" 方法并改为实现了 UIPanGestureRecognizer。

你所要做的就是在 didMoveToView 中设置一个 UIPanGestureRecognizer 并将其最大触摸次数设置为 1。如果你不将其设置为 1,那么任何额外的触摸都会在平均方向上移动棋子触及。

//Declare "draggingPiece" variable at top of swift file
var draggingPiece: UIPanGestureRecognizer!

//...init functions...

override func didMoveToView(view: SKView) {
    //Enable the gesture recognizer
    draggingPiece = UIPanGestureRecognizer(target: self, action: Selector("dragPiece:"))
    draggingPiece.maximumNumberOfTouches = 1

    self.view?.addGestureRecognizer(draggingPiece)

}

func dragPiece(recognizer: UIPanGestureRecognizer) {
    if recognizer.state == UIGestureRecognizerState.Began {

    }else if recognizer.state == UIGestureRecognizerState.Changed {

    }else if recognizer.state == UIGestureRecognizerState.Ended {

    }
}

然后移除 willMoveFromView 中的手势识别器:

self.view?.removeGestureRecognizer(draggingPiece)