如何在Swift中识别连续触摸?

11

如何在Swift代码中识别连续的用户触摸? 连续的意思是用户手指一直按在屏幕上。 我想让一个Sprite Kit节点朝着用户触摸的方向移动,只要用户一直触摸屏幕。

3个回答

22
基本步骤:
  1. 储存触摸事件的位置(touchesBegan/touchesMoved
  2. 将精灵节点移向该位置(update
  3. 当没有检测到触摸时停止移动节点(touchesEnded
以下是一个实现示例:

Xcode 8

let sprite = SKSpriteNode(color: SKColor.white, size: CGSize(width:32, height:32))
var touched:Bool = false
var location = CGPoint.zero

override func didMove(to view: SKView) {
    /* Add a sprite to the scene */
    sprite.position = CGPoint(x:0, y:0)
    self.addChild(sprite)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    touched = true
    for touch in touches {
        location = touch.location(in:self)
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        location = touch.location(in: self)
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    // Stop node from moving to touch
    touched = false
}

override func update(_ currentTime: TimeInterval) {
    // Called before each frame is rendered
    if (touched) {
        moveNodeToLocation()
    }
}

// Move the node to the location of the touch
func moveNodeToLocation() {
    // Compute vector components in direction of the touch
    var dx = location.x - sprite.position.x
    var dy = location.y - sprite.position.y
    // How fast to move the node. Adjust this as needed
    let speed:CGFloat = 0.25
    // Scale vector
    dx = dx * speed
    dy = dy * speed
    sprite.position = CGPoint(x:sprite.position.x+dx, y:sprite.position.y+dy)
}

Xcode 7
let sprite = SKSpriteNode(color: SKColor.whiteColor(), size: CGSizeMake(32, 32))
var touched:Bool = false
var location = CGPointMake(0, 0)

override func didMoveToView(view: SKView) {
    self.scaleMode = .ResizeFill
    /* Add a sprite to the scene */
    sprite.position = CGPointMake(100, 100)
    self.addChild(sprite)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    /* Start moving node to touch location */
    touched = true
    for touch in touches {
        location = touch.locationInNode(self)
    }
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    /* Update to new touch location */
    for touch in touches {
        location = touch.locationInNode(self)
    }
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    // Stop node from moving to touch
    touched = false
}

override func update(currentTime: CFTimeInterval) {
    /* Called before each frame is rendered */
    if (touched) {
        moveNodeToLocation()
    }
}

// Move the node to the location of the touch
func moveNodeToLocation() {
    // How fast to move the node
    let speed:CGFloat = 0.25
    // Compute vector components in direction of the touch
    var dx = location.x - sprite.position.x
    var dy = location.y - sprite.position.y
    // Scale vector
    dx = dx * speed
    dy = dy * speed
    sprite.position = CGPointMake(sprite.position.x+dx, sprite.position.y+dy)

}

主保佑你! - Ahmadreza
如果您只想要一个用户触摸移动事件,那么这些方法将不起作用,因为这些重写的方法会同时识别触摸和触摸移动。为此,您需要添加一个 UIPanGestureRecognizer 事件。使用它,您可以在触摸开始、结束等情况下识别触摸移动。 - Wimukthi Rajapaksha

13
这个过程中最困难的是在多点触控环境中跟踪单个触摸。使用“简单”的解决方案(即,在touchesBegan中打开“istouched”,并在touchesEnded中关闭它)的问题在于,如果用户在屏幕上触摸另一只手指,然后松开它,它将取消第一个触摸的操作。
为了使这个过程完美无缺,你需要跟踪每个单独的触摸,并记录它们的生命周期。当第一个触摸发生时,你需要保存该触摸的位置并将对象移动到那个位置。任何进一步的触摸应与第一个触摸进行比较,如果它们不是第一个触摸,则应被忽略。这种方法还允许你处理多点触控,其中对象可以向任何当前在屏幕上的手指移动,然后在第一个手指抬起后移动到下一个手指等等。
值得注意的是,UITouch对象在touchesBegantouchesMovedtouchesEnded之间都是常量。你可以认为UITouch对象在touchesBegan中创建,在touchesMoved中更改,并在touchesEnded中销毁。你可以通过在touchesBegan中将触摸对象的引用保存到字典或数组中来跟踪触摸的阶段以及它们的生命周期,然后在touchesMoved中检查任何现有触摸的新位置并更改对象的路径,如果用户移动手指,你可以应用容差来防止抖动,例如,如果x/y距离小于某个容差,则不更改路径。在touchesEnded中,你可以检查正在关注的触摸是否是已经结束的触摸,并取消对象的移动或设置它向任何其他仍在进行的触摸移动。这很重要,因为如果你只检查任何旧的触摸对象是否已经结束,这也会取消其他触摸,从而产生意想不到的结果。

本文是关于Obj-C的,但是代码很容易移植到Swift,并向你展示了需要做什么。只需查看“处理复杂的多点触控序列”下的内容:https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/multitouch_background/multitouch_background.html


0
以下是拖动节点在X轴(左右)上移动的代码,非常容易添加Y轴并执行相同操作。
let item = SKSpriteNode(imageNamed: "xx")
var itemXposition = 50

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// updates itemXposition variable on every touch
    for touch in touches {
        let location = touch.location(in: self)
        itemXposition = Int(location.x)
    }
}

// this function is called for each frame render, updates the position on view
override func update(_ currentTime: TimeInterval) {
    spaceShip.position = CGPoint(x: self.itemXposition , y: 50 )
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接