Creating a HUD for every game is vital.
It’s a bit tricky when you are adding UI Elements to Sprite Kit and there are also
a few different ways of doing it.
Here is one of the ways and so far my favorite.
It’s very flexible and it will allow you to easily customize your code later on.
For the purpose of this tutorial we’ll create a SpriteKit Scene with a label in the middle and
then we’ll add a HUD that will only have a UISwitch, which when switched will change our label in the scene. It’s very simple ,but you can build up on top of that and create more complex HUDs for your needs.
We’ll start by creating a new project.
Disable the portrait:
We want to remove the default logic from the GameScene file that places a spaceship wherever you
tap. We’ll also change the label a bit.
Open the GameScene.swift and replace all the content with the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
import SpriteKit class GameScene: SKScene { override func didMoveToView(view: SKView) { /* Setup your scene here */ let frameW = self.frame.size.width let frameH = self.frame.size.height myLabel.name = "label" myLabel.fontSize = 35 myLabel.position = CGPoint(x: frameW / 2, y: frameH / 2) self.addChild(myLabel) } override func touchesBegan(touches: NSSet, withEvent event: UIEvent) { /* Called when a touch begins */ for touch: AnyObject in touches { let location = touch.locationInNode(self) } } override func update(currentTime: CFTimeInterval) { /* Called before each frame is rendered */ } } |
Now we’ll create 2 more files:
global.swift
functions.swift
It’s my personal practice that I like doing and I feel is helping me organize my projects.
In global.swift we’ll keep all global parameters and in functions we’ll keep any functions that would be shared between different classes in the project.
For now just put this in global.swift:
1 2 3 4 5 6 7 |
import Foundation import SpriteKit var gameScene: SKScene! var myLabel = SKLabelNode(text: "fruit") var fruit: Bool = true |
In functions.swift just place this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import Foundation import UIKit import SpriteKit func switchGotSwitched() { if fruit == true { myLabel.text = "veggies" fruit = false } else { myLabel.text = "fruit" fruit = true } } |
Next we gotta prepare the HUD.
Basically the HUD will consist of 3 things.
The UIView that we are going to see, the file that describes the UIView and another file
that helps load the UIView.
Create a new file => UIView , and name it hud:
Now create 2 .swift files:
hud.swift
hudSetup.swift
Open hud.swift and replace the content with the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
import Foundation import UIKit @IBDesignable class hud: UIView { var view: UIView! let nibName = "hud" override init(frame: CGRect) { // programmer creates our custom View super.init(frame: frame) setupHud() } required init(coder aDecoder: NSCoder) { // Storyboard or UI File super.init(coder: aDecoder) setupHud() } func setupHud() { // setup XIB here view = loadHudFromNib() view.frame = CGRect(x: 0, y: 0, width: 250, height: 100) // this will be the size of your HUD in game view.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight addSubview(view) } func loadHudFromNib() ->UIView { let bundle = NSBundle(forClass: self.dynamicType) let nib = UINib(nibName: nibName, bundle: bundle) let view = nib.instantiateWithOwner(self, options: nil)[0] as UIView return view } } |
At this point if you run the project you should see a gray screen with the label ‘fruit’ in the middle. Good.
Now we have to define our custom classes.
Select the hud.xib and inside once you have selected the View, click on File Owner and
change the class to ‘hud’ – this is how we are going to load the view from nib.
Then click on the View below, change the class to hudSetup and change the background color to black.
Drag a UISwtich to the view and just position it towards the top, middle of the screen.
Add the missing constraints:
Next drag the UISwitch with your right mouse button to the hudSetup.swift file to
create the IBAction for it.
At the end you should have this in the hudSetup.swift:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import UIKit import SpriteKit class hudSetup: UIView { @IBAction func switchTapped(sender: AnyObject) { switchGotSwitched() } override func didAddSubview(subview: UIView) { } } |
Notice that we are referencing to our global function here.
Now open the GameScene.swift and add this function at the bottom right before the last
bracket:
1 2 3 4 5 6 7 8 |
func showHud() { let myHud = hud(frame: CGRect(x: 0, y: 0, width: 400, height: 35)) self.view?.addSubview(myHud) } |
Then right after the frameW and frameH in the didMoveToView { }, add this:
1 |
showHud() |
This is going to create our symbolic HUD with the switch inside.
With this we should be all set.
Once you run the app you should see the HUD with the switch in the top left corner and
when you switch it the label will cycle between ‘fruit’ and ‘veggies’.
That’s all for this tutorial.
If you have any questions or recommendations, please leave us a comment below. Thank you!
Soon to add a second part of the HUD SpriteKit Game tutorial ! Will be showing how to add score label and a weapon icon to it.
Thanks for this! Very helpful. Just one question: Why do hud.swift and hudSetup.swift need to be in separate files? What is the advantage, or is it just required that they be separated for a fundamental technical reason?
Glad to hear that, thanks! No, I like separating them, it’s my way of organizing my projects 🙂 I like my classes separate.
How can I add more interface items. This worked great, but I can only have one working switch or button. When I try to implement a second switch with an @IBAction function only the first one works.
Let me know, thanks.
Thanks so much! I figured out what I was doing wrong. You gave me the sanity check I needed to by letting me know It worked for you. The problem I created was that I defined a larger area for my subview in in the “Setup” class, but neglected to change the size when I created the object in my scene. The second button was not actually in the subview, and that’s why it didn’t work. Thanks again, your tutorial is the most helpful tutorial on this subject that I have yet found. Looking forward to more!
Glad you got it 🙂 Yes, I am planning on doing more, but I wanted to do a more complete one for having menu screen, option screen , etc. I hope to have it ready within a month, as I am just really busy at this time…
That’s weird, I have it with working multiple items. I don’t see why more items wouldn’t work… Can you upload your code to GitHub or something, so I can take a look ?