skip to Main Content

I’m trying to get to know when two sprites contact each other but I’m not being able to get it to work.

The code below reproduces the problem. I expected the contact delegate methods to fire when I tap the red square and the yellow square reaches it. However, nothing happens. The code seems like a lot but is actually quite simple. I’ve added comments to make it easier to read:

class GameScene: SKScene, SKPhysicsContactDelegate {
    private var node: SKSpriteNode!
    
    override func didMove(to view: SKView) {
        // Set contact delegate to this class
        physicsWorld.contactDelegate = self

        // Have the Game Scene be the same size as the View
        size = view.frame.size

        // Create a yellow square with a volume based physics body that isn't dynamic
        node = SKSpriteNode(color: .yellow, size: CGSizeMake(50, 50))
        node.position = CGPointMake(100, 100)
        node.physicsBody = SKPhysicsBody(rectangleOf: CGSizeMake(50, 50))
        node.physicsBody!.isDynamic = false

        // Set it's contact bit mask to any value (default category bitmask of 
        // SKSpriteNode is 0xFFFFFFFF so any value over here would do)
        node.physicsBody!.contactTestBitMask = 1

        // Add it to the Scene
        addChild(node)
        
        // Create a red square with a volume based physics body that isn't dynamic
        let otherNode = SKSpriteNode(color: .red, size: CGSizeMake(50, 50))
        otherNode.physicsBody = SKPhysicsBody(rectangleOf: CGSizeMake(50, 50))
        otherNode.physicsBody!.isDynamic = false

        // Set the position to be 100 pts to the right of the yellow square
        otherNode.position = CGPointMake(200, 100)

        // Add it to the Scene
        addChild(otherNode)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // Moves yellow square to where you tapped on the screen
        guard let finger = touches.first?.location(in: self) else { return }
        node.run(.move(to: finger, duration: 1))
    }

    func didBegin(_ contact: SKPhysicsContact) {
        print("did begin contact")
    }
}
struct ContentView: View {
    var body: some View {
        VStack {
            Text("Game")
            SpriteView(scene: GameScene(), debugOptions: [.showsPhysics, .showsNodeCount])
        }
        .padding()
    }
}

Can anyone tell me what I’m doing wrong?

Thanks in advance

2

Answers


  1. When you’re using physics bodies, you should avoid moving nodes using actions. Instead move the bodies by setting forces and/or impulses, with methods like applyForce(_:) and applyImpulse(_:).

    This will allow the physics engine to simulate the physics interactions correctly.

    Login or Signup to reply.
  2. didBegin(contact:) won’t fire if .isDynamic = false so delete those lines and add physicsWorld.gravity = .zero to keep nodes from falling.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search