Where do I put code that runs when two nodes collide or make contact with each other?

Where do I put code that runs when two nodes collide or make contact with each other?


I've already read the article, "About Collisions and Contacts". That doesn't give me all the information I need.


Here is my code so far. The didBegin callback method isn't firing.


import UIKit
import SpriteKit

class GameScene: SKScene {

    let player = SKSpriteNode(imageNamed: "player")
    
    override func didMove(to view: SKView) {
        
        physicsWorld.contactDelegate = self
        
        player.physicsBody = SKPhysicsBody(rectangleOf: player.size)
        player.physicsBody?.isDynamic = false
        player.physicsBody?.categoryBitMask = 0b00001
        player.physicsBody?.collisionBitMask = 0b00001
        
        player.position = CGPoint(x: 20 + player.size.width/2, y: view.frame.height / 2)
        
        addChild(player)
        
        let carEngineStart = SKAudioNode(fileNamed: "car_engine_running")
        
        addChild(carEngineStart)
        
        run(SKAction.repeatForever(
            SKAction.sequence([
                SKAction.run(addCompetitor),
                SKAction.wait(forDuration: 3.0)
                ])
        ))

    }
    
    override func update(_ currentTime: TimeInterval) {
        
        let internalRollSign = TrialSpriteKit.sign(internalRoll)
        
        switch internalRollSign {
        case .zero:
            print("0")
        case .positive:
            print("+")
            if player.position.y < self.size.height {
                player.position.y += 5
            }
        case .negative:
            print("-")
            if player.position.y > 0 {
                player.position.y -= 5
            }
        }
        
    }
    
    func random() -> CGFloat {
        return CGFloat(Float(arc4random()) / /* 0xFFFFFFFF */ 4294967296)
    }
    
    func random(min: CGFloat, max: CGFloat) -> CGFloat {
        return random() * (max - min) + min
    }
    
    func addCompetitor() {
        
        // Create sprite
        let car = SKSpriteNode(imageNamed: "utili")
        
        car.physicsBody = SKPhysicsBody(rectangleOf: car.size) // 1
        car.physicsBody?.isDynamic = false
        car.physicsBody?.categoryBitMask = 0b00001
        car.physicsBody?.collisionBitMask = 0b00001
        
        // Determine where to spawn the car along the Y axis
        let actualY = random(min: car.size.height/2, max: size.height - car.size.height/2)
        
        // Position the car slightly off-screen along the right edge,
        // and along a random position along the Y axis as calculated above
        car.position = CGPoint(x: size.width + car.size.width/2, y: actualY)
        
        // Add the car to the scene
        addChild(car)
        
        // Determine speed of the car
        let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0))
        
        // Create the actions
        let actionMove = SKAction.move(to: CGPoint(x: -car.size.width/2, y: actualY), duration: TimeInterval(actualDuration))
        let actionMoveDone = SKAction.removeFromParent()
        car.run(SKAction.sequence([actionMove, actionMoveDone]))
    }

}

extension GameScene: SKPhysicsContactDelegate {
    
    func didBegin(_ contact: SKPhysicsContact) {
        
        print("BANG!")
        
    }
    
}

Accepted Reply

The didBegin function is called when two physics bodies make contact. Place your collision handling code in didBegin or in its own function that you call from didBegin.


The tougher question is why didBegin is not being called. I noticed you have not set the contact test bit mask for your physics bodies. You need to set the contact bit mask to get notified when two physics bodies make contact. If that does not work, the following article from Hacking with Swift may help you:


hackingwithswift.com/read/11/5/collision-detection-skphysicscontactdelegate

Replies

The didBegin function is called when two physics bodies make contact. Place your collision handling code in didBegin or in its own function that you call from didBegin.


The tougher question is why didBegin is not being called. I noticed you have not set the contact test bit mask for your physics bodies. You need to set the contact bit mask to get notified when two physics bodies make contact. If that does not work, the following article from Hacking with Swift may help you:


hackingwithswift.com/read/11/5/collision-detection-skphysicscontactdelegate