Swift multiple scenes - swift

I have made a swift SpriteKit game but now I want to add a menu scene(and eventually a lose scene). So what I did was
I created a new scene called Menu scene.
I edited GameViewController and changed it to load menu scene(it worked).
In MenuScene.swift I put some code in so when a sprite was clicked it would run this code:
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
let scene = GameScene(size: size)
self.view?.presentScene(scene, transition:reveal)
But when I click the button it flips round to the next scene and immediately crashes.
So my question is: Am I doing this the right way and if I am why does it crash?

It turns out I wasn't deleting a particle emitter so I put in a bit of code to delete it just before the transition and it worked.

If you do, it should work:
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
let scene = GameScene(size: self.frame.size)
let skView = view as SKView!
skView.presentScene(scene, transition:reveal)
I hope this works for you.

Since you're in sprite kit , it's wrong to use :
self.view?.presentScene(scene, transition:reveal)
You should do the following :
let scene = GameScene(size: view.bounds.size)
let skView = view as SKView
//skView.showsFPS = true
//skView.showsNodeCount = true
//skView.ignoresSiblingOrder = true
//scene.scaleMode = .ResizeFill
skView.presentScene(scene, transition:reveal)

Related

How to transition between scenes in sceneKit SCNView

Hey there's an error in this code that I tried to modify for SceneKit. Im trying to goo from a sprite kit scene to a SCNcene
Code Not Working Below:
let scene = PlayController()
let scnView = self.view as! SCNView
scnView.scene = PlayController()
scene.size = scnView.bounds.size
scene.scaleMode = .AspectFill
let reveal = SKTransition.fadeWithDuration(0.45)
scnView.presentScene(scene, transition: reveal)
Code Working but for SpriteKit Only Below:
let scene = GameScene()
let sKView = self.view! as! SKView
sKView.ignoresSiblingOrder = true
scene.size = sKView.bounds.size
scene.scaleMode = .AspectFill
let reveal = SKTransition.fadeWithDuration(0.45)
sKView.presentScene(scene, transition: reveal)
You have to:
import SceneKit
import SpriteKit
before the auto completion recognises what you want. Now you can type scnView.presentScene(...
The "presentScene" API in SceneKit has some extra arguments missing in your code. You need to specify the incoming point of view and provide a completion handler (both can be nil).
- (void)presentScene:(SCNScene *)scene withTransition:(SKTransition *)transition incomingPointOfView:(nullable SCNNode *)pointOfView completionHandler:(nullable void (^)())completionHandler NS_AVAILABLE(10_11, 9_0);

Unable to make a button that will transition you to main menu with Spritekit Swift

I'm new to Swift and Spritekit and having trouble with implementing a button or imagebutton that will take you to the main menu from the GameScene. All I want to do is to make a button that will display a dialog that will tell you if you want to return to the main menu.
For example is there a way to make a dialog that will transition you to other scenes with the code below?
let skview = self.view as! GameSKView!
skview.score = score
let scene = MainMenuScene(size: self.size)
let tr = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1)
scene.scaleMode = SKSceneScaleMode.AspectFill
skview.presentScene(scene,transition: tr)
try this
func changeScene() {
let newScene = MainMenuScene(size: self.size)
let theTransition = SKTransition.revealWithDirection(SKTransitionDirection.Down, duration: 1)
newScene.scaleMode = .AspectFill
scene?.view?.presentScene(newScene, transition: theTransition)
}
Currently developing a button that works like a uibutton using spritekit. Here is what I have, it may be slightly overkill for what you want but here it is.https://github.com/marcJV/SKAToolKit/tree/swift?files=1
It will be pulled over to SKAToolKit when as we are porting it to swift. There is also an example project showing off how to use it. Also there is a lack of a proper readme at this point, but the example should have everything you need. This is using swift 2.0

How to make your button do something only after it does what you want like a completion block

