使用多点触控解决触摸冲突
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
循环之后调用。
我有两个精灵向触摸点旋转。在 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
循环之后调用。