0

I have a similar question like the guy in this thread How to get from SKScene to UIViewController?. First I should say I'm a totally beginner and it's all new for me.

My main menu (the first screen when my app did load) is here:

class MenuVC: UIViewController {

... }

The interactions of my app (game) could be made here:

    //
//  GameScene.swift
//  Doodle Pong
//
//  Created by Daniel Kloe on 28.02.17.
//  Copyright © 2017 Daniel Kloe. All rights reserved.
//

import SpriteKit
import GameplayKit
import Foundation
import UIKit


class GameScene: SKScene {

//let storyboard = UIStoryboard(name: "Main", bundle: nil)

//let MenuVC = storyboard.instantiateViewController(withIdentifier: "MenuVC")

//MenuVC.view.frame = (self.view?.frame)!

//MenuVC.view.layoutIfNeeded()


//UIView.transition(with: self.view!, duration: 0.3, options: .transitionFlipFromRight, animations:

//{

//self.view?.window?.rootViewController = vc

//}, completion: { completed in

//})



var ball = SKSpriteNode()
var enemy = SKSpriteNode()
var main = SKSpriteNode()
var score = [Int] ()

var topLbl = SKLabelNode()
var btmLbl = SKLabelNode()

override func didMove(to view: SKView) {

    topLbl = self.childNode(withName: "topLabel") as! SKLabelNode
    btmLbl = self.childNode(withName: "btmLabel") as! SKLabelNode

    ball = self.childNode(withName: "ball") as! SKSpriteNode
    enemy = self.childNode(withName: "enemy") as! SKSpriteNode
    main = self.childNode(withName: "main") as! SKSpriteNode


    let border = SKPhysicsBody(edgeLoopFrom: self.frame)
    border.friction = 0
    border.restitution = 1
    self.physicsBody = border

    startGame()

}

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

    for touch in touches{


       // let gameSceneTemp = GameScene(fileNamed: "GameScene")
       // self.scene?.view?.presentScene(gameSceneTemp, transition: SKTransition.doorsCloseHorizontal(withDuration: 0.01))

        let location = touch.location(in: self) //die location wird mit dem Berühren auf dem Bildschirm beschrieben

        if currentGameType == .TwoPlayer{

            if location.y > 0{

                enemy.run(SKAction.moveTo(x: location.x, duration: 0.01)) //Der "main Balken" wird zu den location bewegt
            }

            if location.y < 0{

                main.run(SKAction.moveTo(x: location.x, duration: 0.01)) //Der "main Balken" wird zu den location bewegt

            }

        }

        else{

            main.run(SKAction.moveTo(x: location.x, duration: 0.01)) //Der "main Balken" wird zu den location bewegt

        }


    }
}

func startGame(){

    score = [0,0]
    topLbl.text = "\(score[1])"
    btmLbl.text = "\(score[0])"

    //let delay = SKAction.wait(forDuration: 2000)
    //self.run(delay) //evtl. Wartezeit 2s, funktioniert noch nicht richtig

    ball.physicsBody?.applyImpulse(CGVector(dx: 20, dy: 20))

}

func addScore(playerWhoWon : SKSpriteNode){


    ball.position = CGPoint(x: 0, y: 0)
    ball.physicsBody?.velocity = CGVector(dx: 0, dy: 0)


    if playerWhoWon == enemy{

        score[1] += 1
        ball.physicsBody?.applyImpulse(CGVector(dx: 32, dy: 27))


    }

    else if playerWhoWon == main{


        score[0] += 1
        ball.physicsBody?.applyImpulse(CGVector(dx: -32, dy: -27))

    }

    topLbl.text = "\(score[1])"
    btmLbl.text = "\(score[0])"


}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    for touch in touches{

        let location = touch.location(in: self) //die location wird mit dem Berühren auf dem Bildschirm beschrieben

        if currentGameType == .TwoPlayer{

            if location.y > 0{

                enemy.run(SKAction.moveTo(x: location.x, duration: 0.01)) //Der "main Balken" wird zu den location bewegt
            }

            if location.y < 0{

                 main.run(SKAction.moveTo(x: location.x, duration: 0.01)) //Der "main Balken" wird zu den location bewegt

            }

        }

        else{

            self.topLbl.zRotation = CGFloat(2 * M_PI)
           // UIView.animate(withDuration: 0, animations: ({

               // self.topLbl.zRotation = CGFloat(2 * M_PI) //CGFloat(.pi / 4.0)

           // }))

            main.run(SKAction.moveTo(x: location.x, duration: 0.01)) //Der "main Balken" wird zu den location bewegt

        }

    }


}

override func update(_ currentTime: TimeInterval) {

    switch currentGameType{

    case .Easy:
        enemy.run(SKAction.moveTo(x: ball.position.x, duration: 1.0))
        break

    case .Medium:
        enemy.run(SKAction.moveTo(x: ball.position.x, duration: 0.5))
        break

    case .Extreme:
        enemy.run(SKAction.moveTo(x: ball.position.x, duration: 0.08))
        break

    case .TwoPlayer:

        break

    }

     //Called before each frame is rendered
    if ball.position.y <= main.position.y - 20{
        addScore(playerWhoWon: enemy)

    }

     else if ball.position.y >= enemy.position.y + 20{
       addScore(playerWhoWon: main)


    }

}



