解雇SKScene回到UIKit菜单 [英] dismiss SKScene go back to UIKit Menu
问题描述
一旦我的SpriteKit游戏结束,我想回到我的 UIKit MenuViewController
。从我到目前为止所学到的,使用 协议/委托 是最好的(?)选项,但我无法让它工作。我知道协议可能会超过 GameViewController
的类声明,看起来像这样:
协议GameViewControllerDelegate {
var gameOver:Bool?
}
但我需要帮助从 GameScene
并让它解雇 GameViewController
。以下是该应用程序的骨骼,如果有帮助的话。
MenuViewController
类MenuViewController:UIViewController {
覆盖func viewDidLoad (){
super.viewDidLoad()
}
@IBAction func goToGame(_ sender:UIButton){
performSegue(withIdentifier:toGameSegue,sender: sender.currentTitle)
}
覆盖func prepare(对于segue:UIStoryboardSegue,sender:Any?){
如果让destinationVC = segue.destination为? GameViewController {
如果让item = sender为?字符串{
destinationVC.numberOfPlayers = item
}
}
}
}
GameViewController
class GameViewController:UIViewController {
var numberOfPlayers:String?
覆盖func viewDidLoad(){
super.viewDidLoad()
如果让view = self.view为! SKView? {
if let scene = SKScene(fileNamed:GameScene){
scene.scaleMode = .aspectFill
scene.userData = NSMutableDictionary()
scene.userData ?。setObject(numberOfPlayers!,forKey:numberOfPlayersas NSCopying)
view.presentScene(scene)
}
}
}
.. 。
GameScene
class GameScene:SKScene {
var howManyPlayers:String?
覆盖func didMove(查看:SKView){
如果让numPlayers = self.userData?.value(forKey:numberOfPlayers){
howManyPlayers = numPlayers为?字符串
}
打印(howManyPlayers!)
}
...
这款SpriteKit游戏有一个MenuViewController,一个GameViewController和一个GameScene。当您从MenuViewController按下按钮时,数据将通过segue发送到GameViewController。在GameViewController呈现GameScene之前,它将数据存储在scene的userData变量中,以便GameScene可以访问它。在这个例子中,它是玩家的数量。
我同意Whirwind评论:为什么混合两个不同的框架并使你的生活变得复杂,你只能使用一个viewController来完成所有工作你的游戏?
无论如何,根据你的故事板截图,有2个viewControllers,你可以去第二个viewController(和 GameScene
)仅当您按下按钮时。
有两件事要做:取消分配当前的SKScene(在您的情况下为 GameScene
)并显示初始视图控制器或你的 MenuViewController
。
要做到这一点,我使用Hello world 带有协议/委托方法的Sprite-kit模板,用于扩展 SKSceneDelegate
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:
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:
这篇关于解雇SKScene回到UIKit菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!