Andrew
Andrew

Reputation: 53

My nodes are not colliding, am I missing something in my code?

I followed many different tutorials on collision and created my own game where i want to declare a collision between a coin and a player. However, after implementing the collision code my two nodes are not responding to the collision...can someone help me out please?

import SpriteKit
import GameplayKit

// Collision categories

enum ColliderType: UInt32 {
case playerCase = 1
case coinCase = 2
case borderCase = 3
}

class GameScene: SKScene, SKPhysicsContactDelegate {

let player  = SKSpriteNode(imageNamed:"block")
let buttonDirLeft = SKSpriteNode(imageNamed: "left")
let buttonDirRight = SKSpriteNode(imageNamed: "right")
let coins = SKSpriteNode(imageNamed: "coins")
let background = SKSpriteNode(imageNamed: "background")
var pressedButtons = [SKSpriteNode]()

override func didMove(to view: SKView) {

self.physicsWorld.contactDelegate = self

//score label
let points = SKLabelNode(text: "0")
points.position = CGPoint(x: 530, y: 260)
points.zPosition = 6
points.fontColor = UIColor.black
points.fontSize = 50
addChild(points)


//Set Background
background.zPosition = 1
background.position = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
background.size.width = 580
background.size.height = 320

addChild(background)

// Player
player.position = CGPoint(x: 250, y: 40)
player.zPosition = 2
player.texture?.filteringMode = .nearest
// player!.collisionBitMask = 0 //
player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.height / 2.0)
player.physicsBody?.isDynamic = false
player.physicsBody?.allowsRotation = false
player.physicsBody?.affectedByGravity = false
player.physicsBody!.categoryBitMask = ColliderType.playerCase.rawValue
player.physicsBody!.contactTestBitMask = ColliderType.coinCase.rawValue
player.physicsBody!.collisionBitMask = ColliderType.coinCase.rawValue

self.addChild(player)

// button left
buttonDirLeft.position = CGPoint(x: 30, y: 35)
buttonDirLeft.zPosition = 4
buttonDirLeft.size.width = 270
buttonDirLeft.size.height = 320
buttonDirLeft.alpha = 0.0
self.addChild(buttonDirLeft)

// button right
buttonDirRight.position = CGPoint(x: 530, y: 35)
buttonDirRight.zPosition = 4
buttonDirRight.size.width = 270
buttonDirRight.size.height = 320
buttonDirRight.alpha = 0.0
self.addChild(buttonDirRight)


// setting border around game
let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody

//ENEMY SETTINGS START

//repeat coing spawning
run(SKAction.repeatForever(
    SKAction.sequence([
        SKAction.run(spawnCoins),
        SKAction.wait(forDuration: 1.0)])))


}
//coin settings
func random() -> CGFloat {
    return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}

func random(min: CGFloat, max: CGFloat) -> CGFloat {
    return random() * (max - min) + min
}

//spawn coins
func spawnCoins() {
    // 2
    let coins = SKSpriteNode(imageNamed: "coins")
    coins.zPosition = 2
    coins.size.width = 40
    coins.size.height = 40

    let action = SKAction.moveTo(y: -350, duration: TimeInterval(random(min:   1, max: 5)))

    let remove = SKAction.run({coins.removeFromParent(); print("coins removed  from scene")})

    let sequence = SKAction.sequence([action,remove])

    coins.physicsBody = SKPhysicsBody(rectangleOf: coins.size )
    coins.physicsBody?.isDynamic = false
    coins.physicsBody!.affectedByGravity = false
    coins.physicsBody!.categoryBitMask = ColliderType.coinCase.rawValue
    coins.physicsBody!.contactTestBitMask = ColliderType.playerCase.rawValue
    coins.physicsBody!.collisionBitMask = ColliderType.playerCase.rawValue

    coins.run(sequence)


    coins.size.width = 20
    coins.size.height = 20
    coins.name = "coins"
//    coins.physicsBody!.collisionBitMask = 0
    coins.position = CGPoint(x: frame.size.width * random(min: 0, max: 1), y: frame.size.height + coins.size.height/2)
    addChild(coins)

}


override func update(_ currentTime: TimeInterval) {
    // Called before each frame is rendered
    /* Called before each frame is rendered */
    if pressedButtons.index(of: buttonDirLeft) != nil {
        player.position.x -= 3.0
    }
    if pressedButtons.index(of: buttonDirRight) != nil {
        player.position.x += 3.0
    }

    // Update entities       

}
//MOVEMENT FUNCTIONS START HERE
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches {
        let location = touch.location(in: self)
        let previousLocation = touch.previousLocation(in: self)

        for button in [buttonDirLeft, buttonDirRight] {
            // I check if they are already registered in the list
            if button.contains(location) && pressedButtons.index(of: button) == nil {
                pressedButtons.append(button)
            }
        }
    }
}


override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches {
        let location = touch.location(in: self)
        let previousLocation = touch.previousLocation(in: self)

        for button in [buttonDirLeft, buttonDirRight] {
            // if I get off the button where my finger was before
            if button.contains(previousLocation)
                && !button.contains(location) {
                // I remove it from the list
                let index = pressedButtons.index(of: button)
                if index != nil {
                    pressedButtons.remove(at: index!)
                }
            }

                // if I get on the button where I wasn't previously
            else if !button.contains(previousLocation)
                && button.contains(location)
                && pressedButtons.index(of: button) == nil {
                // I add it to the list
                pressedButtons.append(button)

            }}}}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches {
        let location = touch.location(in: self)
        let previousLocation = touch.previousLocation(in: self)

        for button in [buttonDirLeft, buttonDirRight] {
            if button.contains(location) {
                let index = pressedButtons.index(of: button)
                if index != nil {
                    pressedButtons.remove(at: index!)
                }
            }
            else if (button.contains(previousLocation)) {
                let index = pressedButtons.index(of: button)
                if index != nil {
                    pressedButtons.remove(at: index!)
                }
            }
        }
    }
}


override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch: AnyObject in touches {
        let location = touch.location(in: self)
        let previousLocation = touch.previousLocation(in: self)

    for button in [buttonDirLeft, buttonDirRight] {
        if button.contains(location) {
            let index = pressedButtons.index(of: button)
            if index != nil {
                pressedButtons.remove(at: index!)
            }
        }
        else if (button.contains(previousLocation)) {
            let index = pressedButtons.index(of: button)
            if index != nil {
                pressedButtons.remove(at: index!)
            }
        }
    }
}
}

func didBeginContact(contact: SKPhysicsContact){
print("colliding!")
}

Upvotes: 2

Views: 49

Answers (1)

Whirlwind
Whirlwind

Reputation: 13665

Contact will happen only if at least one body is dynamic. So either set your player or coin to be dynamic and if everything else is set correctly (if categories are set properly and didBeginContact method implementation is correct) your bodies will now collide / make contacts. If you are interested only in contacts, set collision bit mask to 0.

Upvotes: 2

Related Questions