Using .sks files to layout sprites

Hi, I'm in the process of learning Sprite Kit and finished reading the getting started guide as well as watching the best practices video. I recently dove in and started experimenting. One of the first things I wanted to do was create a Button class that would allow me to create a button using a default state sprite and a hover state sprite. Additionally, I wanted to detect when the button is pressed within the class rather than keeping a list of sprites and adding conditional logic within the touchesBegan handler in the scene file. Creating the class turned out to be pretty straight forward and accomplishes the job quite well. One key aspect here is that my class extends SKNode and receives two SKSpriteNode's so that it can display the correct state of the button. If I dynamically add this node at run-time it works as expected. However, I would like to separate my positional data from my code, as mentioned in the best practices video. I believe I have a couple of options here:


1. I can put the display data into a .plist file and position my items dynamically at runtime

2. I can use the scene's sks file to position data


I would like to go with option 2 as the sks editor appears to be a useful tool. There is just one problem... I can add SKNode's, and SKSpriteNode's but I cannot add my Button class that extends SKNode. The best practices video states that the data from this file is loaded through a function in the view controller: unarchiveFromFile. I thought there might be a way to look at the archive data, find the node I'm referencing, and convert it at run-time. Unfortunately, I haven't found a good way to accomplish this. One solution I could use is to search for the sprite nodes at run time, remove them from the scene, instantiate a new Button class using those sprites and then add the Button (which extends SKNode) to the scene. This does not seem like a good solution to me. There has to be a way that is considered a best practice to add classes that extend SKNode and SKSpriteNode to the sks file or to somehow dynamically change the class like they are doing in unarchiveFromFile with the scene. Is anyone else experiencing this issue and does anyone know of a good solution?


Regards,


Will

Replies

Here is the code i'm using for reference. Note that this code is working but it feels akward that I am having to create a container node with my sprites and dynamically remove the sprites and add them to my new button class. If you can think of a better way to do this please share!


import SpriteKit
class Button: SKNode {
   
    let normal:SKNode;
    let hover:SKNode;
   
    init(containerNode:SKNode) {
        normal = containerNode.childNodeWithName("normal")!
        hover = containerNode.childNodeWithName("hover")!
        self.hover.hidden = true
       
        super.init()
        self.userInteractionEnabled = true
        normal.removeFromParent()
        hover.removeFromParent()
        self.addChild(normal)
        self.addChild(hover)
        self.zPosition = 1
        containerNode.addChild(self)
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
   
    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
        normal.hidden = true;
        hover.hidden = false;
    }
    override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
        normal.hidden = false;
        hover.hidden = true;
    }
}


Then, in the scene file, all I have to do is:


override func didMoveToView(view: SKView) {
    playButton = Button(containerNode: childNodeWithName("/background/playButtonContainer")!)
}

You do that through the class inspector utility panel. Select the node, then select the View > Utilities > Show Custom Class Inspector menu item or use Cmd-Option-0 to show the Utilities panel and select the inspector's icon (looks like a driver's license).


This same mechanism is used with xib and storyboard editors.

This is basically what I do as well. You can create an SKEmitterNode (Particle system) and a SKSceneNode from a .SKS file, but not anything else. For other kinds of nodes you have to put them in a scene, then in loading code take them out of that scene with `removeFromParent()`.