How to Use Storyboards with Spritekit Using Swift

How do I use storyboards with spriteKit using swift

A SpriteKit Scene is presented on an instance of a SKView, which is a subclassed UIView.

For an iOS game made using SpriteKit, one needs to have at least one viewController set up, either programatically in the App delegate or in a storyboard, on which the SKScene can be displayed. It is on the main view of this VC that a SKScene will be presented in.

So if you are using a storyboard, the iOS game will have to instantiate the root viewController from it. You can easily design your UI on the viewController, and present the game from the code on the press of a button, either in the same viewController or a new one. All this will be evident once you read a beginner tutorial for SpriteKit using Swift like this.

Let's say your root viewController has your main menu (on another view called menuView), with a play button on it. Now presenting a game on the press of a button would look something like this:

class MyViewController: UIViewController {
@IBOutlet wear var menuView: UIView?
@IBOutlet weak var playButton: UIButton?

@IBAction func likedThis(sender: UIButton) {
//Hide the menu view
menuView.hidden = true

//instantiate and present the scene on the main view
let scene = MyScene(size: view.bounds.size)
let skView = self.view as SKView
skView.presentScene(scene)
}
}

As for going back to the main menu from the scene, have a look at this answer.

is it a good practice to use Storyboard and Spritekit to make a game in IOS?

Both approaches are fine. If your menu and generic screens are not too complex maybe sticking to Spritekit would be a bit better in the long term.

See: iOS 7 SpriteKit - Creating game menus/buttons (Scenes vs. more view controllers)

SpriteKit Example without Storyboard

You will first need to have a View Controller. You can adjust the properties how you would like them. Here is mine:

import UIKit
import SpriteKit


class GameViewController: UIViewController {

// MARK: View Controller overrides
override func viewDidLoad() {
super.viewDidLoad()

view = SKView(frame: view.bounds)

if let view = self.view as! SKView? {
// Initialise the scene
let scene = GameScene(size: view.bounds.size) // <-- IMPORTANT: Initialise your first scene (as you have no .sks)

// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill

// Present the scene
view.presentScene(scene)

// Scene properties
view.showsPhysics = false
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}

}

Then, you create a class for your first scene. Mine is called GameScene which was initialised in the view controller. Make sure this is a subclass of SKScene. It will look something like this:

import SpriteKit

class GameScene: SKScene {

/* All Scene logic (which you could extend to multiple files) */

}

If you have any questions, let me know :)

Interface builder for SpriteKit

There are .sks files that are included to provide a way to drag and drop your items directly onto the scene as if it were sprite-kit's "storyboard" of sorts. This can be for animations, buttons, anything graphical. There's a lot you can do there that will replace code as well.

Look at an example here -> SpriteKit from Scratch Tutorial

The above tutorial entries from the same person shows you how to animate, reference, etc.

I haven't gone through them yet but if you're looking for Sprite-Kit's version of a storyboard that's going to be your best friend.

Swift: How to handle view controllers for my game

Your way seems very complicated to essentially present 3 scenes. Its not what you are supposed to do for SpriteKit games, you only really need 1 view controller (GameViewController).

Load your first scene from GameViewController (e.g HomeScene) and nothing else.
Create your playButton and other UI directly in HomeScene. Use SpriteKit APIs for your UI (SKLabelNodes, SKNodes, SKSpriteNodes etc).

You should never really use UIKit (UIButtons, UILabels) in SpriteKit. There are some exceptions to this, like maybe using UICollectionViews for massive level select menus, but basic UI should be done with SpriteKit APIs.

There is plenty tutorials to google on how to create sprite kit buttons, how to use SKLabelNodes etc. Xcode has a SpriteKit level editor so you can do all that visually similar to storyboards.

Than from HomeScene transition to the LevelSelect Scene and than to the GameScene and vice versa. Its super easy to do.

/// Home Scene
class HomeScene: SKScene {

...

func loadLevelSelectScene() {

// Way 1
// code only, no XCode/SpriteKit visual level editor used
let scene = LevelSelectScene(size: self.size) // same size as current scene

// Way 2
// with xCode/SpriteKit visual level editor
// fileNamed is the LevelSelectScene.sks you need to create that goes with your LevelSelectScene class.
guard let scene = LevelSelectScene(fileNamed: "LevelSelectScene") else { return }


let transition = SKTransition.SomeTransitionYouLike
view?.presentScene(scene, withTransition: transition)
}
}

/// Level Select Scene
class LevelSelectScene: SKScene {
....

func loadGameScene() {

// Way 1
// code only, no XCode/SpriteKit visual level editor used
let scene = GameScene(size: self.size) // same size as current scene

// Way 2
// with xCode/SpriteKit visual level editor
// fileNamed is the GameScene.sks you need to create that goes with your GameScene class.
guard let scene = GameScene(fileNamed: "GameScene") else { return }


let transition = SKTransition.SomeTransitionYouLike
view?.presentScene(scene, withTransition: transition)
}
}

/// Game Scene
class GameScene: SKScene {
....
}

