Search code examples
iosswiftsprite-kituitouchtouches

SpriteKit - touchesMoved not called often enough - fast movement


Im programming a SpriteKit based game in Swift. The SKScene contains a SKSpriteNode which contains SKShapeNodes. One of those shapes is the "player". The user should be able to drag and drop the player. I implemented different methods to get this working user touchesBegan, touchesMoved, touchesCanceled and touches Ended. Basically everything works fine, as long as the user drags the "player" at a normal speed. But if the user drags the "player" really quickly the touchesMoved method is not called often enough. I thought it maybe due to the fact that I use SKShapeNodes but based on the output (below) that does not seem to be the case.

The code:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

let touchLocation = touches.first!.locationInNode(self)
if(self.player.containsPoint(touchLocation)){
    self.startedTouchingPlayer()
}
super.touchesBegan(touches, withEvent: event)
print("TOUCHES BEGAN")

}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {

let touchLocation = touches.first!.locationInNode(self)
if(self.player.containsPoint(touchLocation)){
    self.isTouchingPlayer(touchLocation)
    print("TOUCHES MOVED \(touchLocation)")
}
super.touchesMoved(touches, withEvent: event)

}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {

self.endedTouchingHelper()
super.touchesEnded(touches, withEvent: event)
print("TOUCHES ENDED")

}

override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {

print("TOUCHES CANCELED")
self.endedTouchingHelper()
super.touchesCancelled(touches, withEvent: event)

}

Print statements:

Normal Movement:

TOUCHES BEGAN
TOUCHES MOVED (-4.0, -241.499984741211)
TOUCHES MOVED (0.500015258789062, -239.0)
TOUCHES MOVED (4.0, -237.000015258789)
TOUCHES MOVED (11.0, -234.0)
TOUCHES MOVED (19.5, -229.499984741211)
TOUCHES MOVED (27.0000152587891, -225.499984741211)
TOUCHES MOVED (34.0, -221.499984741211)
TOUCHES MOVED (41.0, -217.499984741211)
TOUCHES MOVED (48.0, -213.499984741211)
TOUCHES MOVED (53.4999847412109, -210.0)
...
TOUCHES MOVED (77.5, -177.000015258789)
TOUCHES MOVED (77.5, -178.0)
TOUCHES ENDED

Fast movement:

TOUCHES BEGAN
TOUCHES MOVED (6.5, -277.5)
TOUCHES MOVED (3.0, -261.000030517578)
[*** at this point the finger is at a different position as the "player" ***] TOUCHES ENDED

Any kind of help is appreciated. Thanks.


Solution

  • Darvydas pointed me in the right direction and I was able to solve the problem like that:

    The problem was not in the way I moved the player around it was this line in touchesMoved:

    if(self.player.containsPoint(touchLocation))
    

    When the user moves really quickly the touchLocation is not inside the player (because the position could not be updated that quickly). I changed the condition in the statement so it would just check if the player is currently being dragged (or allowed to be dragged).

    1. touchesBegan sets a bool to true to indicate that the player got touched
    2. touchesMoved always updates the players position (no matter where the touch occurred) as long as the bool is true
    3. touchesEnded sets the bool to false

    Thanks.