swiftxcodeskspritenodeskphysicsbodysknode

Cannot assign PhysicsBody and property to an SKSpriteNode?


I'm building a function in which a random variable will choose 1 in 4 SKSpritenode in an array and assign itself to it. However, that randomline, although appear as expected on the screen, does not contain any physicsbody property so it cannot be collide with other node. Below is my code:

func line() {

        redLine = SKSpriteNode(imageNamed: "redline")
        blueLine = SKSpriteNode(imageNamed: "blueline")
        yellowLine = SKSpriteNode(imageNamed: "yellowline")
        greenLine = SKSpriteNode(imageNamed: "greenline")

        let lineArray = [redLine,blueLine,yellowLine,greenLine]
        // Add physics
        lineArray[0].physicsBody?.categoryBitMask = gamePhysics.RedLine
        lineArray[1].physicsBody?.categoryBitMask = gamePhysics.BlueLine
        lineArray[2].physicsBody?.categoryBitMask = gamePhysics.YellowLine
        lineArray[3].physicsBody?.categoryBitMask = gamePhysics.GreenLine

        for i in 0...3 {
            lineArray[i].physicsBody = SKPhysicsBody(circleOfRadius: 10)
            lineArray[i].physicsBody?.collisionBitMask = gamePhysics.RedBall | gamePhysics.BlueBall | gamePhysics.YellowBall | gamePhysics.GreenBall
            lineArray[i].physicsBody?.contactTestBitMask = gamePhysics.RedBall | gamePhysics.BlueBall | gamePhysics.YellowBall | gamePhysics.GreenBall
            lineArray[i].physicsBody?.affectedByGravity = false
            lineArray[i].physicsBody?.isDynamic = true
        }
        let randomLine:SKSpriteNode! = lineArray.randomElement()
        ...

        self.addChild(randomLine)
        ...

        randomLine.run(SKAction.sequence([moveLine,delay,removeLine]))
    }

So basically when the randomline collide with other node, nothing happen.

Here is my didBegin (contact) func:

func didBegin(_ contact: SKPhysicsContact) {
        let firstBody = contact.bodyA
        let secondBody = contact.bodyB

        if firstBody.categoryBitMask == gamePhysics.RedBall && secondBody.categoryBitMask == gamePhysics.RedLine || firstBody.categoryBitMask == gamePhysics.BlueBall && secondBody.categoryBitMask == gamePhysics.BlueLine || firstBody.categoryBitMask == gamePhysics.YellowBall && secondBody.categoryBitMask == gamePhysics.YellowLine || firstBody.categoryBitMask == gamePhysics.GreenBall && secondBody.categoryBitMask == gamePhysics.GreenLine {

            currentScore += 1
            secondBody.node?.removeFromParent()
            print("hit point")

        } else if firstBody.categoryBitMask == gamePhysics.RedLine && secondBody.categoryBitMask == gamePhysics.RedBall || firstBody.categoryBitMask == gamePhysics.BlueLine && secondBody.categoryBitMask == gamePhysics.BlueBall || firstBody.categoryBitMask == gamePhysics.YellowLine && secondBody.categoryBitMask == gamePhysics.YellowBall || firstBody.categoryBitMask == gamePhysics.GreenLine && secondBody.categoryBitMask == gamePhysics.GreenBall {

            currentScore += 1
            firstBody.node?.removeFromParent()
            print("hit point")

        }
    }

Any help would be appreciated! EDIT: Here is the ball func(). Maybe somehow the SKNode contain multiple categorybitmask and therefore, won't work?

func Ball() {

        ballNode = SKNode()
        redBall = SKSpriteNode(imageNamed: "redball")
        blueBall = SKSpriteNode(imageNamed: "blueball")
        yellowBall = SKSpriteNode(imageNamed: "yellowball")
        greenBall = SKSpriteNode(imageNamed: "greenball")

        let ballArray = [redBall,blueBall,yellowBall,greenBall]
        ...

        // Add physics
        ballArray[0].physicsBody?.categoryBitMask = gamePhysics.RedBall
        ballArray[1].physicsBody?.categoryBitMask = gamePhysics.BlueBall
        ballArray[2].physicsBody?.categoryBitMask = gamePhysics.YellowBall
        ballArray[3].physicsBody?.categoryBitMask = gamePhysics.GreenBall

        for i in 0...3 {
            ballArray[i].physicsBody = SKPhysicsBody(circleOfRadius: 20)
            ballArray[i].physicsBody?.collisionBitMask = gamePhysics.RedLine | gamePhysics.BlueLine | gamePhysics.YellowLine | gamePhysics.GreenLine
            ballArray[i].physicsBody?.contactTestBitMask = gamePhysics.RedLine | gamePhysics.BlueLine | gamePhysics.YellowLine | gamePhysics.GreenLine
            ballArray[i].physicsBody?.affectedByGravity = false
            ballArray[i].physicsBody?.isDynamic = false
        }

        ballNode.addChild(redBall)
        ballNode.addChild(greenBall)
        ballNode.addChild(yellowBall)
        ballNode.addChild(blueBall)

        self.addChild(ballNode)
    }

UPDATE 2: Here is a struct where i store my categorybitmask:

struct gamePhysics {

    static let RedBall : UInt32 = 0x1 << 1
    static let BlueBall : UInt32 = 0x1 << 2
    static let GreenBall : UInt32 = 0x1 << 3
    static let YellowBall : UInt32 = 0x1 << 4
    static let RedLine : UInt32 = 0x1 << 5
    static let BlueLine : UInt32 = 0x1 << 6
    static let GreenLine : UInt32 = 0x1 << 7
    static let YellowLine : UInt32 = 0x1 << 8
}

Solution

  • OMG i found the answer to my question. The reason for the value of the categorybitmask to return "nil" was because i actually assign the node to categorybitmask before specified its physicsbody. Move the line down a few line and everything is solved!