Reputation: 5441
I noticed this issue has happened to a lot of people. I made sure to have the self.physicsWorld.contactDelegate = self
in the didMove function but it still doesn't work. Here is my code:
class PoolTableScene: SKScene, SKPhysicsContactDelegate {
struct PhysicsCatagory {
static let None : UInt32 = 0 //0
static let OrangeBall : UInt32 = 0b1 //1
static let BlueBall : UInt32 = 0b10 //2
static let PokeBall : UInt32 = 0b100 //3
static let Border : UInt32 = 0b1000 //4
static let All : UInt32 = UInt32.max
}
let ballPoke = SKSpriteNode(imageNamed:"pokeBall")
let ballBlue = SKSpriteNode(imageNamed:"blueBall")
let ballOrange = SKSpriteNode(imageNamed: "orangeBall")
//var lastTouch: CGPoint? = nil
override func didMove(to view: SKView) {
self.physicsWorld.contactDelegate = self
self.physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
//used to set gravity
//creates body for sprite that will lock the objects to a specific area
let sceneBody = SKPhysicsBody(edgeLoopFrom: self.frame)
sceneBody.friction = 0 //This will make the ball bounce naturally off the edges of the scenBody
self.physicsBody = sceneBody // make physics only affect whats in sceneBody - NEED PHYSICS BODY UNLESS IT WON'T BE AFFECTED BY PHYSICS
self.physicsBody?.categoryBitMask = PhysicsCatagory.Border
self.physicsBody?.collisionBitMask = PhysicsCatagory.BlueBall | PhysicsCatagory.OrangeBall | PhysicsCatagory.PokeBall
self.physicsBody?.contactTestBitMask = PhysicsCatagory.None
ballPoke.name = "ballPoke"
ballPoke.size = CGSize(width: 50, height: 50)
ballPoke.anchorPoint = CGPoint(x:0.5, y:0.5)
ballPoke.position = CGPoint(x: self.frame.size.width*0.25, y:self.frame.size.height/2)
ballPoke.zPosition = 100
ballPoke.physicsBody = SKPhysicsBody(circleOfRadius: 25)//need this so the ball can be affected by physics
ballPoke.physicsBody?.affectedByGravity = true //ball will be affected by gravity determined by the scene's physics
ballPoke.physicsBody?.restitution = 1 // sets bounciness of ball
ballPoke.physicsBody?.linearDamping = 0 //used to set how air resistence will affect ball
ballPoke.physicsBody?.categoryBitMask = PhysicsCatagory.PokeBall
ballPoke.physicsBody?.collisionBitMask = PhysicsCatagory.BlueBall | PhysicsCatagory.Border
ballPoke.physicsBody?.contactTestBitMask = PhysicsCatagory.OrangeBall
self.addChild(ballPoke)
ballBlue.name = "ballBlue"
ballBlue.size = CGSize(width: 50, height: 50)
ballBlue.anchorPoint = CGPoint(x:0.5, y:0.5)
ballBlue.position = CGPoint(x: self.frame.size.width*0.50, y:self.frame.size.height/3)
ballBlue.zPosition = 100
ballBlue.physicsBody = SKPhysicsBody(circleOfRadius: 25)//need this so the ball can be affected by physics
ballBlue.physicsBody?.affectedByGravity = true //ball will be affected by gravity determined by the scene's physics
ballBlue.physicsBody?.restitution = 1 // sets bounciness of ball
ballBlue.physicsBody?.linearDamping = 0 //used to set how air resistence will affect ball
ballBlue.physicsBody?.categoryBitMask = PhysicsCatagory.BlueBall
ballBlue.physicsBody?.collisionBitMask = PhysicsCatagory.OrangeBall | PhysicsCatagory.PokeBall | PhysicsCatagory.Border
ballBlue.physicsBody?.contactTestBitMask = PhysicsCatagory.None
self.addChild(ballBlue)
ballOrange.name = "ballOrange"
ballOrange.size = CGSize(width: 50, height: 50)
ballOrange.anchorPoint = CGPoint(x:0.5, y:0.5)
ballOrange.position = CGPoint(x: self.frame.size.width*0.75, y:self.frame.size.height/2)
ballOrange.zPosition = 100
ballOrange.physicsBody = SKPhysicsBody(circleOfRadius: 25)//need this so the ball can be affected by physics
ballOrange.physicsBody?.affectedByGravity = true //ball will be affected by gravity determined by the scene's physics
ballOrange.physicsBody?.restitution = 1 // sets bounciness of ball
ballOrange.physicsBody?.linearDamping = 0 //used to set how air resistence will affect ball
ballOrange.physicsBody?.categoryBitMask = PhysicsCatagory.OrangeBall
ballOrange.physicsBody?.collisionBitMask = PhysicsCatagory.BlueBall | PhysicsCatagory.Border
ballOrange.physicsBody?.contactTestBitMask = PhysicsCatagory.PokeBall
self.addChild(ballOrange)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
//Finds the position where user touches screen
for touch: AnyObject in touches {
let positionOfTouch = touch.location(in: self)
//drags ball to where user touches screen
let dragBallAction = SKAction.move(to: CGPoint(x: positionOfTouch.x, y: positionOfTouch.y), duration: 0.5)
ballOrange.run(dragBallAction)
}
}
func didBeginContact(contact: SKPhysicsContact) {
print("contact")
var contactBody1: SKPhysicsBody
var contactBody2: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
contactBody1 = contact.bodyA
contactBody2 = contact.bodyB
}
else// else almost never gets called but still add it to function
{
contactBody1 = contact.bodyB
contactBody2 = contact.bodyA
}
//this uses the catagories set up in above struct (1 = Square, 2 = Ball)
if ((contactBody1.categoryBitMask == 1) && (contactBody2.categoryBitMask == 3)) {
//if the ball contact the square, remove the ball
contactBody2.node!.removeFromParent()
}
}
}
Upvotes: 1
Views: 312
Reputation: 8134
Read my answer on this question SpriteKit - Making certain SpriteNodes NOT collide without disabling their physics bodies which describes the difference between collisions and contacts.
Also try implementing my checkPhysics()
function (source is in the same answer) which will analyse your scene and list which nodes collide with which other nodes and also which nodes notify when contacting other nodes.
The output will be something like this for a physicsDemo I have with 4 SKSPriteNodes called shape_blueSquare, shape_redCircle, shape_purpleSquare, shape_greenRect & shape_yellowTriangle and a border around the screen called "Screen_edge".
Optional("shape_blueSquare") collides with Optional("Screen_edge")
Optional("shape_blueSquare") collides with Optional("shape_redCircle")
Optional("shape_blueSquare") collides with Optional("shape_purpleSquare")
Optional("shape_blueSquare") collides with Optional("shape_greenRect")
Optional("shape_redCircle") collides with Optional("Screen_edge")
Optional("shape_redCircle") collides with Optional("shape_blueSquare")
Optional("shape_redCircle") notifies when contacting Optional("shape_purpleSquare")
Optional("shape_redCircle") collides with Optional("shape_greenRect")
Optional("shape_redCircle") notifies when contacting Optional("shape_greenRect")
Optional("shape_purpleSquare") collides with Optional("Screen_edge")
Optional("shape_purpleSquare") collides with Optional("shape_greenRect")
Category for Optional("shape_greenRect") does not appear to be set correctly as 4294967295
ptional("shape_greenRect") collides with Optional("Screen_edge")
Optional("shape_yellowTriangle") collides with Optional("Screen_edge")
Optional("shape_yellowTriangle") notifies when contacting Optional("shape_redCircle")
Optional("shape_yellowTriangle") collides with Optional("shape_greenRect")
Optional("shape_yellowTriangle") notifies when contacting Optional("shape_greenRect")
Upvotes: 1
Reputation: 611
the property that detects collision is contact test bit mask that is why its just passing through i think you have collision bit mask and contact test bit mask confused with each other
contact test is what detects contact while collision bit mask allows bodies to pass through each other
Upvotes: 0
Reputation: 2818
I had that same problem and because I'm not too familiar with how ContactA and ContactB works, I gave each object a name and check if those two objects collide like so.
func didMoveToView(view: SKView) {
objectA = self.childNodeWithName("ObjectA") as! SKSpriteNode!
objectB = self.childNodeWithName("ObjectB") as! SKSpriteNode!
}
func didBeginContact(contact: SKPhysicsContact) {
let contactA: SKPhysicsBody = contact.bodyA
let contactB: SKPhysicsBody = contact.bodyB
let nodeA = contactA.node as! SKSpriteNode
let nodeB = contactB.node as! SKSpriteNode
if nodeA.name == "ObjectA" && nodeB.name == "ObjectB" {
//do something
}
}
Upvotes: 1