关闭 SKScene 返回 UIKit 菜单 [英] dismiss SKScene go back to UIKit Menu

查看:10
本文介绍了关闭 SKScene 返回 UIKit 菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

SpriteKit 游戏结束后,我想回到我的 UIKit MenuViewController.根据我目前所学到的,使用 protocol/delegate 是最好的(?)选项,但我无法让它发挥作用.我知道该协议可能会超出 GameViewController 的类声明,看起来像:

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

但我需要帮助从 GameScene 访问它并让它关闭 GameViewController.以下是应用程序的基本内容,以防万一.

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

游戏场景

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

    }
...

这个 SpriteKit 游戏有一个 MenuViewController、一个 GameViewController 和一个 GameScene.当您从 MenuViewController 按下按钮时,数据会通过 segue 发送到 GameViewController.在 GameViewController 呈现 GameScene 之前,它将数据存储在场景的 userData 变量中,以便 GameScene 可以访问它.在这个例子中,它是玩家的数量.

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.

推荐答案

我同意 Whirwind 的评论:当你只能使用一个 viewController 来完成所有游戏时,为什么要混合两个不同的框架并使你的生活变得复杂?

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?

无论如何,根据您的故事板屏幕截图,有 2 个 viewController,您可以转到第二个 viewController(以及 GameScene)只有按下按钮.

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.

有两件事要做:释放当前的 SKScene(在您的情况下为 GameScene)并呈现初始视图控制器"或您的 MenuViewController.

There are two things to do: deallocate the current SKScene (in your case the GameScene) and present the "initial view controller" or your MenuViewController.

为此,我使用 "Hello world" Sprite-kit 模板和 protocol/delegate 方法来扩展 SKSceneDelegate <一个 href="https://developer.apple.com/reference/spritekit/skscenedelegate" rel="nofollow noreferrer">类.如您所见,我们可以关闭场景(呈现 nil)并在 GameViewController 上调用外部方法来呈现 MainViewController

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

为了确保这两个操作都能成功,我还使用了两个 print 仅用于调试:

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("
 THE SCENE ((type(of: self))) WAS REMOVED FROM MEMORY (DEINIT) 
")
    }
}

输出:

这篇关于关闭 SKScene 返回 UIKit 菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