dismiss SKScene go back to UIKit Menu

佐手、 提交于 2019-12-04 03:38:39

问题


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.


回答1:


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:

GameViewController:

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)
        }
    }
}

GameScene:

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:



来源:https://stackoverflow.com/questions/43336790/dismiss-skscene-go-back-to-uikit-menu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!