14
votes

I prototype games using shapes, and spritekit was awesome for that before swift.

Now when i try to extend a SKSpriteNode and add my init function, I can't call super.init(color, size).

I have no way to call the code that creates the shape texture.

I need to know how to either call that init function, or how to create the shape texture, so I can override the designated init, then call it using my shape texture.

EDIT: Here is the exact code I'm doing and I do almost the exact same thing in another SKSprite node extended class:

class TetrisCell : SKSpriteNode
{
    let length = 10;
    convenience init(color:UIColor) {
        var size = CGSize(width: length, height: length);

        //Not allowed to call a super's convenience init, must call non-convenience init
        super.init(color: color, size: size);
    }
}

I understand why it won't let me, so I'm looking for another way around. For now, the TetrisCell doesn't have a texture. I'd like to simply use shapes for convenience.

From what I can tell I HAVE to call super.init(texture:,color:,size:) in order to initialize my SKSpriteNode. If there is no way to do the above code, then I'd like to know what they set their SKTexture to, so I can mimic it. Something like super.init(texture: SKTexture.blankTexture) or something. Whatever they put as the texture is manipulated by the color: attribute, while my 1x1 pixel doesn't seem to be affected by the color: attribute.

3
could you paste your code & the error? - jaime
Code added. To be frank I'm very surprised no one else has come across this issue. Does no one prototype games using textureless sprites in spritekit? - Jason McCarrell
For the time being, I created a white 1x1 pixel png and explicitly set that as the texture, rather than using whatever Spritekit uses when you don't specify a texture. - Jason McCarrell
A subclass cannot call it's superclass's convenience initialisers. - user4233369
Correct, that is what i said >> In this case it's ok, because the SKTexture parameter was nillable, which I didn't notice at first. It was the only mystery. I still think this restriction on calling super convenience initializers is an unnecessary pain, but for now it isn't blocking me. - Jason McCarrell

3 Answers

13
votes

TL;DR: The texture parameter is of type SKTexture!. Since it's defined as an implicitly unwrapped optional, you can just pass nil.


First, you can't just call super(texture:, color, size:) from your convenience init, you actually have to call an init method on self. So, you'll have to add override init(texture: SKTexture!, color: SKColor!, size: CGSize) (which you can then just call super from).

Second, you can just pass nil as the texture parameter; SpriteKit will handle it appropriately.

Third (and only related because I had to make the change to get things to compile), you can't use your length property when creating your size variable because the class instance hasn't been initialized yet. Instead, I'd recommend declaring length as a var and passing it as a parameter to your convenience init.

Put all that together and you get something like this:

class TetrisCell : SKSpriteNode
{
    var length: CGFloat!

    override init(texture: SKTexture!, color: SKColor!, size: CGSize) {
        self.length = 10 // Some sort of sensible default
        super.init(texture: texture, color: color, size: size)
    }

    convenience init(color: SKColor, length: CGFloat = 10) {
        var size = CGSize(width: length, height: length);
        self.init(texture:nil, color: color, size: size)
        self.length = length
    }

    required init?(coder aDecoder: NSCoder) {
        // Decoding length here would be nice...
        super.init(coder: aDecoder)
    }
}
4
votes

One way to solve this is just to make a new init method and set color and size properties in that:

class Sprite: SKSpriteNode {

    init(color:SKColor,size:CGSize) {
        super.init()
        self.size=size
        self.colorBlendFactor=1
        self.color=color
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
3
votes

Without seeing your code or the error, my guess is it's complaining that you're not including the required initializer or something.. This may solve your issue:

override init(texture: SKTexture!, color: UIColor!, size: CGSize) {
    super.init(texture: texture, color: color, size: size)
    // Do custom stuff here
}

// Swift requires this initializer to exist if you're adding any other custom ones
required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}