使用多点触控解决触摸冲突

Resolving conflicting touches with multitouch

我有两个精灵向触摸点旋转。在 touchesBegan 中,我使用 if 语句来检查触摸点是否在两个 X 点范围内,以便分离两个精灵的旋转。例如,如果触摸点在左侧范围内,则左侧精灵会向触摸点旋转。我使用 touchesMoved 来更新精灵的旋转。然后我使用 touchesEnded 将精灵 return 到其原始位置。

我面临的问题是,如果我将手指从左向右拖动并因此从左侧范围移动到右侧范围,那么 touchesEnded 不会 return 第一个精灵回到原来的位置。我知道这是由于触摸在另一个范围内结束,然后只纠正了另一个精灵。我试图通过在 touchesMoved 中添加一个 if 语句来解决这个问题,以便在触摸移动超出一个范围并进入另一个范围时更正位置。

在我用两根手指(屏幕的每一侧各一根)同时以不同方式旋转两个精灵之前,它一直有效。精灵然后不受控制地从当前旋转位置来回跳到它们的原始位置。解决这个问题的最佳方法是什么?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches {
        location = touch.location(in: self)
        let DegreesToRadians = Pi / 180

        let rightDeltaX = location.x - rightSprite.position.x
        let rightDeltaY = location.y - rightSprite.position.y
        let rightAngle = atan2(rightDeltaY, rightDeltaX)

        let leftDeltaX = location.x - leftSprite.position.x
        let leftDeltaY = location.y - leftSprite.position.y
        let leftAngle = atan2(leftDeltaY, leftDeltaX)

            if 0...768 ~= location.x {
                leftSprite.zRotation = leftAngle - 90 * DegreesToRadians
            }
            if 769...1536 ~= location.x {
                rightSprite.zRotation = rightAngle - 90 * DegreesToRadians
            }
    }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches {
        location = touch.location(in: self)
        let DegreesToRadians = Pi / 180

        let rightDeltaX = location.x - rightSprite.position.x
        let rightDeltaY = location.y - rightSprite.position.y
        let rightAngle = atan2(rightDeltaY, rightDeltaX)

        let leftDeltaX = location.x - leftSprite.position.x
        let leftDeltaY = location.y - leftSprite.position.y
        let leftAngle = atan2(leftDeltaY, leftDeltaX)

            if 0...768 ~= location.x {
                leftSprite.zRotation = leftAngle - 90 * DegreesToRadians

                if !(769...1536 ~= location.x) {
                    rightSprite.zRotation = 0
                }
            }
            if 769...1536 ~= location.x {
                rightSprite.zRotation = rightAngle - 90 * DegreesToRadians

                if !(0...768 ~= location.x) {
                    leftSprite.zRotation = 0
                }
            }
    }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches {
        location = touch.location(in: self)

            if 0...768 ~= location.x {
                leftSprite.zRotation = 0
            }
            if 769...1536 ~= location.x {
                rightSprite.zRotation = 0
            }
    }
}

传递给函数的 UI 触摸集中的每个 "touch" 都是一个不同的触摸事件。当同时使用多个触摸时,每个手指将在集合中用单独的 "touch" 表示。请记住,这是一个无序集。

在您提供的代码中,您检索了单个触摸事件的位置。您检查触摸位置的 x 值是否高,然后在该条件下,您还检查它是否低。但是您正在检查相同的位置,相同的 x 值。如果 x 值为 768 或以下,它将总是 为“!(x > 769)”。如果是769或以上,则总是是"not 768 or below".

因此,对于 "move" 函数期间的每个触摸事件,无论它在哪一侧,另一侧都会被重置。如果你在相对的两侧同时有两个触摸事件,它们都会不断地设置自己的一侧并重置另一侧。如您所说,结果行为将是 "uncontrollable"。

解决方案

您需要跟踪 UI 的状态。具体来说,您需要跟踪触摸位置。

touchesBegan() 期间,您将位置添加到跟踪触摸集中。在 touchesEnded() 期间,您从跟踪触摸集中删除了该位置。在 touchesMoved() 期间,您确定哪个跟踪触摸最接近移动的触摸对象,并相应地更新它。

每次更新您的设置时,您将解析跟踪的触摸集并相应地更新节点的旋转。如果一个节点没有触摸来旋转它,它就会被重置。这个函数可能最好在 for touch in touches 循环之后调用。