Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying Levels with SpriteKit / Views vs. ViewController

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:

  1. 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.

  2. 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!

like image 244
NullHypothesis Avatar asked Oct 30 '22 09:10

NullHypothesis


1 Answers

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.

like image 55
jwade502 Avatar answered Jan 04 '23 13:01

jwade502