I strongly recommend you scratch your storyboard and ViewController approach, and just use different SKScenes and 1 GameViewController.

Hope this helps

linking GameViewController.swift to GameScene.swift

This seems to be quite a common problem people have with SpriteKit games so lets go through the difference between SpriteKit games and UIKit apps.

When you make a regular UIKit app, e.g. YouTube, Facebook, you would use ViewControllers, CollectionViews, Views etc for each screen/menu that you see (Home screen, Channel screen, Subscription channel screen etc). So you would use UIKit APIs for this such as UIButtons, UIImageViews, UILabels, UIViews, UICollectionViews etc. To do this visually we would use storyboards.

In SpriteKit games on the other hand it works differently. You work with SKScenes for each screen that you see (MenuScene, SettingsScene, GameScene, GameOverScene etc) and only have 1 ViewController (GameViewController). That GameViewController, which has a SKView in it, will present all your SKScenes.

So we should add our UI directly in the relevant SKScenes using SpriteKit APIs such as SKLabelNodes, SKSpriteNodes, SKNodes etc. To do this visually we would use the SpriteKit scene level editor and not storyboards.

So the general logic would be to load your 1st SKScene as usual from the GameViewController and than do the rest from within the relevant SKScenes. Your GameViewController should basically have next to no code in it beyond the default code. You can also transition from 1 scene to another scene very easily (GameScene -> GameOverScene).

If you use GameViewController for your UI it will get messy really quickly if you have multiple SKScenes because UI will be added to GameViewController and therefore all SKScenes. So you would have to remove/show UI when you transition between scenes and it would be madness.

To add a label in SpriteKit it would be something like this

 class GameScene: SKScene {

lazy var scoreLabel: SKLabelNode = {
let label = SKLabelNode(fontNamed: "HelveticaNeue")
label.text = "SomeText"
label.fontSize = 22
label.fontColor = .yellow
label.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
return label
}()

override func didMove(to view: SKView) {

addChild(scoreLabel)
}
}

To make buttons you essentially create a SKSpriteNode and give it a name and then look for it in touchesBegan or touchesEnded and run an SKAction on it for animation and some code after.

enum ButtonName: String {
case play
case share
}

class GameScene: SKScene {

lazy var shareButton: SKSpriteNode = {
let button = SKSpriteNode(imageNamed: "ShareButton")
button.name = ButtonName.share.rawValue
button.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
return button
}()

override func didMove(to view: SKView) {

addChild(shareButton)
}

/// Touches began
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

for touch in touches {
let location = touch.location(in: self)
let node = atPoint(location)

if let nodeName = node.name {
switch nodeName {
case ButtonName.play.rawValue:
// run some SKAction animation and some code
case ButtonName.share.rawValue:

let action1 = SKAction.scale(to: 0.9, duration: 0.2)
let action2 = SKAction.scale(to: 1, duration: 0.2)
let action3 = SKAction.run { [weak self] in
self?.openShareMenu(value: "\(self!.score)", image: nil) // image is nil in this example, if you use a image just create a UIImage and pass it into the method
}
let sequence = SKAction.sequence([action1, action2, action3])
node.run(sequence)

default:
break
}
}
}
}
}

To make this even easier I would create a button helper class, for a simple example have a look at this
https://nathandemick.com/2014/09/buttons-sprite-kit-using-swift/

You can also check out Apple's sample game DemoBots for a more feature rich example.

This way you can have things such as animations etc in the helper class and don't have to repeat code for each button.

For sharing, I would actually use UIActivityController instead of those older Social APIs which might become deprecated soon. This also allows you to share to multiple services via 1 UI and you will also only need 1 share button in your app. It could be a simple function like this in the SKScene you are calling it from.

func openShareMenu(value: String, image: UIImage?) {
guard let view = view else { return }

// Activity items
var activityItems = [AnyObject]()

// Text
let text = "Can you beat my score " + value
activityItems.append(text as AnyObject)

// Add image if valid
if let image = image {
activityItems.append(image)
}

// Activity controller
let activityController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)

// iPad settings
if Device.isPad {
activityController.popoverPresentationController?.sourceView = view
activityController.popoverPresentationController?.sourceRect = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0)
activityController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.init(rawValue: 0)
}

// Excluded activity types
activityController.excludedActivityTypes = [
UIActivityType.airDrop,
UIActivityType.print,
UIActivityType.assignToContact,
UIActivityType.addToReadingList,
]

// Present
view.window?.rootViewController?.present(activityController, animated: true)
}

and then call it like so when the correct button was pressed (see above example)

openShareMenu(value: "\(self.score)", image: SOMEUIIMAGE)

Hope this helps

Using SpriteKit in AppKit app swift

This is exactly what the SpriteKit Game template you can start a new app with in Xcode is. There's nothing magic about it — it's an AppKit app, containing an SKView that displays an SKScene.

Take a look at a new project created with that template to see how it works. Create an SKView in code or in IB, make an outlet to it, and from your app's controller code (say, in the app delegate or a window controller), create a scene and pass that to the view's presentScene method.



Related Topics



Leave a reply



Submit