Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading an SKNode from a .sks scene file in Swift

I want to use multiple .sks files to store some complex SKNode hierarchies such as game menus. I have a background with moving objects I'd like to keep throughout the game, so presenting different SKScenes doesn't achieve what I want. I am restricted to one scene, but I'd still like to separate out my code from artwork as much as possible, and trying to squeeze everything into one .sks file gets crowded quick!

So I'd like to have multiple .sks files, each one storing a different menu: titleMenu, getReadyMenu, pauseMenu, gameOverMenu, with all the elements of each menu a descendent of an empty SKNode.

I have managed to load the files, cache the SKNode in a local variable, and display it on screen, but when I click on the buttons for the menu, the touchesBegan function is never called, when I click just outside the buttons on the menu it is normal responder chain functionality. Very perplexing.

I am sure my solution is so convoluted that is would be simpler to just ask if someone could post an example of grabbing out just an SKNode (and children) from a .sks file, without presenting a new scene.

So, can someone please post an example of this in Swift?

like image 619
mogelbuster Avatar asked Aug 18 '15 07:08

mogelbuster


1 Answers

When creating a new project, select the Game template. GameViewController.swift will have the following extension implementation defined at the top of the file:

extension SKNode {
    class func unarchiveFromFile(file : String) -> SKNode? {
        if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
            var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
            var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)

            archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
            let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
            archiver.finishDecoding()
            return scene
        } else {
            return nil
        }
    }
}

I haven't done this in Swift, but am reasonably experienced with this stuff using Objective-C and it works nicely.

like image 152
CloakedEddy Avatar answered Oct 01 '22 06:10

CloakedEddy