Search code examples
iosswiftsprite-kit2d-games

Create HUD in Sprite Kit that remains static on screen


I'm trying to create a static HUD that stays at the top of the screen throughout the game in a jump game from this tutorial. I'm still new to Swift, so maybe it's a convention I don't see easily:

http://www.raywenderlich.com/87232/make-game-like-mega-jump-sprite-kit-swift-part-2

In the tutorial, he puts the HUD in the override init(size: CGSize) function:

 required init?(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)
  }

 override init(size: CGSize) {
      super.init(size: size)
    ...

   // Build the HUD

   // HUD
   hudNode = SKNode()
   hudNode.zPosition = 1000
   addChild(hudNode)


   // Coins
   // 1
   let coin = SKSpriteNode(imageNamed: "powerup05_1")
   coin.position = CGPoint(x: 300, y: self.size.height-100)
   coin.zPosition = 1000
   hudNode.addChild(coin)

  // 2
  lblCoins = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
  lblCoins.fontSize = 70
  lblCoins.fontColor = SKColor.whiteColor()
  lblCoins.position = CGPoint(x: 375, y: self.size.height-100)
  lblCoins.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Left
  lblCoins.zPosition = 1000

  // 3
  lblCoins.text = String(format: "X %d", GameState.sharedInstance.coins)
  hudNode.addChild(lblCoins)

  // Score
  // 4
  lblScore = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
  lblScore.fontSize = 70
  lblScore.fontColor = SKColor.whiteColor()
  lblScore.position = CGPoint(x: self.size.width-325, y: self.size.height-100)
  lblScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Right
  lblScore.zPosition = 1000

  // 5
  lblScore.text = "0"
  hudNode.addChild(lblScore)
 }

However, if I try to use this function in my game I get an error:

Argument labels '(fileNamed:)' do not match any available overloads

In this function:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
   switch gameState.currentState {
   case is WaitingForTap:
   gameState.enterState(WaitingForBomb)
   // Switch to playing state
   self.runAction(SKAction.waitForDuration(2.0),
    completion:{
      self.gameState.enterState(Playing)
  })

  case is GameOver:
  // Error! Argument labels '(fileNamed:)' do not match any available overloads
   let newScene = GameScene(fileNamed:"GameScene")
   newScene!.scaleMode = .AspectFill
   let reveal = SKTransition.flipHorizontalWithDuration(0.5)
   self.view?.presentScene(newScene!, transition: reveal)

   default:
   break
  }
}

So I've resorted to putting it in the override func didMoveToView(view: SKView), but the HUD moves once the player jumps up:

override func didMoveToView(view: SKView) {
 ....
// Build the HUD

// HUD
 hudNode = SKNode()
 hudNode.zPosition = 1000
 addChild(hudNode)


// Coins
// 1
 let coin = SKSpriteNode(imageNamed: "powerup05_1")
 coin.position = CGPoint(x: 300, y: self.size.height-100)
 coin.zPosition = 1000
 hudNode.addChild(coin)

// 2
 lblCoins = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
 lblCoins.fontSize = 70
 lblCoins.fontColor = SKColor.whiteColor()
 lblCoins.position = CGPoint(x: 375, y: self.size.height-100)
 lblCoins.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Left
 lblCoins.zPosition = 1000

 // 3
 lblCoins.text = String(format: "X %d", GameState.sharedInstance.coins)
 hudNode.addChild(lblCoins)

 // Score
 // 4
 lblScore = SKLabelNode(fontNamed: "ChalkboardSE-Bold")
 lblScore.fontSize = 70
 lblScore.fontColor = SKColor.whiteColor()
 lblScore.position = CGPoint(x: self.size.width-325, y: self.size.height-100)
 lblScore.horizontalAlignmentMode = SKLabelHorizontalAlignmentMode.Right
 lblScore.zPosition = 1000

 // 5
 lblScore.text = "0"
 hudNode.addChild(lblScore)
}

Solution

  • Adding your hudNode to the cameraNode makes the HUD move together with the camera so that it will look static on screen. That is to change addChild(hudNode) to cameraNode.addChild(hudNode).

    Then use convert(_:to:) to change the point from the current scene coordinate to the cameraNode coordinate. That will set HUD's position in the new coordinate with just a little modification. For instance, change coin.position like this:

    coin.position = convert(CGPoint(x: 300, y: self.size.height-100), to: cameraNode)
    

    Do the same thing to the other HUD:

    lblCoins.position = convert(CGPoint(x: 375, y: self.size.height-100), to: cameraNode)
    lblScore.position = convert(CGPoint(x: self.size.width-325, y: self.size.height-100), to: cameraNode)
    

    The result after those 4 lines modification:

    enter image description here