Search code examples
swiftxcodesprite-kitskspritenodetouchesbegan

Move object while holding button in Swift


I have a little Space Invaders game and I added two buttons leftButton and rightButton and I want the ship to move as long as one of the buttons is touched AND HELD in the proper direction.

I made it move in the right direction but I have to tap the button repeatedly, but I want ship to move WHILE the player is holding the button.

For simplicity I only posted code for the left button as I believe the way to code the other button is identical:

class GameScene: SKScene {
   var leftButton = SKSpriteNode()
   var ship = SKSpriteNode()

   override func didMove(to view: SKView) {
       leftButton = self.childNode(withName: "left") as! SKSpriteNode
       ship = self.childNode(withName: "player") as! SKSpriteNode
   }

   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
       for touch: AnyObject in touches {
           let pointTouched = touch.location(in: self)

           if leftButton.contains(pointTouched) {
               player.position.x -= 30
           }
      }
   }
}

Solution

  • Use an Action for that. There are other ways to implement this, but this will work for you.

    First add a func moveBythat takes the direction you want your ship to go and a key: String. You will use these in your touchesBegan later.

    func moveShip (moveBy: CGFloat, forTheKey: String) {
        let moveAction = SKAction.moveBy(x: moveBy, y: 0, duration: 1)
        let repeatForEver = SKAction.repeatForever(moveAction)
        let seq = SKAction.sequence([moveAction, repeatForEver])
    
        //run the action on your ship
        player.run(seq, withKey: forTheKey)
    }
    

    TouchesBegan:

            if leftButton.contains(pointTouched) {
                moveShip(moveBy: -30, forTheKey: "left")
            }
    
            if rightButton.contains(pointTouched) {
                moveShip(moveBy: 30, forTheKey: "right")
            }
    

    EDIT:

    touchesEnded:

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        player.removeAction(forKey: "left")
        player.removeAction(forKey: "right")
    }