I am making a game in Swift and want to allow the user to select a level (tap on it) to play that particular level. Each level is a box on the screen that has the level number in it. So if the area had 20 levels, you'd see 20 boxes on the screen with the level # and the name and the # of stars you achieved. I'm confused about the best approach for this. I see two ways:
You create a viewcontroller that possesses a UICollectionView, and I feed the levels into it as a data source, and handle the on tap event there as well. When you tap on it, I can do a presentScene to the corresponding game scene (SKScene) to handle the normal game drawing.
I render the levels directly as SKSpriteNodes (the boxes for the levels) on the screen with a for.. loop and perform a addChild and set the position of each sprite. Since I could have 20 levels, I'd draw ~5 per row since my guess is that would fit on most devices from the emulators I've tried. Seems like i'm recreating what a UICollectionView does automatically though, and on top of that I need to do trickery like positioning and offsets and such.
Right now i'm doing approach #2 above because it seems like most Swift game tutorials don't use story boards or view controllers and instead just focus on building everything using SKScenes and having one view controller whose job is to just present one scene. So as I learned I went in this direction.
What is the right approach here?
Thanks!
Either of your methods will work, but you'll have to decide a way that works best for the specific scenario, so the "right approach" is up to you. I had the same question about six months ago and the following solution has worked flawlessly for me so far:
The Benefits of using SKSpriteNodes in your SKScene
I discovered that you can write a custom SKNode
subclass which I named SpriteKitButton
that contains custom code and animations that make an SKSpriteNode
act like a UIButton for use with SpriteKit
, and it allows you to add better looking animations and such to it when it is pressed.
I primarily prefer this approach because the custom sprite buttons are as easy to initialize as a UIButton and will load with the respective SKScene
you add them to and disappear with them as well.
This has allowed me to only work with SKScenes
instead of having to deal with loading UIViewControllers
or UIViews
along with loading SKScenes
.
Therefore, all you have to do is simply call self.view?.presentScene...
to change between your scenes, and you will have sprites that act and feel like buttons in them.
Here's a hint to get you started:
1) Make a new swift file and add the following:
import SpriteKit
class SpriteKitButton: SKNode {
var button: SKSpriteNode!
var buttonUnpressedTexture: SKTexture!
var buttonPressedTexture: SKTexture!
var action: (String) -> Void
init(buttonUnpressedImage: String, buttonPressedImage: String, buttonAction: (String) -> Void) {
//Initialize your button here
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
}
2) Make a new button in your SKScene like so:
let artboardButton = SpriteKitButton(buttonUnpressedImage: "artboardButtonUnpressed.png", buttonAction: openArtboard)
artboardButton.position = CGPoint(x: ..., y: ...)
artboardButton.zPosition = 0.0
artboardButton.userInteractionEnabled = true
self.addChild(artboardButton)
//Add a function to handle what to do when the button is pressed
func openArtboard() {
}
Use the various touches
methods inside of your SKNode
subclass to handle what you want the button to do when it is touched. How you handle what the button does when handled is entirely up to you.
You can also use a for
loop to load your 20 or so buttons at once.
Be sure to unload the button in willMoveFromView
by setting it to nil.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With