Hey so I have a problem detecting collisions. I have this project I am making based on Ray Wenderlich's tutorial on How to Make a game like Mega Jump. So everything is works great at the beginning, where platforms and stars are static in one place. But as you go further in the game, stars and platforms start moving (I am using SKActions for this), tried to do this to make it a little harder. But when I get there, collision is NOT being detected at all, player just passes by through the objects like they weren't there. I've been reading everywhere online, I am using precise collision detection but still I see no difference. Any ideas on what can be wrong or what else can I do? Here is a bit of code on how I am doing this:
player = SKSpriteNode(texture: firstFrame)
player.position = (CGPoint(x: self.size.width / 2, y: 50.0))
player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.width / 2)
player.physicsBody?.dynamic = true
player.physicsBody?.allowsRotation = false
player.physicsBody?.restitution = 1.0
player.physicsBody?.friction = 0.0
player.physicsBody?.angularDamping = 0.0
player.physicsBody?.linearDamping = 0.0
player.physicsBody?.usesPreciseCollisionDetection = true
player.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Player
player.physicsBody?.collisionBitMask = 0
player.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Star | CollisionCategoryBitmask.Platform | CollisionCategoryBitmask.Monster
foregroundNode.addChild(player)
func createPlatformAtPosition(position: CGPoint, ofType type: PlatformType) -> PlatformNode {
let node = PlatformNode()
let thePosition = CGPoint(x: position.x * scaleFactor, y: position.y)
node.position = thePosition
node.name = "NODE_PLATFORM"
node.platformType = type
var sprite: SKSpriteNode
var spriteFrames : [SKTexture]!
if type == .Break {
let spriteAnimatedAtlas = SKTextureAtlas(named: "CloudBreak")
var cloudFrames = [SKTexture]()
spriteFrames = cloudFrames
let firstFrame = SKTexture(imageNamed: "Cloud02")
sprite = SKSpriteNode(texture: firstFrame)
let move = SKAction.moveToX(self.position.x - 160.0, duration:2.0)
let back = SKAction.moveToX(self.position.x, duration:2.0)
let sequence = SKAction.sequence([move, back, move, back])
sprite.runAction(SKAction.repeatActionForever(sequence))
} else {
let spriteAnimatedAtlas = SKTextureAtlas(named: "Cloud")
var cloudFrames = [SKTexture]()
spriteFrames = cloudFrames
let firstFrame = SKTexture(imageNamed: "Cloud")
sprite = SKSpriteNode(texture: firstFrame)
}
node.addChild(sprite)
node.physicsBody = SKPhysicsBody(rectangleOfSize: sprite.size)
node.physicsBody?.dynamic = false
node.physicsBody?.categoryBitMask = CollisionCategoryBitmask.Platform
node.physicsBody?.contactTestBitMask = CollisionCategoryBitmask.Player
node.physicsBody?.collisionBitMask = 0
return node
}
func didBeginContact(contact: SKPhysicsContact) {
var updateHUD = false
let whichNode = (contact.bodyA.node != player) ? contact.bodyA.node : contact.bodyB.node
let other = whichNode as GameObjectNode
updateHUD = other.collisionWithPlayer(player)
}
struct CollisionCategoryBitmask {
static let Player: UInt32 = 0x00
static let Star: UInt32 = 0x01
static let Platform: UInt32 = 0x02
static let Monster: UInt32 = 0x03
}
Slow the objects down and see if they collide. I had an issue where I was moving my nodes too fast and they were past the collision points when the new frame was rendered. If they move so fast they pass each other's physics body in the frame cycle they will not register a hit.
To detect a collision in that case, you can compare where they are in each frame, and if they have passed each other or their x/y plane values overlap, you can execute your collision code.
The collision is not detected because you didn't set the collisionBitMask.
player.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Star | CollisionCategoryBitmask.Platform | CollisionCategoryBitmask.Monster
node.physicsBody?.collisionBitMask = CollisionCategoryBitmask.Player
Contact and Collision aren't the same thing. You can find more information online.
If it still doesn't work, please show us your CollisionCategoryBitmask to make sure you created it properly.
Edit :
struct CollisionCategoryBitmask {
static let Player: UInt32 = 0
static let Star: UInt32 = 0b1
static let Platform: UInt32 = 0b10
static let Monster: UInt32 = 0b100
}
Here is a table I've made for another question, that might help you too :
http://goo.gl/7D8EGY
Check out my collision physics engine, it's very simple but has support for continuous/predicting/bullet collisions. You might learn something from the code, and it's written in javascript so it should be easy to read.https://github.com/Murplyx/AAE---Axis-Aligned-Engine
Related
I'm trying to get my player to play the jump animation when the touch begins. The player is in his own swift file and I have the GameScene.swift call his file so everything that deals with his movement is in player.swift file. Any help would be awesome!
import SpriteKit
struct ColliderType {
static let PLAYER: UInt32 = 0
static let GROUND: UInt32 = 1
static let ROCKET_AND_COLLECTABLES: UInt32 = 2
}
class Player: SKSpriteNode {
private var textureAtlas = SKTextureAtlas()
private var playerAnimation = [SKTexture]()
private var animatePlayerAction = SKAction()
let jumpAnimation1 = [SKTexture]()
let jumpAnimation2 = [SKTexture]()
var jumpAnimation = SKAction ()
func initializePlayer() {
name = "Player"
for i in 1...7 {
let name = "Player \(i)"
playerAnimation.append(SKTexture(imageNamed: name))
}
animatePlayerAction = SKAction.animate(with: playerAnimation,
timePerFrame: 0.08, resize: true, restore: false)
//Animate the player forever.
self.run(SKAction.repeatForever(animatePlayerAction))
physicsBody = SKPhysicsBody(rectangleOf: CGSize(width:
self.size.width-60, height: self.size.height-80))
physicsBody?.affectedByGravity = true
physicsBody?.allowsRotation = false
//Restitution is Boucniess
physicsBody?.restitution = 0
physicsBody?.categoryBitMask = ColliderType.PLAYER
physicsBody?.collisionBitMask = ColliderType.GROUND
physicsBody?.contactTestBitMask =
ColliderType.ROCKET_AND_COLLECTABLES
}
func move (){
self.position.x += 10
}
func reversePlayer() {
physicsBody?.velocity = CGVector(dx: 0, dy: 0)
physicsBody?.applyImpulse(CGVector(dx: 0, dy: 300))
playerNode?.removeAction(forKey:"animate") playerNode?.run(attackAnimation,completion:{
self.playerNode?.run(self.animation,withKey: "animate")
}
}
Replace the part where you set textures, create and run the action with the following code snippet. It works perfectly for me and is the simplest way to do it.
let hero = SKSpriteNode(imageNamed: "hero")
hero.size = CGSize(width: 45, height: 125)
let f1 = SKTexture.init(imageNamed: "h1")
let f2 = SKTexture.init(imageNamed: "h2")
let f3 = SKTexture.init(imageNamed: "h3")
let frames: [SKTexture] = [f1, f2, f3]
let hero = SKSpriteNode(imageNamed: "h1")
let animation = SKAction.animate(with: frames, timePerFrame: 0.1)
hero.run(SKAction.repeatForever(animation))
Also, it is possible that your animation action cannot be accessed as it is in another file. Declare the player and animations globally i.e. outside of any class or function. Hope it works for you!
When player body meet a monster body the function func didBeginContact(contact: SKPhysicsContact) is never called.
My class implement SKPhysicsContactDelegate
class GameScene: SKScene, SKPhysicsContactDelegate
the property collisionBitMask i commented it because i read that if we don't put it, node can collise with all node
I add my player like this :
bear.position = CGPoint(x:self.frame.width/20, y:self.frame.height/5)
bear.size = CGSize(width: self.frame.width/7, height: self.frame.height/5)
bear.physicsBody = SKPhysicsBody(rectangleOfSize: bear.frame.size)
bear.physicsBody?.dynamic = false;
bear.physicsBody?.categoryBitMask = PhysicsCategory.Player
bear.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
//bear.physicsBody?.collisionBitMask = PhysicsCategory.Monster
I add monster like this:
let thePosition = CGPoint(x: positionX, y: (self.frame.height/7.4)*positionY)
let monster = SKSpriteNode(imageNamed: pattern as String)
monster.size = CGSize(width: self.frame.width/16, height: self.frame.height/11)
monster.name = name
monster.position = thePosition
monster.physicsBody = SKPhysicsBody(rectangleOfSize: monster.frame.size)
monster.physicsBody?.dynamic = false
monster.physicsBody?.categoryBitMask = PhysicsCategory.Monster // 3
monster.physicsBody?.affectedByGravity = false
monster.physicsBody?.contactTestBitMask = PhysicsCategory.Player // 4
//platformNode.physicsBody?.collisionBitMask = PhysicsCategory.Player // 5
addChild(monster)
my PhysicalCategory
struct PhysicsCategory {
static let None : UInt32 = 0
static let All : UInt32 = UInt32.max
static let Player: UInt32 = 0b1 // 1
static let Monster : UInt32 = 0b10 // 2
static let Projectile: UInt32 = 0b100 // 3
static let Plateforme: UInt32 = 0b1000 // 4
}
I have multiple Textures, for example when player walk i call this :
func walkingBear() {
bear.runAction( SKAction.repeatActionForever(SKAction.animateWithTextures(bearCoursFrames, timePerFrame: 0.1, resize: false, restore: true)), withKey:"cours")
}
I initlaise bearCoursFrames like this
var walkFrames = [SKTexture]()
var numImages : Int = bearAnimatedAtlas.textureNames.count
for var i=1; i<=numImages/2; i++ {
let bearTextureName = "cours\(i)"
walkFrames.append(bearAnimatedAtlas.textureNamed(bearTextureName))
}
bearCoursFrames = walkFrames
Where is my error please, i can't find a solution in other post
any help would be appreciated
---------------------------------EDIT------------------------------
Solution: I just add self.physicsWorld.contactDelegate = self and it works now.
The answer is simple. There is a rule which says that at least one body has to be defined as dynamic in order to register the contact.
Change either player or other body to be dynamic and contact will be detected.
As an addition, if you already haven't, enable physics visual representation ... It can be helpful because sometimes contact is not detected because the actual bodies are not intersecting each other eg. when node's anchor point is changed, so the texture and a body are misplaced (which is fixable, using appropriate initializers of SKPhysicsBody class, but this is a very common error).
I just add
self.physicsWorld.contactDelegate = self
and it works now.
I have a moving platform, but when the node is above the platform it doesnt move with the platform horizontally
In this article, the problem is explained: Moving Platform Hell
http://www.learn-cocos2d.com/2013/08/physics-engine-platformer-terrible-idea/
And in comment there is solutions for Box2D: Kinematic body
But what about SpriteKit ?
Update
I'm moving the platform using
let moveHPart1 = SKAction.moveByX(origW, y: 0, duration: moveDuration);
let moveHPart2 = SKAction.moveByX(-origW, y: 0, duration: moveDuration);
platform(SKAction.repeatActionForever(SKAction.sequence([moveHPart1, moveHPart2])));
Personally I am against of using physics for moving platforms because moving platform physics body has to be dynamic.
Static platforms
For static platforms setting physics body dynamic property to false is perfect solution. And this is how it is meant to be. Static bodies are not affected by forces but still give you a collision response. So, the problem is solved.
But you can't change position of static physics bodies by using forces. You can do this by using actions or manually setting its position. But, then you are removing a platform out of physics simulation.
In order to do all with physics, you have to keep the platform dynamic. But this can lead in other problems. For example when player lands on platform, he will push the platform down, because player has a mass.
Even if platform has big mass it will go down as time passing. Remember, we cant just update platforms x position manually, because this can make a mess with physics simulation.
"Moving platform hell" as stated in that nice article of LearnCocos2d is probably the best description what can happen when using physics for this task :-)
Moving platform example
To show you some possibilities I made an simple example on how you can move a platform with applying a force to it, and make a character to stay on it.There are few things I've done in order to make this to work:
Changed a mass of platform. This will prevent platform from moving when player bumps in it from below.
Made an edge based physics body to prevent platform falling when player lands on it.
Played with properties like allows rotation and friction to get desired effect.
Here is the code :
import SpriteKit
class GameScene: SKScene,SKPhysicsContactDelegate
{
let BodyCategory : UInt32 = 0x1 << 1
let PlatformCategory : UInt32 = 0x1 << 2
let WallCategory : UInt32 = 0x1 << 3
let EdgeCategory : UInt32 = 0x1 << 4 // This will prevent a platforom from falling down
let PlayerCategory : UInt32 = 0x1 << 5
let platformSpeed: CGFloat = 40.0
let body = SKShapeNode(circleOfRadius: 20.0)
let player = SKShapeNode(circleOfRadius: 20.0)
let platform = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width:100, height:20))
let notDynamicPlatform = SKSpriteNode(color: SKColor.greenColor(), size: CGSize(width:100, height:20))
override func didMoveToView(view: SKView)
{
//Setup contact delegate so we can use didBeginContact and didEndContact methods
physicsWorld.contactDelegate = self
//Setup borders
self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody?.categoryBitMask = WallCategory
self.physicsBody?.collisionBitMask = BodyCategory | PlayerCategory
//Setup some physics body object
body.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
body.fillColor = SKColor.greenColor()
body.physicsBody = SKPhysicsBody(circleOfRadius: 20)
body.physicsBody?.categoryBitMask = BodyCategory
body.physicsBody?.contactTestBitMask = PlatformCategory
body.physicsBody?.collisionBitMask = PlatformCategory | WallCategory
body.physicsBody?.allowsRotation = false
body.physicsBody?.dynamic = true
self.addChild(body)
//Setup player
player.position = CGPoint(x: CGRectGetMidX(self.frame), y:30)
player.fillColor = SKColor.greenColor()
player.physicsBody = SKPhysicsBody(circleOfRadius: 20)
player.physicsBody?.categoryBitMask = PlayerCategory
player.physicsBody?.contactTestBitMask = PlatformCategory
player.physicsBody?.collisionBitMask = PlatformCategory | WallCategory | BodyCategory
player.physicsBody?.allowsRotation = false
player.physicsBody?.friction = 1
player.physicsBody?.dynamic = true
self.addChild(player)
//Setup platform
platform.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame) - 100)
platform.physicsBody = SKPhysicsBody(rectangleOfSize: platform.size)
platform.physicsBody?.categoryBitMask = PlatformCategory
platform.physicsBody?.contactTestBitMask = BodyCategory
platform.physicsBody?.collisionBitMask = BodyCategory | EdgeCategory | PlayerCategory
platform.physicsBody?.allowsRotation = false
platform.physicsBody?.affectedByGravity = false
platform.physicsBody?.dynamic = true
platform.physicsBody?.friction = 1.0
platform.physicsBody?.restitution = 0.0
platform.physicsBody?.mass = 20
//Setup edge
let edge = SKNode()
edge.physicsBody = SKPhysicsBody(edgeFromPoint: CGPoint(x: 0, y:-platform.size.height/2), toPoint: CGPoint(x: self.frame.size.width, y:-platform.size.height/2))
edge.position = CGPoint(x:0, y: CGRectGetMidY(self.frame) - 100)
edge.physicsBody?.categoryBitMask = EdgeCategory
edge.physicsBody?.collisionBitMask = PlatformCategory
self.addChild(edge)
self.addChild(platform)
}
override func update(currentTime: NSTimeInterval) {
if(platform.position.x <= platform.size.width/2.0 + 20.0 && platform.physicsBody?.velocity.dx < 0.0 ){
platform.physicsBody?.velocity = CGVectorMake(platformSpeed, 0.0)
}else if((platform.position.x >= self.frame.size.width - platform.size.width/2.0 - 20.0) && platform.physicsBody?.velocity.dx >= 0.0){
platform.physicsBody?.velocity = CGVectorMake(-platformSpeed, 0.0)
}else if(platform.physicsBody?.velocity.dx > 0.0){
platform.physicsBody?.velocity = CGVectorMake(platformSpeed, 0.0)
}else{
platform.physicsBody?.velocity = CGVectorMake(-platformSpeed, 0.0)
}
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
let touch: AnyObject? = touches.anyObject()
let location = touch?.locationInNode(self)
if(location?.x > 187.5){
player.physicsBody?.applyImpulse(CGVector(dx: 3, dy: 50))
}else{
player.physicsBody?.applyImpulse(CGVector(dx: -3, dy: 50))
}
}
}
Here is the result :
this may be a duplicate of
Static Physics body still moving with contact
but I have not the reputation to add a comment.
My problem is with collisions and static bodies. I'm working on a little game and I have a player, so configured (from sks file):
player = worldNode.childNodeWithName("player") as! SKSpriteNode
let playerBodyTexture = SKTexture(imageNamed: "player_physicBody_mask")
player.physicsBody = SKPhysicsBody(texture: playerBodyTexture, size: CGSizeMake(player.size.width, player.size.height))
player.physicsBody!.usesPreciseCollisionDetection = true
player.physicsBody!.categoryBitMask = PhysicsCategory.player
player.physicsBody!.collisionBitMask = PhysicsCategory.ground | PhysicsCategory.enemies
player.physicsBody!.contactTestBitMask = PhysicsCategory.enemies
player.physicsBody!.restitution = 0
player.physicsBody!.friction = 0
player.physicsBody!.allowsRotation = false}
an enemy:
worldNode.enumerateChildNodesWithName("enemy") { node, _ in
let enemy = node as! SKSpriteNode
enemy.name = "enemy"
enemy.physicsBody = SKPhysicsBody(circleOfRadius: 17)
enemy.physicsBody!.dynamic = true
enemy.physicsBody!.mass = 0.4
enemy.physicsBody!.restitution = 0
enemy.physicsBody!.categoryBitMask = PhysicsCategory.enemies
enemy.physicsBody!.collisionBitMask = PhysicsCategory.ground | PhysicsCategory.player
enemy.physicsBody!.contactTestBitMask = PhysicsCategory.player}
and I have the platfrom brick, so configured:
worldNode.enumerateChildNodesWithName("fixedBlock") { node, _ in
let fixedBlock = node as! SKSpriteNode
fixedBlock.name = "fixedBlock"
let fixedBlockBodyTexture = SKTexture(imageNamed: "tripleBlocks_physicBody_mask")
fixedBlock.physicsBody = SKPhysicsBody(texture: fixedBlockBodyTexture, size: CGSizeMake(fixedBlock.size.width, fixedBlock.size.height))
fixedBlock.physicsBody!.categoryBitMask = PhysicsCategory.ground
fixedBlock.physicsBody!.collisionBitMask = PhysicsCategory.player | PhysicsCategory.enemies
fixedBlock.physicsBody!.contactTestBitMask = 0
fixedBlock.physicsBody!.dynamic = false
fixedBlock.physicsBody!.affectedByGravity = false
fixedBlock.physicsBody!.allowsRotation = false
fixedBlock.physicsBody!.pinned = false
fixedBlock.physicsBody!.friction = 0.3
fixedBlock.physicsBody!.restitution = 0}
When the player jumps on the enemies, he has an impulse (like Super Mario :-)), so I have this:
func didBeginContact(contact: SKPhysicsContact) {
let collision: UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
if collision == PhysicsCategory.player | PhysicsCategory.enemies {
self.player.physicsBody!.applyImpulse(CGVectorMake(0, 500))}}
Ok... sometimes, often, when the player jumps on enemy, the impulse appens correctly, but the ground tile moves down, also if its dynamic propriety is set on false. I tried to apply a JointFixed on the ground tile but when it is pushed down, its physic body "glitch"; I tried to print the physicsBody velocity propierty of the ground tile and when the problem occours, the velocity's dx vector is >100, but should static bodies not be affected by forces?
Any idea?
Many thanks
I have been struggling for the past two days to get two SKSpriteNodes to register a collision and evoke didBegin#contact.
I've set their bit masks 'categoryBitMask', 'contactTestBitMask' and 'collisionTestBitMask' for both objects.
I've also set the 'dynamic' property for both to 'true'
initPhysics() seems to set up the physicsWorld okay.
All I'm expecting is that didBegin#Contact is called, but it is not
//Set up Physicsbody bit masks
let playerCarBitMask: UInt32 = 0x1 << 1
let slowCarBitMask: UInt32 = 0x1 << 2
//initPhysics
func initPhysics() {
println("(((((((((((((( Initiating Physicsbody ))))))))))))))")
self.physicsWorld.contactDelegate = self
self.physicsWorld.gravity = CGVector.zeroVector
println("self.physicsWorld.contactDelegate = \(self.physicsWorld.contactDelegate)")
}
//setupPlayer
func setupPlayer() {
car = SKSpriteNode(imageNamed: "redCarUp")
car.setScale(2.0)
car.position = CGPoint(x: 800, y: 400)
car.zPosition = 100
car.name = "car"
gameNode.addChild(car)
let carBody = SKPhysicsBody(
rectangleOfSize: car.frame.size, center: car.position)
carBody.dynamic = true
carBody.categoryBitMask = playerCarBitMask
carBody.contactTestBitMask = slowCarBitMask
carBody.mass = 5
carBody.collisionBitMask = slowCarBitMask
car.physicsBody = carBody
println("carBody = \(carBody)")
println("carBody.dynamic = \(carBody.dynamic)")
println("carBody.mass = \(carBody.mass)")
println("carBody.categoryBitMask = \(carBody.categoryBitMask)")
println("carBody.contactTestBitMask = \(carBody.contactTestBitMask)")
println("carBody.collisionBitMask = \(carBody.contactTestBitMask)")
slowCar = SKSpriteNode(imageNamed: "blueCarUp")
slowCar.setScale(2.0)
let slowCarScenePos = CGPoint(
x: 680,
y: 2048)
slowCar.position = gameNode.convertPoint(slowCarScenePos, fromNode: self)
println("slowCar.position = \(slowCar.position) ****")
slowCar.zPosition = 80
slowCar.name = "slowCar"
let slowCarBody = SKPhysicsBody(
rectangleOfSize: slowCar.frame.size, center: slowCar.position)
println("slowCar = \(slowCar) ****")
slowCarBody.dynamic = true
slowCarBody.categoryBitMask = slowCarBitMask
slowCarBody.contactTestBitMask = playerCarBitMask
slowCarBody.mass = 5
slowCarBody.collisionBitMask = playerCarBitMask
slowCar.physicsBody = slowCarBody
gameNode.addChild(slowCar)
}
func didBeginContact(contact: SKPhysicsContact!) {
println("*******************PhysicsContact********************")
}
'didBeginContact' has been changed to 'didBegin' in swift 3
func didBegin(_ contact: SKPhysicsContact) {
//stuff
}
I had a code from swift 2 and 'didBeginContact' was sitting there but wasn't being called. After quite a white I figured out that the function was changed. So, I thought my answer could help someone.
If you want make a contact between car and slowCar you have to init the categoryBitMask of both physicsBodies (I think you did). See the code below to get contact between two physicsBodies. When there is a contact it returns your display function :
//init your categoryBitMask :
let carCategory:UInt32 = 0x1 << 0
let SlowCarCategory:UInt32 = 0x1 << 1
//init car
car.physicsBody?.categoryBitMask = carCategory
car.physicsBody?.contactTestBitMask = slowCarCategory
//init slowCar
slowCar.physicsBody?.categoryBitMask = slowCarCategory
slowCar.physicsBody?.contactTestBitMask = CarCategory
// set your contact function
func didBeginContact(contact: SKPhysicsContact!)
{
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask)
{
firstBody = contact.bodyA
secondBody = contact.bodyB
}
else
{
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if ((firstBody.categoryBitMask & carCategory) != 0 && (secondBody.categoryBitMask & slowCarCategory) != 0)
{
displayfunction(firstBody.node as SKSpriteNode, car: secondBody.node as SKSpriteNode)
}
}
func displayFunction (slowCar : SKSpriteNode, car : SKSpriteNode)
It turned out to be a simple problem. In my original code I was setting parameters for the SKPhysicsBody detection frame like so:
let carBody = SKPhysicsBody(
rectangleOfSize: car.frame.size, center: car.position)
Similarly I was doing the same for the second node that I was testing physics collisions for.
Simply removing the 'centre:' parameters like so:
let carBody = SKPhysicsBody(rectangleOfSize: car.frame.size)
for the two sprite nodes solved the problem and the nodes now crash into each other and push themselves aside as expected.
Please Note that contact will not be detected between two static bodies
(node.physicsBody?.isDynamic = false)