Search code examples
swiftsprite-kitskphysicsbodyskphysicscontact

SKPhysicsContact body, can't change properties


I have a SpriteKit physics contact firing in didBegin(contact:). I grab the physics body for the instance of the Dot object that I want to move offscreen, but when I try to change its position like so, nothing happens:

First Approach

/* In GameScene.swift */

func didBegin(_ contact: SKPhysicsContact) {
    let dotBody: SKPhysicsBody
    if contact.bodyA.categoryBitMask == 0b1 {
        dotBody = contact.bodyB
    } else {
        dotBody = contact.bodyA
    }

    if let dot = dotBody.node as? Dot {
        dot.position.x = 10000
    }
}

However, if I instead call a method in my Dot class, passing in that body, the position gets set correctly:

Second Approach

/* In GameScene.swift */

func didBegin(_ contact: SKPhysicsContact) {
    let dotBody: SKPhysicsBody
    if contact.bodyA.categoryBitMask == 0b1 {
        dotBody = contact.bodyB
    } else {
        dotBody = contact.bodyA
    }

    if let dot = dotBody.node as? Dot {
        dot.move()
    }        
}

Here is the Dot class:

import SpriteKit
class Dot : SKSpriteNode {
    let dotTex = SKTexture(imageNamed: "dot")
    init() {
        super.init(texture: dotTex, color: .clear, size: dotTex.size())
        self.physicsBody = SKPhysicsBody(circleOfRadius: size.width / 2)
        self.physicsBody?.categoryBitMask = 0b1 << 1
        self.physicsBody?.contactTestBitMask = 0b1
    }

    func move() {
        let reset = SKAction.run {
            self.position.x = 10000
        }
        self.run(reset)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}

Can anyone explain why the position change in the second approach works but it does not work in my first approach?

Here's a link to the project on Github.


Solution

  • func didBegin(_ contact: SKPhysicsContact) {
      let hitDot = contact.bodyB.node! as! SKSpriteNode
      let hitDot1 = contact.bodyA.node! as! SKSpriteNode
        if hitDot.name? == "dot" || hitDot1.name? == "dot" {
           reset = true
        }        
    }
    
       override func update(_ currentTime: TimeInterval) {
        if reset {
            newDot.position.x = 0
            reset = false
        }
    }
    

    There might be small errors in the code coz i just edited here. But hope this gives u the idea. This should work without errors.