Search code examples
xcodeswiftsubclassingexc-bad-instruction

Subclassing in Swift SpriteKit


I'm making an RPG-type game, in which you can choose the attack your user has. I'm trying to make it so that I have a superclass named "Projectile", where general variables are described, and subclasses that change the variables. But whenever I override the value of the variables, I get an EXC_BAD_INSTRUCTION.

import Foundation
import SpriteKit

class Projectile: SKNode {


    var texture: SKTexture!
    var projectileBody = SKSpriteNode()
    var projectile: SKEmitterNode!
    var negativeEffect: DefaultNegativeEffect!


    func setUpValues() {

        texture = SKTexture(imageNamed: "bokeh.png")
        projectileBody = SKSpriteNode()
        projectile = SKEmitterNode(fileNamed: "testbokeh.sks")
        negativeEffect = DefaultNegativeEffect(runningSpeed: 0)


    }

     override init() {
        super.init()
        projectileBody.texture = texture
        projectileBody.size = texture.size()
        projectileBody.position = self.position
        self.physicsBody = SKPhysicsBody(circleOfRadius: 2)
        self.physicsBody?.dynamic = true
        self.physicsBody?.categoryBitMask = PhysicsCategory.Projectile
        self.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
        self.physicsBody?.collisionBitMask = PhysicsCategory.None
        self.physicsBody?.usesPreciseCollisionDetection = true
        projectile.position = self.position
        self.addChild(projectileBody)
        self.addChild(projectile)

    }


    func update() {

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

}
import Foundation
import SpriteKit

class FireBall: Projectile {

    override func setUpValues() {

        texture = SKTexture(imageNamed: "spark5.png")
        projectileBody = SKSpriteNode()
        projectile = SKEmitterNode(fileNamed: "testbokeh.sks")
        negativeEffect = DefaultNegativeEffect(runningSpeed: 0)

    }

}

Solution

  • It looks like class Projectile calls super.init() before setting its own properties, and never calls setUpValues() at all, meaning your variable properties never have values.

    In the Fireball subclass the setUpValues function still isn't being called, and you don't have a separate init() function, so it's the same problem: the values aren't ever being set.

    The rules for initialization in Swift are a bit different from Obj-C in that you need to initialize all stored instance properties before calling super.init(), and have to consider how you handle inherited properties as well to ensure you have a fully/properly initialized object.

    From Apple's Swift Programming Guide:

    1. A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.

    2. A designated initializer must delegate up to a superclass initializer before assigning a value to an inherited property. If it doesn’t, the new value the designated initializer assigns will be overwritten by the superclass as part of its own initialization.