Unable to pass a variable to a scene in spritekit in swift - swift

I'm currently having trouble with passing variables to a scene in spritekit (swift). In android when moving to a different activity, I just set the parameter to the Intent and simply get the variable. But since I'm new to spritekit and swift, i find it difficult. Is there a clear way to pass a variable to the scene ? I have a sample code below that I tested but did not work.
class GameSKView: SKView {
var mylevel = 0
}
//Inside my main GameScen
let gameView = self.view as GameSKView
sample.text = "my level is :\(gameView.mylevel)"

Try this:
class GameSKView: SKView {
internal var mylevel = 0
}
And inside you main game scene
if let gameView = self.view as GameSKView {
sample.text = "my level is :\(gameView!.mylevel)"
}

Finally found the solution.
In order to use the custom SKView, I have done the following procedures.
Open the Idenity inspector in the Main.storyboard
Replace the [SKView] inside the Custom Class with your [customSKView]
, In my case GameSKView
Save. That was all I needed to do.

Related

Assigning SCNScene to SCNView - found nil while unwrapping Optional value

Recently, I decided to apply my previous knowledge in C++ and Python to learning Swift. After which, I decided to see what I could do with the SceneKit framework. After hours of checking through the documentation, and consulting a tutorial, I have to wonder what's going wrong with my code:
class GameViewController: UIViewController {
var gameView:SCNView!
var gameScene:SCNScene!
var cameraNode:SCNNode!
override func viewDidLoad() {
super.viewDidLoad()
initScene()
initView()
initCamera()
}
func initView() {
//initialize the game view - this view holds everything else in the game!
gameView = self.view as! SCNView
//allow the camera to move to gestures - mainly for testing purposes
gameView.allowsCameraControl = true
//use default lighting while still practicing
gameView.autoenablesDefaultLighting = true
}
func initScene() {
//initialize the scene
gameScene = SCNScene()
//set the scen in the gameView object to the scene created by this function
gameView.scene = gameScene
}
func initCamera() {
//create a node that will become the camera
cameraNode = SCNNode()
//since a node can be any object in the scene, this needs to be set up as a camera
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3 (x:0, y:5, z:15)
}
}
After more checking through the documentation and making sure that I was now copying from the tutorial directly to get it to work, I still have no luck with this. According to a lot of the other questions I found here on StackOverflow, it looks like it has something to do with the forced unwrapping, the exclamation points, but I'm not exactly sure why that is.
I've probably been staring the answer in the face combing through this documentation, but I'm not quite seeing what the problem is.
Also, apologies if my comments are a bit long and/or distracting.
You have the following problems:
1) you should re-order the initializations in your viewDidLoad, doing so:
initView() // must be initialized before the scene
initScene() // you have been crashing here on getting `gameView.scene`, but gameView was nil
initCamera()
2) cameraNode is not attached on the rootNode, so you may add the following code at the end of initCamera:
gameScene.rootNode.addChildNode(cameraNode)

Keeping the game paused after app become active?

