Search code examples
sprite-kitspriteuigesturerecognizerswipegesture

Continous minimum velocity tracking of a finger on a sprite in spritekit/ios


What is a good way to continuously track the velocity of a user moving their finger up and down on a sprite without lifting the finger? And if they don't go fast enough(set a minimum) to perform an action.


Solution

  • This is some code you can use to drag a sprite across the screen at different speeds depending on your finger acceleration. You can add your own code to detect the magnitude of change and perform whichever action you want..

    enter image description here

    class GameScene: SKScene {
    
        // time values
        var delta:NSTimeInterval = NSTimeInterval(0)
        var last_update_time:NSTimeInterval = NSTimeInterval(0)
    
        // our sprite
        let sprite = SKSpriteNode(color: SKColor.redColor(), size: CGSize(width: 20, height: 30))
    
        // tracking difference between touches
        var currentTouchY: CGFloat = CGFloat(0)
        var lastTouchY: CGFloat = CGFloat(0)
    
        // the magnitude of change between current and last touch
        var forceMag: CGFloat = CGFloat(0)
        // max mag so our sprite doesnt travel at crazy speed
        let forceMagMax: CGFloat = CGFloat(7)
        // direction of our sprites travel
        var forceDir: CGFloat = CGFloat(0)
        // arbitrary speed we want sprite to move
        let velocity: CGFloat = CGFloat(70)
    
        // we use this to stop moving our sprite when we let go
        var intervalsWithoutChange = 0
    
        override func didMoveToView(view: SKView) {
            sprite.position.x = 100
            sprite.position.y = size.width/2
            self.addChild(sprite)
        }
    
        override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
            for touch: AnyObject in touches {
                let location = touch.locationInNode(self)
                let yCoord = location.y
    
                lastTouchY = yCoord
            }
        }
    
        override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
            for touch: AnyObject in touches {
                let location = touch.locationInNode(self)
                let yCoord = location.y
    
                intervalsWithoutChange = 0
                currentTouchY = yCoord
                let diff = currentTouchY - lastTouchY
                forceMag = abs(diff)
                forceMag = forceMag > forceMagMax ? forceMagMax : forceMag
                forceDir = diff < 0 ? -1 : 1
                lastTouchY = yCoord
            }
        }
    
        override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
            intervalsWithoutChange = 1
            currentTouchY = 0
            lastTouchY = 0
        }
    
        override func update(currentTime: NSTimeInterval) {
    
            if last_update_time == 0.0 {
                delta = 0
            } else {
                delta = currentTime - last_update_time
            }
    
            last_update_time = currentTime
    
            if intervalsWithoutChange > 0 {
                forceMag -= CGFloat(15) * CGFloat(delta)
            }
    
            if forceMag < 0.01 {
                forceMag = 0
            }
    
            let change = forceDir * pow(forceMag, 1.29)
    
            sprite.position.y += change * CGFloat(delta) * velocity
        }
    }