Once my SpriteKit game has ended, I would like to go back to my UIKit MenuViewController
. From what I've learned so far, using protocol/delegate is the best(?) option, but I haven't been able to get that to work. I know that the protocol would probably go above the class declaration for GameViewController
, and look something like:
protocol GameViewControllerDelegate {
var gameOver: Bool?
}
But I need help accessing that from GameScene
AND getting it to dismiss GameViewController
. Below are the bones of the app, in case that helps.
MenuViewController
class MenuViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func goToGame(_ sender: UIButton) {
performSegue(withIdentifier: "toGameSegue", sender: sender.currentTitle)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationVC = segue.destination as? GameViewController {
if let item = sender as? String {
destinationVC.numberOfPlayers = item
}
}
}
}
GameViewController
class GameViewController: UIViewController {
var numberOfPlayers: String?
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: "GameScene") {
scene.scaleMode = .aspectFill
scene.userData = NSMutableDictionary()
scene.userData?.setObject(numberOfPlayers!, forKey: "numberOfPlayers" as NSCopying)
view.presentScene(scene)
}
}
}
...
GameScene
class GameScene: SKScene {
var howManyPlayers: String?
override func didMove(to view: SKView) {
if let numPlayers = self.userData?.value(forKey: "numberOfPlayers") {
howManyPlayers = numPlayers as? String
}
print(howManyPlayers!)
}
...
This SpriteKit game has a MenuViewController, a GameViewController, and a GameScene. When you press a button from MenuViewController, data is sent via segue to GameViewController. Before GameViewController presents GameScene it stores the data in scene's userData variable so that GameScene can access it. In this example, it's the number of players.
I agree with Whirwind comment's: why mixing two different frameworks and complicate your life when you can use one viewController only to do all your game?
Anyway, according to your storyboard screenshot,there are 2 viewControllers and you can go to the second viewController (and to the GameScene
) only if you press a button.
There are two things to do: deallocate the current SKScene (in your case the GameScene
) and present the "initial view controller" or your MenuViewController
.
To do it, I use the "Hello world" Sprite-kit template with a protocol/delegate approach to extend the SKSceneDelegate
class. As you can see we able to dismiss the scene (presenting nil) and call an external method on the GameViewController
to present the MainViewController
To be sure that both of these operations go to be successful I use also two print
just for debug:
import UIKit
import SpriteKit
class GameViewController: UIViewController,TransitionDelegate {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
if let scene = SKScene(fileNamed: "GameScene") {
scene.scaleMode = .aspectFill
scene.delegate = self as TransitionDelegate
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
func returnToMainMenu(){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
guard let storyboard = appDelegate.window?.rootViewController?.storyboard else { return }
if let vc = storyboard.instantiateInitialViewController() {
print("go to main menu")
self.present(vc, animated: true, completion: nil)
}
}
}
import SpriteKit
protocol TransitionDelegate: SKSceneDelegate {
func returnToMainMenu()
}
class GameScene: SKScene {
override func didMove(to view: SKView) {
self.run(SKAction.wait(forDuration: 2),completion:{[unowned self] in
guard let delegate = self.delegate else { return }
self.view?.presentScene(nil)
(delegate as! TransitionDelegate).returnToMainMenu()
})
}
deinit {
print("\n THE SCENE \((type(of: self))) WAS REMOVED FROM MEMORY (DEINIT) \n")
}
}
Output:
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