swiftsprite-kitgesturemulti-touchtouches

Multi-touch gesture in Sprite Kit


I'm working in Swift with Sprite-Kit using XCode 6, and I have many different nodes but for the moment I only manage to detect one finger and move one node at the same time. I want to know how could I manage to detect multiple fingers in order to move multiple nodes at the same time. My actual code is :

var location = CGFloat() // finger position
var actualNode = -1 // node touched by the finger, -1 means no node touched

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) // when a finger touch the screen
{
    for touch: AnyObject in touches
    {
        location = touch.locationInNode(self) // we detect the finger position
    } 

    for var index = 0; index < colorNode.count; index++
    {
        if nodeAtPoint(location) == colorNode[index].node
        {
            actualNode = index // the number of the node touched by the finger
        }
    }
}

override func touchesMoved(touches: NSSet, withEvent event: UIEvent) // when a finger move
{
    for touch: AnyObject in touches
    {
        location = touch.locationInNode(self) // we detect the finger position
    }

    if actualNode != -1 // if a node is touched
    {
        colorNode[actualNode].position = location // we move this node to the finger
    }
}
override func touchesEnded(touches: NSSet, withEvent event: UIEvent) // when a finger don't touch the screen anymore
{        
    actualNode = -1 // there is no node touched
}

As you can see I only have the position of my first finger, but how can I detect multiple finger position and assign each finger to the node touched by the finger ?


Solution

  • Moving multiple nodes simultaneously is fairly straightforward. The key is to track each touch event independently. One way to do that is to maintain a dictionary that uses the touch event as the key and the node being moved as the value.

    First, declare the dictionary

    var selectedNodes:[UITouch:SKSpriteNode] = [:]
    

    Add each sprite touched to the dictionary with the touch event as the key

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in:self)
            if let node = self.atPoint(location) as? SKSpriteNode {
                // Assumes sprites are named "sprite"
                if (node.name == "sprite") {
                    selectedNodes[touch] = node
                }
            }
        }
    }
    

    Update the positions of the sprites as needed

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in:self)
            // Update the position of the sprites
            if let node = selectedNodes[touch] {
                node.position = location
            }
        }
    }
    

    Remove the sprite from the dictionary when the touch ends

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            if selectedNodes[touch] != nil {
                selectedNodes[touch] = nil
            }
        }
    }