Search code examples
swiftxcodesprite-kitskscene

How to detect two simultaneous touches in xcode spritekit?


I am trying to detect two simultaneous touches in my sprite kit game, but the game only detects my first touch and ignores the second one.

I am using touchesBegan, touchesMoved, and touchesCancelled:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        if !miniGameHasStarted {
            if touches.contains(where: {$0.location(in: self).y > 0}) && touches.contains(where: {$0.location(in: self).y < 0}){
                player_two_desc.isHidden = true
                player_one_desc.isHidden = true
                startGame()
            }
            
            if touches.contains(where: {$0.location(in: self).y > 0}) {
                player_two_desc.isHidden = true
            } else if !touches.contains(where: {$0.location(in: self).y > 0}) {
                player_two_desc.isHidden = false
            }

            if touches.contains(where: {$0.location(in: self).y < 0}) {
                player_one_desc.isHidden = true
            } else if !touches.contains(where: {$0.location(in: self).y < 0}) {
                player_one_desc.isHidden = false
            }
        }
        
        
        let location = touch.location(in: self)
        
        if location.y > 0 {
            player_two_paddle.run(SKAction.moveTo(x: location.x, duration: 0.2))
        }
        if location.y < 0 {
            player_one_paddle.run(SKAction.moveTo(x: location.x, duration: 0.2))
        }
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    touches.forEach { touch in
        let location = touch.location(in: self)
        
        if location.y > 0 {
            player_two_paddle.run(SKAction.moveTo(x: location.x, duration: 0.2))
        }
        if location.y < 0 {
            player_one_paddle.run(SKAction.moveTo(x: location.x, duration: 0.2))
        }
    }
    // Check if both players have touched their side to start the game
    if !miniGameHasStarted {
        if touches.contains(where: {$0.location(in: self).y > 0}) && touches.contains(where: {$0.location(in: self).y < 0}){
            player_two_desc.isHidden = true
            player_one_desc.isHidden = true
            startGame()
        }

        if touches.contains(where: {$0.location(in: self).y > 0}) {
            player_two_desc.isHidden = true
        } else if !touches.contains(where: {$0.location(in: self).y > 0}) {
            player_two_desc.isHidden = false
        }

        if touches.contains(where: {$0.location(in: self).y < 0}) {
            player_one_desc.isHidden = true
        } else if !touches.contains(where: {$0.location(in: self).y < 0}) {
            player_one_desc.isHidden = false
        }
    }

    for touch in touches {
        let location = touch.location(in: self)

        print(touches.count)

        if location.y > 0 {
            player_two_paddle.run(SKAction.moveTo(x: location.x, duration: 0.2))
        }
        if location.y < 0 {
            player_one_paddle.run(SKAction.moveTo(x: location.x, duration: 0.2))
        }
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if !miniGameHasStarted {
        player_one_desc.isHidden = false
        player_two_desc.isHidden = false
    }
}

While testing, it seems that the touches set only contains one touch instead of two. Any alternatives to touchesMoved or correction would be appreciated.


Solution

  • I figured out my problem. By default, multiple touches are not allowed in views. You have to enable mutli-touches programmatically. In my game view controller, I added this line and it fixed it:

    view.isMultipleTouchEnabled = true