如何防止额外的触摸干扰拖动位置
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)
我正在寻求帮助以解决我已经困扰了一段时间但找不到答案的问题。
我有一个 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)