@IBAction func backToMainMenu(_ sender: Any) {
     //self.view?.window?.rootViewController
    self.view?.window!.rootViewController?.dismiss(animated: false, completion: nil)
}


}

In my function "backToMainMenu" I try to go back to the MenuVC but I get a warning "Expression of type 'UIViewController?' is unused" and if I try it in the simulator the simulator will crash.

I'm thankful for every kind of help :).

dani chloé
  • 23
  • 1
  • 5

1 Answers1

0

try:

self.view.window!.rootViewController?.dismiss(animated: false, completion: nil)

This should dismiss all views above the rootViewController

edit:

This may work for you as we define the ViewController, make sure in your Storyboard your MenuVC has an Identifier:

let storyboard = UIStoryboard(name: "Main", bundle: nil)

        let vc = storyboard.instantiateViewController(withIdentifier: "MenuVC") // Make sure is the same identifier as in the storyboard.

        vc.view.frame = (self.view?.frame)!

        vc.view.layoutIfNeeded()


        UIView.transition(with: self.view!, duration: 0.3, options: .transitionFlipFromRight, animations:

            {

                self.view?.window?.rootViewController = vc

        }, completion: { completed in

        })

    }

Edit:

It seems the best way to do this, is to host your SKScene class in another view controller. What I suggest is to create another ViewController where your SKScene will be, for example SKViewController. Embed your MenuVC inside a navigationController clicking on it in storyBoard, clicking Editor (from the menu at the top) > Embed in > Navigation Controller. Edit your MenuVC so that instead of opening your Scene, you just segue to the SKViewController, and open the scene there. To do this just create a segue from MenuVC in storyboard, with an identifier "MenuToSKScene" for example, and when you want to open the scene, from your MenuVC just do:

  self.performsegue(with identifier: "MenuToSKScene", sender: self)

Then do whatever you do currently in MenuVC in SKViewController instead to open the scene.

This will send you to the SKViewController, which has your SKScene class. Then when you want to go back to the menu, all you have to do is:

 self.dismiss(animated: true, completion: nil)

or create a segue from SKViewController to MenuVC with identifier "SKSceneToMenu" and call:

self.performsegue(with identifier: "SKSceneToMenu", sender: self)

So essentially, don't open the SKScene from MenuVC, but have a separate viewController SKViewController that you open when you want to open your scene, so that you can jump back to the menu easily.

Peter Ruppert
  • 1,067
  • 9
  • 24
  • I had to change the code a little bit to --> self.view?.window!.rootViewController?.dismiss(animated: false, completion: nil). The syntax seems to be correct now but if I press the main menu button the app crashes (-> 0x108929e28 <+72>: movq -0x20(%rbp), %rdi). – dani chloé Mar 11 '19 at 18:17
  • Is your MenuVC in a navigationController? – Peter Ruppert Mar 11 '19 at 18:25
  • @danichloé try the solution above in my edit it should work from an SKScene defining the ViewController and then using a Transition. – Peter Ruppert Mar 11 '19 at 18:30
  • Thank you. My MenuVC is in a View Controller that has a relationship to a Navigation Controller. Do you mean with "...make sure in your Storyboard your MenuVC has an Identifier" that I have to insert in the View Controller of my MenuVC a Storyboard ID? – dani chloé Mar 11 '19 at 18:58
  • @edey yes thats right, where `(withIdentifier: "MenuVC")` is the same as the Storyboard ID you gave the MenuVC ( I just put MenuVC as the identifier) – Peter Ruppert Mar 11 '19 at 19:01
  • Ok, great. I put your code into my "class GameScene: SKScene {.." but I get this warning "Cannot use instance member 'storyboard' within property initializer; property initializers run before 'self' is available". And if I try "self.storyboard...." I will get "Value of type '(GameScene) -> () -> GameScene' has no member 'storyboard'". I think we are close to get it, maybe there is a small issue that I don't get :P – dani chloé Mar 11 '19 at 19:12
  • try adding `import UIKit` and `import Foundation` at the top? – Peter Ruppert Mar 11 '19 at 19:14
  • Now added, but the problem seems to be the same. class GameScene: SKScene { let storyboard = UIStoryboard(name: "Main", bundle: nil) let MenuVC = storyboard.instantiateViewController(withIdentifier: "MenuVC") //Cannot use instance member 'storyboard' within property initializer; property initializers run before 'self' is available MenuVC.view.frame = (self.view?.frame)! //Expected declaration MenuVC.view.layoutIfNeeded() ..... – dani chloé Mar 11 '19 at 19:44
  • I think it is to do with your `@IBAction func` Is it a button? Can I you update your question with the full SKScene class? I think you need to make a button, make a seperate function, and then add that function as the target of the button viewDidLoad() for example. – Peter Ruppert Mar 11 '19 at 19:56
  • @danichloé made an edit, it seems the best solution is to use another ViewController to host your SKScene, then you can segue between them easily. – Peter Ruppert Mar 12 '19 at 00:36
  • problem solved with https://www.youtube.com/watch?v=DvBO9-KZUP4&t=273s :) – dani chloé Mar 12 '19 at 18:39
  • @danichloé glad you found the solution! Good luck! – Peter Ruppert Mar 12 '19 at 21:27