Tried to perform an SKTransition for the very first loading of GameScene from GameViewController but nothing seemed to happen. Can't we perform some transition while presenting a scene directly from the GameViewController? It seemed to me quite hilarious that the normal present scene is working but not the one with transition. Here is the code :
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
let scene = GameScene(size: view.bounds.size)
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
//transition
let transition = SKTransition.doorsOpenVertical(withDuration: 2)
// Present the scene
view.presentScene(scene, transition: transition)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
}
class GameScene: SKScene {
override func didMove(to view: SKView) {
self.backgroundColor = SKColor.red
}
}
Please solve the query.
Related
i have the problem, that the GameViewController doesn't load my GameMenu. If i simulate my app it only shows a grey screen with node:0 and the fps count.
Here the Code from GameViewController.swift:
import UIKit
import SpriteKit
import GameplayKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = GameMenu(fileNamed: "GameMenu") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
I tried also the line:
if let scene = SKScene(fileNamed: "GameMenu")
but it changed nothing.
I also added the Custom Class "GameMenu" to the GameMenu.sks
I think the problem is this if let scene = SKScene(fileNamed: "GameMenu") line.
I have read a lot about this problem but i my case nothing was successful.
I also tried this:
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let gkScene = GKScene(fileNamed: "GameMenu.sks") {
if let skScene = gkScene.rootNode as? SKScene {
// Set the scale mode to scale to fit the window
skScene.scaleMode = .aspectFill
// Present the scene
view.presentScene(skScene)
}
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
but nothing happend.
You have to load it as GKScene from .sks file and get SKScene from its rootNode attribute.
if let gkScene = GKScene(fileNamed: "GameMenu") {
if let skScene = gkScene.rootNode as? SKScene {
// TODO
}
}
I want to make the background for the scene in GameScene.sks. I have Tile Map Node there, but when I set background in GameScene.swift the picture is on my textures. I want it on the back of the scene.
Here is the code of GameScene.swift:
import SpriteKit
class GameScene: SKScene {
var background = SKSpriteNode(imageNamed: "BackGround")`
override func didMove (to view: SKView) {
background.zPosition = 1
background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
addChild(background)
}
}
Here is the code of GameViewController.swift:
import UIKit
import SpriteKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = SKScene(fileNamed: "GameScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
override var prefersStatusBarHidden: Bool {
return true
}
Does 1 the least z position in your scene? If so, try to set ignoresSiblingOrder property of your SKView to false. Also I would suggest you to read SKScene and SKNode documentations at least. And SpriteKit documentation in general.
I am trying to implement a main menu to my Spritekit game, but whenever I try to present the scene I get a blank gray screen. Here is the code right now, which presents the game itself and not a menu:
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let scene = GameScene(fileNamed:"GameScene") {
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
skView.showsDrawCount = true
skView.ignoresSiblingOrder = true
scene.scaleMode = SKSceneScaleMode.AspectFill
skView.presentScene(scene)
}
}
I'm new to this, and I wasn't sure what to do so I tried replacing GameScene with the menu scene, which gave me the gray screen. Any help will be appreciated.
Use this code to load a SKScene file that is created in code only and not in the Scene editor
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if let skView = self.view as? SKView {
if skView.scene == nil {
let scene = MenuScene(size: skView.bounds.size)
skView.showsFPS = false
skView.showsNodeCount = true
skView.showsPhysics = true
skView.ignoresSiblingOrder = true
scene.scaleMode = .aspectFill
skView.presentScene(scene)
}
}
}
and then in your MenuScene file you will need an init func
init(size: CGSize) {
super.init(size: size)
name = "menuScene"
}
I need to deallocate gamescene after the player have finished a level so that the memory is available to load another level of my game. If I don't do that, I have a crash of my app because of memory issues.
I have followed the indications given there:
Swift: Deallocate GameScene after transition to new scene?
But unfortunately, it doesn't work for me. I get an error "Could not cast value 'UIView' to 'SKView' in my GameViewController class. Here is my whole code:
import Foundation
import UIKit
import SpriteKit
class GameViewController: UIViewController {
var scene1: SKScene?
var scene2: SKScene?
var scene3: SKScene?
var skView: SKView?
func nextSceneAction1() {
scene2 = nil
scene3 = nil
skView! = self.view as! SKView
skView!.showsFPS = true
skView!.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView!.ignoresSiblingOrder = true
scene1 = TransitionSigns(size: skView!.frame.size)
scene1!.size.width = 2048
scene1!.size.height = 1536
/* Set the scale mode to scale to fit the window */
scene1!.scaleMode = .AspectFill
let transition = SKTransition.revealWithDirection(.Right, duration: 2)
scene1!.scaleMode = .AspectFill
skView!.presentScene(scene1!, transition: transition)
}
func nextSceneAction2() {
scene1 = nil
scene3 = nil
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
scene2 = TransitionSigns(size: skView.frame.size)
scene2!.size.width = 2048
scene2!.size.height = 1536
/* Set the scale mode to scale to fit the window */
scene2!.scaleMode = .AspectFill
let transition = SKTransition.revealWithDirection(.Right, duration: 2)
scene2!.scaleMode = .AspectFill
skView.presentScene(scene2!, transition: transition)
}
func nextSceneAction3() {
scene1 = nil
scene2 = nil
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
scene3 = TransitionSigns(size: skView.frame.size)
scene3!.size.width = 2048
scene3!.size.height = 1536
/* Set the scale mode to scale to fit the window */
scene3!.scaleMode = .AspectFill
let transition = SKTransition.revealWithDirection(.Right, duration: 2)
scene3!.scaleMode = .AspectFill
skView.presentScene(scene3!, transition: transition)
}
override func viewWillLayoutSubviews() {
// Configure the view.
let skView = self.view as! SKView
skView.showsFPS = true
skView.showsNodeCount = true
/* Sprite Kit applies additional optimizations to improve rendering performance */
skView.ignoresSiblingOrder = true
let scene = MainView(size: skView.frame.size)
scene.size.width = 2048
scene.size.height = 1536
/* Set the scale mode to scale to fit the window */
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return UIInterfaceOrientationMask.AllButUpsideDown
} else {
return UIInterfaceOrientationMask.All
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidDisappear(animated: Bool) {
self.view.removeFromSuperview()
}
override func viewWillDisappear(animated: Bool){
self.view.removeFromSuperview()
}
}
I call the different functions nextSceneAction1(), nextSceneAction2(), and nextSceneAction3() from my other classes with:
let controller1 = GameViewController()
controller1.nextSceneAction1()
or
let controller2 = GameViewController()
controller2.nextSceneAction1()
When the new scene is loaded, I get this error: "Could not cast value of type 'UIView' to 'SKView'. Do you know what is wrong with this code?
By the way, I'm open with all other possibilities to clean old scene from memory before loading a new one so that there is no memory crash during the life of the app.
In general a SKScene automatically deallocates once you transition to a new scene, unless you have a memory leak, so usually you don't have to do anything in particular to free memory.
To see if your scene has deallocated you can add the deinit method
func deinit {
print("scene did deallocate")
}
If this method gets called when you change scenes you know everything correctly deallocated, if it doesn't get called you have a memory leak.
Also you code is faulty, you are creating a new GameViewController instance everytime you change scene instead of accessing the current instance.
let controller2 = GameViewController() // creates new instance of GameViewController
controller2.nextSceneAction1()
You normally only load your 1st scene from your GameViewController and than all other scene changes can be done directly in the SKScene you are in. Don't bother using the GameViewController for this.
In your current SKScene you can change to a new scene like this (e.g from GameScene to MenuScene)
class GameScene: SKScene {
...
func loadMenuScene() {
let menuScene = MenuScene(size: self.size) // use size of current scene
let transition = Some SKTransition
view?.presentScene(menuScene, withTransition: transition)
}
}
Hope this helps
Hello my problem is that when I click on a button to restart my game it will restart, but then if I click on a button that transitions to the MainMenuViewController than the scene will freeze. The interesting thing is that if I restart the game and click on the segue button first it will work properly, but then if I click the restart button the game will then freeze. When clicking on the segue button and it crashes I get the error has no segue with identifier 'GameToMain' when it indeed does work the first time. When I click on the restart game it will just crash with no error. Here is the relevant code for this problem:
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let skView = view as! SKView
let scene = GameScene(size: skView.bounds.size)
skView.showsFPS = true
skView.showsNodeCount = true
skView.ignoresSiblingOrder = false
//skView.showsPhysics = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
scene.viewController = self
}
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var viewController: GameViewController!
This is set up in a func that is called when the player loses:
let tryAgain = SKLabelNode(fontNamed: "Chalkduster")
tryAgain.text = "Try Again?"
tryAgain.color = SKColor.yellowColor()
tryAgain.name = "retryLabel"
tryAgain.fontSize = 28
tryAgain.position = CGPoint(x: size.width/2, y: size.height/2)
playerLayerNode.addChild(tryAgain)
let mainMenuTransition = SKLabelNode(fontNamed: "Chalkduster")
mainMenuTransition.text = "Main Menu"
mainMenuTransition.color = SKColor.yellowColor()
mainMenuTransition.name = "mainMenuTransitionSeque"
mainMenuTransition.fontSize = 20
mainMenuTransition.position = CGPoint(x: size.width/2, y: size.height/2 - 60)
playerLayerNode.addChild(mainMenuTransition)
This is how the labels register and react to being tapped
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in (touches ) {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if (node.name == "retryLabel") {
print("restart")
let gameScene = GameScene(size: self.size)
let transition = SKTransition.doorsCloseHorizontalWithDuration(0.5)
gameScene.scaleMode = SKSceneScaleMode.AspectFill
gameScene.viewController = GameViewController()
self.scene!.view?.presentScene(gameScene, transition: transition)
print("complete Reload")
}
if (node.name == "mainMenuTransitionSeque") {
print("go to main menu")
self.viewController!.performSegueWithIdentifier("GameToMain", sender: self)
print("complete2")
}
I solved the problem with the current code:
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let skView = view as! SKView
let scene = GameScene(size: skView.bounds.size)
//skView.showsFPS = true
//skView.showsNodeCount = true
skView.ignoresSiblingOrder = false
//skView.showsPhysics = true
scene.scaleMode = .AspectFill
scene.viewController = self
skView.presentScene(scene)
}
}
In GameScene
var viewController: GameViewController!
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let location = touch.locationInNode(self)
let node = self.nodeAtPoint(location)
if (node.name == "retryLabel") {
let skView = view as SKView!
let scene = GameScene(size: skView.bounds.size)
skView.ignoresSiblingOrder = false
scene.scaleMode = .AspectFill
scene.viewController = viewController.self
skView.presentScene(scene)
}
if (node.name == "mainMenuTransitionSeque") {
self.viewController.dismissViewControllerAnimated(false, completion: nil)
print("complete2")
}
}
}
}
So basically to restart the scene I copy and pasted the code from the GameViewController into GameScene so that it would restart the scene exactly, but the key was redeclaring the viewController variable. Then to get to the mainMenu I dismissed the view controller (GameScene) instead of creating a new segue so that I do not keep adding more and more scenes on top of each other.