It is my first post on this forum and I apologize in advance if I am doing something not in the right way ! :)
I am making an iphone game with Swift & SpriteKit and I am currently facing a problem. When my app is going to background it calls a function pause (cf. below) but it automatically unpause when the game resumes.
I have seen this very interesting post : Spritekit - Keep the game paused when didBecomeActive (and How to keep SpriteKit scene paused when app becomes active?) but I am stuck.
I don't know how to implement the new SKView class as my View is configured as shown in the below code...
This is how my application works :
class GameViewController: UIViewController {
var scene: GameScene!
override func viewDidLoad() {
super.viewDidLoad()
// Configure the View
let SkView = view as! SKView
SkView.multipleTouchEnabled = true
// Create and configure the scene
scene = GameScene(size: SkView.bounds.size)
scene.scaleMode = .AspectFill
// Present the scene
SkView.presentScene(scene)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("PauseWhenBackGround:"), name:"PauseWhenBackGround", object: nil)
}
func PauseWhenBackGround(notification : NSNotification) {
if scene.Pausing == false{
scene.Pause()
}
}
I've tried the following :
I added a new class which is :
class GameSceneView : SKView {
func CBApplicationDidBecomeActive() {
}
}
Then, I tried to set my view as let SkView = view as! GameSceneView but I got an error saying that I cannot cast the view to MyProjectName.GameSceneView()...
I also tried the following : let SkView! = GameSceneView() as GameSceneView! but I end up with a gray background scene...
Does anyone knows how I can implement the new SKView class to prevent the CBApplicationDidBecomeActive() bug from happening so that the game does not unpause when becoming active ?
Thank you very much in advance ! :)
I think a better way is instead of pausing the whole scene you could create a worldNode in your GameScene and add all the sprites that need to be paused to that worldNode. Its better because if you pause the scene you cannot add pause menu nodes or use touches began etc. It basically gives you more flexibility pausing a node rather than the whole scene.
First create the world node (make global property if needed)
let worldNode = SKNode()
addChild(worldNode)
Than add all the sprites you need paused to the worldNode
worldNode.addChild(sprite1)
worldNode.addChild(sprite2)
Create an enum for your different game states
enum GameState {
case Playing
case Paused
case GameOver
static var current = GameState.Playing
}
Than make a pause func in your game scene
func pause() {
GameState.current = .Paused
//self.physicsWorld.speed = 0 // in update
//worldNode.paused = true // in update
// show pause menu etc
}
And call it like you did above using NSNotification or even better using delegation.
I prefer this method way more than pausing the scene from the gameViewController and also pausing the whole scene.
Create a resume method
func resume() {
GameState.current = .Playing
self.physicsWorld.speed = 1
worldNode.paused = false
// remove pause menu etc
}
and finally add this to your update method
override func update(currentTime: CFTimeInterval) {
if GameState.current == .Paused {
self.physicsWorld.speed = 0
worldNode.paused = true
}
Spritekit sometimes tends to resume the game when the app becomes active again or when an alert such as for in app purchases is dismissed. To avoid this I always put the code to actually pause the game in the update method.
Hope this helps.

SpriteKit: Add SKSpriteNodes To The View

I basically want to add a SKSpriteNode to the screen and I have no idea where the mistake it. So I include pictures of my three classes participating in this problem. I created a class for all the background stuff. There I use the function addChild() to add my 56 Nodes to the View but they do not appear on the screen. Theoretically (for me) everything should work.
Hopefully you can help me adding the Nodes to the screen!
Edit: Updated the pictures.
When you call this:
GameScene().addChild(image)
you every time inside for create the local GameScene object, add image to this object and when you move to the next iteration of the loop, this object is destroyed. In fact, after your loop thire is no one GameScene object.
Second, you don't need to use var image = SKSpriteNode() in your hintergrund object. You every time set this reference to new object.
You have the cross references in code, try to make somthing like this:
class GameScene: SKScene {
...
override func didMoveToView(view: UIView) {
hintergrund.setBackgroundForScene(self, width: screenWidht)
}
}
class hintergrund {
...
class func setBackgroundForScene(gameScene: GameScene, width: CGFloat) {
...
for (...) {
...
gameScene.addChild(image)
}
}
}

How do I call a function from another scene?

My game unlocks a level every-time they beat a level. So the problem im having is when the user beats level one I want it to show a button of level 2 thats in my GameScene. When I call the function unlockLevelTwo() in my Level1.swift file it doesn't show up in my GameScene.swift file. What am I doing wrong?
//GameScene.Swift
func unlockLevelTwo() {
let fadeIn = SKAction.fadeInWithDuration(0.5)
levelTwo.position = CGPointMake(self.size.width / 2.0, self.size.height / 2.2)
levelTwo.zPosition = 20
levelTwo.setScale(0.8)
levelTwo.alpha = 0
levelTwo.runAction(fadeIn)
levelTwo.name = "leveltwo"
addChild(levelTwo)
}
//Level1.swift
if firstBody.categoryBitMask == HeroCategory && sixthBody.categoryBitMask == GoldKeyCategory{
//calling this function from my gameScene to unlock levelTwo button.
var gameScene = GameScene()
gameScene.unlockLevelTwo()
}
This function:
if firstBody.categoryBitMask == HeroCategory && sixthBody.categoryBitMask == GoldKeyCategory{
//calling this function from my gameScene to unlock levelTwo button.
var gameScene = GameScene()
gameScene.unlockLevelTwo()
}
is creating a new GameScene object and adding the childNode "levelTwo" to that gamescene. Instead, you need to call unlockLevelTwo() on the actual GameScene that is currently presented to the user.
I imagine somewhere in Level1.Swift there is a reference to the current GameScene (the one the user is interacting with)? Call the function on that one.
EDIT:
In essence, what you must do is keep a reference to your original GameScene object somewhere in your code, which I will henceforth refer to it as MyScene. That way, when in Level1.swift, you can reference MyScene and add buttons, levels, whatever you like to it without creating a new one like you did here:
var gameScene = GameScene()
gameScene.unlockLevelTwo()
Instead, you would just call
MyScene.unlockLevelTwo().
If Level1 is a view of some sort, or an object that gets created, in the init function you could pass in your GameScene object and set it like so
class Level1 : (Type) {
var myScene: GameScene!
init(myScene: GameScene) {
self.myScene = myScene)
}
}
Something like that, hope it helps!

Replace Scene in Spritekit with swift

I want to replace scene in my project.
I have made project using spritekit and swift in xcode version 6
Now when I try to write replace scene code using this
for touch:AnyObject in touches
{
let location=touch.locationInNode(self)
if self.nodeAtPoint(location)==self.playbutton
{
println("Go to the game!")
var scene=PlayScene(size:self.size)
let skView = self.view as SKView //ERROR
}
}
It gives me ERROR:
Downcast from 'SKView?' to 'SKView' only unwraps optionals; did you mean to use '!'?
You have an "optional" problem over here.
Use this instead:
let skView = self.view? as SKView!
You don't need the downcast part, that's what Xcode is saying, not as .....
Remove as.... and just unwrap with let skView = self.view! or an if/let statement if you're not sure about whether its nil:
if let skView = self.view{
skView.presentScene(...)
}
Watch out for strong reference cycles when you replace the scene. Remember the view and scene are together, so..., you'll figure out.