Search code examples
iosswiftoopsprite-kit

Class Instances in Swift/Spritekit


I am a Swift noob and could really use some advice. I am trying to create a class that builds a block in my SpriteKit scene by passing a few paramters for size and color through to the class. The code builds and the blocks DO appear in the scene BUT by printing out the node tree, I can see I am getting an empty node/container wrapping my blocks (maybe from the two addChilds?!). I am guessing I am doing more than one thing wrong here and would really love to understand how to structure this cleaner.

In my scene:

for i in 1...4! {
    let block = Block(blockCount: i, blockSize: "Large", blocksColor: blocksColor)
    blocksContainer?.addChild(block)
}

And my class:

import SpriteKit

class Block: SKShapeNode {
    
    var block : SKSpriteNode?
    
    private var blockCount: Int
    private var blockSize: String
    private var blocksColor: UIColor

    init(blockCount: Int?, blockSize: String?, blocksColor: UIColor?) {
        
        self.blockCount = blockCount!
        self.blockSize = blockSize!
        self.blocksColor = blocksColor!
        
        super.init()
        
        var blockSizePixels: Int
        if (blockSize == "XLarge") {
            blockSizePixels = 232
        } else if (blockSize == "Large") {
            blockSizePixels = 152
        } else if (blockSize == "Medium") {
            blockSizePixels = 104
        } else if (blockSize == "Small") {
            blockSizePixels = 56
        } else {
            blockSizePixels = 32
        }
        
        //build block
        block = SKSpriteNode(color: blocksColor!, size: CGSize(width: blockSizePixels, height: blockSizePixels))
        block!.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: blockSizePixels, height: blockSizePixels))
        block!.position = CGPoint(x: Int.random(in: -100...100), y: 300)
        block!.physicsBody!.friction = 0.05
        block!.physicsBody!.restitution = 0.6
        block!.physicsBody!.mass = 1.0
        block!.name = "block" + String(self.blockCount)
        self.addChild(block!)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

And my node tree print out comes out as:

Optional("blocksContainer")
nil <- empty node
Optional("block1")
nil
Optional("block2")
nil
Optional("block3")
nil
Optional("block4")

Solution

  • With help from @Paulw11 I refactored my class to be the following... taking out the multiple sprites and replacing them with a path. Nice!

    import SpriteKit
    
    class Block: SKShapeNode {
        
        private var blockCount: Int
        private var blockSize: String
        private var blocksColor: UIColor
    
        init(blockCount: Int?, blockSize: String?, blocksColor: UIColor?) {
            
            self.blockCount = blockCount!
            self.blockSize = blockSize!
            self.blocksColor = blocksColor!
            
            super.init()
            
            //isUserInteractionEnabled = false
            
            var blockSizePixels: Int
            if (blockSize == "XLarge") {
                blockSizePixels = XLarge
            } else if (blockSize == "Large") {
                blockSizePixels = Large
            } else if (blockSize == "Medium") {
                blockSizePixels = Medium
            } else if (blockSize == "Small") {
                blockSizePixels = Small
            } else {
                blockSizePixels = Tiny
            }
            
            //build block
            self.path = CGPath(rect: CGRect(origin: CGPoint(x: -blockSizePixels/2, y: -blockSizePixels/2), size: CGSize(width: blockSizePixels, height: blockSizePixels)), transform: nil)
            self.fillColor = blocksColor!
            self.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: blockSizePixels, height: blockSizePixels))
            self.position = CGPoint(x: Int.random(in: -100...100), y: 300)
            self.physicsBody!.friction = 0.05
            self.physicsBody!.restitution = 0.6
            self.physicsBody!.mass = 1.0
            self.name = "block" + String(self.blockCount)
    
        }
        
        class func classMethod() {
            print ("hello from the class method")
        }
        
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
    }