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

时间:2014-11-09 15:18:44

标签: swift sprite-kit gesture-recognition

如何识别Swift代码中的持续用户触摸?连续我的意思是用户将手指放在屏幕上。只要用户触摸屏幕,我想将精灵套件节点移动到用户触摸的方向。

3 个答案:

答案 0 :(得分:18)

基本步骤

  1. 存储触摸事件的位置(touchesBegan / touchesMoved
  2. 将精灵节点移向该位置(update
  3. 不再检测到触摸时停止移动节点(touchesEnded
  4. 这是一个如何做到这一点的例子

    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)
    
    }
    

答案 1 :(得分:11)

此过程最困难的事情是跟踪多点触控环境中的单个触控。 &#34;简单&#34;的问题对此的解决方案(即,在touchesBegan中转动&#34; istouched&#34;并在touchesEnded中将其关闭)是因为如果用户触摸屏幕上的另一个手指然后将其抬起,则将取消第一次触摸的动作。

要使这种防弹,您需要跟踪其生命周期内的各个触摸。当第一次触摸发生时,您保存该触摸的位置并将对象移向该位置。任何进一步的触摸都应该与第一次触摸相比较,如果它们不是第一次触摸就应该被忽略。这种方法还允许您处理多点触控,其中对象可以朝向当前在屏幕上的任何手指移动,然后如果第一个手指被抬起则移动到下一个手指,依此类推。

值得注意的是UITouch对象在touchesBegantouchesMovedtouchesEnded之间保持不变。您可以将UITouch对象视为在touchesBegan中创建,在touchesMoved中更改,并在touchesEnded中销毁。您可以通过将触摸对象的引用保存到touchesBegan中创建的字典或数组,然后在touchesMoved中查看,可以跟踪触摸过程中的触摸阶段。任何现有触摸的新位置,如果用户移动手指,则改变对象的路线(您可以应用公差以防止抖动,例如,如果x / y距离小于某个容差,则不要改变课程)。在touchesEnded中,您可以检查焦点中的触摸是否是结束的触摸,并取消对象的移动,或将其设置为朝向仍在发生的任何其他触摸移动。这很重要,就像你只检查任何旧的触摸物体结束一样,这也会取消其他触摸,这会产生意想不到的结果。

这篇文章在Obj-C中,但代码很容易移植到Swift并向您展示您需要做什么,只需查看&#34;处理复杂多点触控序列下的内容&#34;:{{3 }}

答案 2 :(得分: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 )
}
相关问题