Search code examples
swiftsprite-kittouchuipangesturerecognizer

how to get the delta of swipe/ draging touch


I want to calculate the delta between a swipe gesture or dragging gesture. what I want to do is to get this delta and then to use it as velocity (by adding time var). I really get confused about how should I do this - via touchesMoved or via UIPanGestureRecognizer. also, I don't really understand the difference between them. right now I set and get the first touch on the screen but I don't know how to get the last one so I can calculate the vector. can anyone help me with that?

right now I'm doing that via touchesBegan and touchesEnded, I'm not sure if its the right and the better way, here is my code so far:

class GameScene: SKScene {
var start: CGPoint?
var end: CGPoint?


override func didMove(to view: SKView) {        

}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else {return}
    self.start = touch.location(in: self)
    print("start point: ", start!)
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else {return}
    self.end = touch.location(in: self)
    print("end point: ", end!)

    let deltax:CGFloat = ((self.start?.x)! - (self.end?.x)!)
    let deltay:CGFloat = ((self.start?.y)! - (self.end?.y)!)
    print(UInt(deltax))
    print(UInt(deltay))
}

Solution

  • You can detect swipe gestures using the built-in touch handlers of SpriteKit or you can implement a UISwipeGestureRecognizer. The following is an example of how to detect swipe gestures using SpriteKit's touch handlers:

    First, define the variables and constants...

    Define the starting point and time of the initial touch.

    var touchStart: CGPoint?
    var startTime : TimeInterval?
    

    Define constants that specify the characteristics of the swipe gesture. By changing these constants, you can detect the difference between a swipe, drag, or flick.

    let minSpeed:CGFloat = 1000
    let maxSpeed:CGFloat = 5000
    let minDistance:CGFloat = 25
    let minDuration:TimeInterval = 0.1
    

    In touchesBegan, store the starting point and time of the initial touch

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        touchStart = touches.first?.location(in: self)
        startTime = touches.first?.timestamp
    }
    

    In touchesEnded, calculate the gesture's distance, duration, and speed. Compare these value against the constants to determine if the gesture was a swipe.

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touchStart = self.touchStart else {
            return
        }
        guard let startTime = self.startTime else {
            return
        }
        guard let location = touches.first?.location(in: self) else {
            return
        }
        guard let time = touches.first?.timestamp else {
            return
        }
        var dx = location.x - touchStart.x
        var dy = location.y - touchStart.y
        // Distance of the gesture
        let distance = sqrt(dx*dx+dy*dy)
        if distance >= minDistance {
            // Duration of the gesture
            let deltaTime = time - startTime
            if deltaTime > minDuration {
                // Speed of the gesture
                let speed = distance / CGFloat(deltaTime)
                if speed >= minSpeed && speed <= maxSpeed {
                    // Normalize by distance to obtain unit vector
                    dx /= distance
                    dy /= distance
                    // Swipe detected
                    print("Swipe detected with speed = \(speed) and direction (\(dx), \(dy)")
                }
            }
        }
        // Reset variables
        touchStart = nil
        startTime = nil
    }