Ben Vanderloos - 1 year ago 76
Swift Question

# Trouble with collision detection swift 2.0 spritekit

I am building a game for iOS for the first time. I am very close, however I got collision detection working early then I changed something and I lost it working. I have tried to get in back but haven't work. This is what I have so far, but nothing working. I am trying different versions of collision detection that I have found online but I am sticking to get this one to work. Just don't understand where I have went wrong.

import SpriteKit
enum ColliderType: UInt32 {
case Player = 1
case Traffic = 2
}

class GameScene: SKScene, SKPhysicsContactDelegate {
override func didMoveToView(view: SKView) {

createWalls()

self.backgroundColor = SKColor.whiteColor()
self.physicsWorld.gravity = CGVectorMake(0, 0)

player.physicsBody = SKPhysicsBody(rectangleOfSize: player.size)
player.physicsBody?.dynamic = true

player.zPosition = 3
player.name = "player"
player.position = CGPoint(x: self.frame.midX, y: (self.frame.midY)/3)
player.setScale(1.0)

_ = NSTimer.scheduledTimerWithTimeInterval(2.5, target: self, selector: #selector(GameScene.makeTraffic), userInfo: nil, repeats: true)
}

func makeTraffic(){

var aNumber = Int(arc4random_uniform(2))

let Pos1 = Int(self.frame.midX/2)+30
let Pos2 = Int((self.frame.size.width)/2)
let Pos3 = Int(self.frame.size.width-300)

let array = [Pos1, Pos2, Pos3]
let randomIndex = Int(arc4random_uniform(UInt32(array.count)))
let randomPOS = CGPoint(x:Int(array[randomIndex]), y:Int(self.frame.height))

if aNumber == 0 {
aNumber = aNumber + 1
}

switch aNumber {
case 1:
let car1 = SKSpriteNode(imageNamed: "Car_Green_Front")
car1.position = randomPOS
car1.zPosition = 3
car1.setScale(1.0)

car1.physicsBody = SKPhysicsBody(rectangleOfSize: car1.size)
car1.physicsBody?.dynamic = true

case 2:
let car2 = SKSpriteNode(imageNamed: "Car_Purple_Front")
car2.position = randomPOS
car2.zPosition = 3
car2.setScale(1.0)

car2.physicsBody = SKPhysicsBody(rectangleOfSize: car2.size)
car2.physicsBody?.dynamic = true

default:
return
}
}

func createWalls(){
let wallSize = CGSize(width: 5, height: self.frame.size.height)

let rightwall = SKShapeNode(rectOfSize: wallSize)
rightwall.physicsBody = SKPhysicsBody(rectangleOfSize: wallSize)
rightwall.physicsBody!.dynamic = false

rightwall.position = CGPoint(x: self.frame.maxX-300, y: self.frame.size.height/2)
rightwall.fillColor = UIColor.clearColor()

let leftwall = SKShapeNode(rectOfSize: wallSize)
leftwall.physicsBody = SKPhysicsBody(rectangleOfSize: wallSize)
leftwall.physicsBody!.dynamic = false

leftwall.position = CGPoint(x: self.frame.minX+300, y: self.frame.size.height/2)
leftwall.fillColor = UIColor.clearColor()
}

func didBeginContact(contact: SKPhysicsContact) {
print("Contact")

print("Hi")

} else {

print("Hello")    }

}


}

Your code seems alrite, although there is some small changes I would make.

1) I would write my collider types like so

 struct ColliderType {
static let player: UInt32 = 0x1 << 0
static let traffic: UInt32 = 0x1 << 1
}


because this way you only need to increment the last number by 1. Your way if you decide to add more categories the next one would have to be 4, than 8, than 16 etc, which is more confusing (you are dealing with 32 bit integers)

Than use it like so

 ...categoryBitMask = ColliderType.player


2) It is recommended that you give the sprite the position before adding the physicsBody. You are doing it the other way round which could cause unexpected issues.

3) Change your collision method to this

func didBeginContact(contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody

firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}

// player hit traffic, do something
}
}


4) Finally the most important part is that you need to set the delegate which I couldn't see in your code.

Call this in DidMoveToView

 physicsWorld.contactDelegate = self


otherwise the DidBeginContact method will never fire.

Also it is a good idea if you follow apples naming conventions. So only classes, protocols, enums and structs should start with capital letters.

Hope this helps