Search code examples
iosswiftsprite-kittouchsprite

TouchesEnded is called the other button is tapped and cancels other actions


When the player is holding down a button to move around and then presses the shoot button, TouchesEnded is called which then cancels the player's movement. Both actions work separately but not when they're both called at the same time.

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)

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

        let objects = nodes(at: location)
        for node in objects {
            if node.name == "leftBtn" {
                player.run(player.leftMovement, withKey: "leftMovement")
            } else if node.name == "rightBtn" {
                player.run(player.rightMovement, withKey: "rightMovement")
            } else if node.name == "upBtn" {
                let jump = SKAction.applyImpulse(CGVector(dx: 0, dy: 1000), duration: 0.2)
                player.run(jump, withKey: "jump")
            } else if node.name == "downBtn" {
                let downMovement = SKAction.applyImpulse(CGVector(dx: 0, dy: -500), duration: 0.2)
                player.run(downMovement, withKey: "downMovement")
            } else if node.name == "shootBtn" {
                player.shoot()
            }
        }
    }
}

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

    player.removeAction(forKey: "leftMovement")
    player.removeAction(forKey: "rightMovement")
    player.removeAction(forKey: "jump")
    player.removeAction(forKey: "downMovement")
}

I expect both actions to work independently from another, but unfortunately,​ that is not the case.


Solution

  • This is probably because when you are touching the shoot button, touchesEnded is also being called which will cancel all your movements.

    Similar to how you are checking which nodes were touched in your touchesBegan method, you will need to check if the shoot button was pressed in touchesEnded:

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            let location = touch.location(in: self)
    
            let objects = nodes(at: location)
            for node in objects {
                if ["leftBtn", "rightBtn", "upBtn", "downBtn"].contains(node.name) {
                    player.removeAction(forKey: "leftMovement")
                    player.removeAction(forKey: "rightMovement")
                    player.removeAction(forKey: "jump")
                    player.removeAction(forKey: "downMovement")
                }
            }
        }