How do I make it so that the scene does not change until after both of those functions a finished?
Thanks
Code:
let location = touch.locationInNode(self)
if self.nodeAtPoint(location) == self.playButton {
PlayPressDown()
PressedPlay()
println(" PlayBtn Going to game play.")
var scene = SecondScene(size: self.size)
let sKView = self.view! as SKView
sKView.ignoresSiblingOrder = true
scene.size = sKView.bounds.size
let reveal = SKTransition.fadeWithDuration(1.1)
sKView.presentScene(scene, transition: reveal)
Don't link your button directly to a segue. Link it to an IBAction. Write code in your IBAction that does what you want, then invokes the segue using performSegueWithIdentifier after your steps are complete.

Swift -- Sprite Kit -- Scenes have different sizes

I am programming a game but I have one problem. I have two scenes. (1. GameScene 2. PlayScene). The GameScene displays the PlayButton. If you press the PlayButton the PlayScene will be displayed. The PlayScene displays the game. If you lose the Game, the GameScene will be presented again.
GameScene --> PlayScene --> GameScene
This is the code, which is in the GameScene and presents the PlayScene.
if self.nodeAtPoint(location) == self.playButton { // Wenn position des klicks gleich mit position des play button
println("Go to the game")
var scene = PlayScene(size: self.size)
let skView = self.view! as SKView
skView.ignoresSiblingOrder = true
scene.scaleMode = .ResizeFill
scene.size = skView.bounds.size
skView.presentScene(scene)
}
This is the code, which is in the PlayScene and presents the GameScene again.
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
let skView = self.view as SKView!
skView.ignoresSiblingOrder = true
scene.size = skView.bounds.size
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
My Problem is that the GameScene has first a different size than the GameScene which is presented after the PlayScene. I can't show photos because I don't have 10 reputations -.-, but I can explain it. For example: The PlayButton in the GameScene, which is presented after the program starts, is smaller than the PlayButton, which is presented in the GameScene after the PlayScene is presented.
I tried to change the scaleModes but that didn't work.
Here are the links for the photos, which show my problem.
This is the "second" GameScene presented:
https://drive.google.com/open?id=0B57TI4Xur5Fldy1EcVh6NmVIdm8&authuser=0
This is the "first" GameScene presented:
https://drive.google.com/open?id=0B57TI4Xur5FlR3ZXT2NFSEZRZHc&authuser=0
The issue could be that you aren't using the same settings as you are for the first scene. Try this.
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
let skView = self.view as SKView!
skView.ignoresSiblingOrder = true
scene.size = self.size
scene.scaleMode = self.scaleMode
skView.presentScene(scene)
}
Thank you but it didn´t worked. I tried some other changes and it worked but I don´t know why.
if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
let skView = self.view as SKView!
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
Now both Scenes have the same size.

Transitioning back to gamescene.swift causes error "'Attemped to add a SKNode which already has a parent"

My app contains two scenes. Playscene.swift and gamescene.swift.
Transitioning from gamescene to playscene (where play takes place) works perfectly. However, once a gameover is reached, I have a "replay" button appear allowing the user to return back to gamescene.swift. Upon transitioning back it crashes with an error "Attempted to add a SKNode which already has a parent." Is there a correct way to transition back to a home screen or restart the game so I don't receive the error? Thank you for all your help!!
if self.nodeAtPoint(touchLocation) == self.replay {
let scene = GameScene(size: self.size)
let skView = self.view as SKView!
scene.size = skView.bounds.size
self.view?.presentScene(scene)
let transition = SKTransition.crossFadeWithDuration(1.0)
transition.pausesOutgoingScene = false
skView.presentScene(scene, transition: transition)
}
}
Gamescene.swift error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent: <SKLabelNode> name:'(null)' text:'Highscore:' fontName:'Avenir-Black' position:{344, 549}'
*** First throw call stack:
I feel stupid. I had added a breakpoint and wasn't paying attention. its safe to say its time for bed.
You are trying to present the same scene twice :
self.view?.presentScene(scene)
skView.presentScene(scene, transition: transition)
Maybe you wan't to do like so :
if self.nodeAtPoint(touchLocation) == self.replay {
let skView = self.view as SKView!
let scene = GameScene(size: skView.bounds.size)
// Might also work with the following line instead :
// let scene = GameScene(size: self.frame.size)
let transition = SKTransition.crossFadeWithDuration(1.0)
transition.pausesOutgoingScene = false
self.view?.presentScene(scene, transition: transition)
}
You might be declaring that SKLabelNode outside of the GameScene class, making the SKLabelNode global, you should declare it inside the class so it dies when scene A transitions to scene B.