0

I'm learning SpriteKit while laid up and recovering from back surgery. I appreciate your help in helping me understand why I'm getting this error.

I have a sprite "zombie1" that I can call via timer and it spawns over and over before moving across the screen without an issue until I try to add the riotShield Sprite. Once I do this it crashes as soon as the func is called the 2nd time and the first riotShield is already present:

    func addZ1ArmoredShield()     {
    zombie1Mask = SKSpriteNode(texture: zombie1Texture)
    var TextureAtlas = SKTextureAtlas()
    var TextureArray = [SKTexture]()
    TextureAtlas = SKTextureAtlas(named: "ZombieArmored")
    for i in 1...TextureAtlas.textureNames.count{
        let Name = "armoredZombie_\(i)"
        TextureArray.append(SKTexture(imageNamed: Name))
    }
    zombie1 = SKSpriteNode(imageNamed: TextureAtlas.textureNames[0] as String)
    zombie1.name = "monster"
    zombie1.position = CGPointMake(globalVariables.skScene.frame.size.width + 50, CGFloat(randomStartPosition()))
    let moveZombie1 = SKAction.moveToX(0, duration: spawnSpeed1()   )
    let removeZombie1 = SKAction.removeFromParent()
    let moveAndRemoveZombie1 = SKAction.sequence([moveZombie1, removeZombie1])
    zombie1.runAction(moveAndRemoveZombie1)       zombie1.runAction(SKAction.repeatActionForever(SKAction.animateWithTextures(TextureArray, timePerFrame: 0.1)))

    zombie1.physicsBody = SKPhysicsBody(texture: zombie1MaskTexture, size: zombie1Mask.size)
    zombie1.physicsBody!.dynamic = true
    zombie1.physicsBody!.affectedByGravity = false
    zombie1.physicsBody!.charge = 50
    zombie1.physicsBody!.usesPreciseCollisionDetection = true
    zombie1.physicsBody!.categoryBitMask = ColliderType.monster2HPContact.rawValue
    zombie1.physicsBody!.contactTestBitMask = ColliderType.bulletContact.rawValue|ColliderType.bottemEdge.rawValue|ColliderType.topEdge.rawValue|ColliderType.monster2HPContact.rawValue|ColliderType.heroTop.rawValue
    zombie1.physicsBody!.collisionBitMask = ColliderType.bottemEdge.rawValue|ColliderType.topEdge.rawValue
    zombie1.physicsBody!.fieldBitMask = ColliderType.monsterContact.rawValue
    zombie1.physicsBody!.mass = 2
    zombie1.physicsBody!.allowsRotation = false



    riotShield.name = "RiotShield"
    riotShield.color = SKColor.blackColor()
    riotShield.size = CGSizeMake(2, 25)
    riotShield.position = CGPoint(x: (zombie1.position.x + 80  ), y: (zombie1.position.y + 40 ))
    riotShield.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, 25))
    riotShield.physicsBody!.categoryBitMask = ColliderType.riotShieldContact.rawValue
    riotShield.physicsBody!.contactTestBitMask = ColliderType.bulletContact.rawValue
    riotShield.physicsBody!.dynamic = true
    riotShield.physicsBody!.affectedByGravity = false
    riotShield.physicsBody!.usesPreciseCollisionDetection = true


    let riotShieldJoint = SKPhysicsJointFixed.jointWithBodyA(zombie1.physicsBody!, bodyB: riotShield.physicsBody!, anchor: CGPoint(x: (zombie1.position.x + 10  ), y: zombie1.position.y + 10 ))




    globalVariables.currentScene.addChild(zombie1)
    globalVariables.currentScene.addChild(riotShield)
    globalVariables.currentScene.physicsWorld.addJoint(riotShieldJoint)




}//end function

What I don't understand is how come my zombie1 creates an instance of the SKSpritenode but my riotShield is seen as a singular sprite trying to be added to the same parent. I've read a ton of posts about this error, and I think I understand the cause (riotShield not being added as an instance). I just don't understand the difference between the two sprites and whey they behave differently when I'm adding them (to me) essentially the same way.

I appreciate your time and any help you may provide.

  • Same node can have only one parent. If you try to add it to another parent, you get this crash... Also that `globalVariables` thing looks shady :) – Whirlwind Apr 01 '16 at 01:13
  • Thank you, the globalVariable just points to the current scene so the function always adds the sprite to the active "level" scene. In regards to the single parent, that does make sense, I just don't quite understand the difference between zombie1 and riotShield in that regard. I can add the zombie1 a hundred times without issue, but as soon as a 2nd riotShield is added, it crashes. Do you know why riotShield is being applied against the same parent as the first instance but zombie1 does not? (Sorry if this is a silly question. – Undead-Earth .com Apr 01 '16 at 01:22
  • So the scene is always alive right? If so, the added sprites are never removed, and when you try to add them again, you get crash. Not sure about your current setup (and why you doing things like that) but retaining a scene like that is probably not a good idea. How many scenes do you have? – Whirlwind Apr 01 '16 at 01:24
  • I have 6 scenes, they vary based on the types of speed of the "zombies". I haven't had any issues with the parent issue until I tried to learn about joints, which is the first time I've also tried to add 2 sprites in 1 function like this. (and thank you for taking a look and your feedback) – Undead-Earth .com Apr 01 '16 at 01:28

1 Answers1

0

Based on the single parent issue and looking at the way I was adding the "riotShield" node I figured out that it was the way I was using the SKSpritenode as a shapenode, which apparently changes its behavior.

By adding the riotShield as an image as below, everything worked.

riotShield.name = "RiotShield"
riotShield = SKSpriteNode(imageNamed: "riotShield1")
riotShield.position = CGPoint(x: (zombie1.position.x + 80  ), y: (zombie1.position.y + 40 ))
riotShield.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, 25))
riotShield.physicsBody!.categoryBitMask = ColliderType.riotShieldContact.rawValue
riotShield.physicsBody!.contactTestBitMask = ColliderType.bulletContact.rawValue
riotShield.physicsBody!.dynamic = true
riotShield.physicsBody!.affectedByGravity = false
riotShield.physicsBody!.usesPreciseCollisionDetection = true

Thank you to everyone who posted other questions and responded to mine.

  • Oh I see the issue now. It is not how you use SKSpriteNode (you can't use it like SKShapeNode if it is an SKSpriteNode). It is because the riotShield is a property of a scene and when you call this method multiple times the game crashes. Now it works because you are re-initializing the `riotShield` each time , with this line riotShield = SKSpriteNode(imageNamed: "riotShield1"). In your previous code you have been re-using the same sprite, which already has a parent, and thus the error. – Whirlwind Apr 01 '16 at 19:22