0

In my xcode project I am trying to create a function that gets called when a SKShapeNode hits the world border(edge of screen) that I have created. The SKShapeNode hits the edge of the screen and rolls to the right due to the gravity but when the contact is made the function didBeginContact isnt called. here is my code

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

struct PhysicsCategory {

    static let redBall: UInt32 =  0x1 << 1
    static let blueBall:  UInt32 = 0x1 << 2
    static let worldBorder: UInt32 = 0x1 << 3

}

let slimeBall = SKSpriteNode(imageNamed: "slimeBall")
let lilyPete = SKSpriteNode(imageNamed:"golden")



override func didMoveToView(view: SKView) {

    self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    self.physicsWorld.gravity = CGVectorMake(1, 5)
    self.physicsBody?.categoryBitMask = PhysicsCategory.worldBorder
    self.physicsBody!.node?.name = "world"


    self.backgroundColor = UIColor.darkGrayColor()

    let playerCircle = SKShapeNode(circleOfRadius: 15)
    playerCircle.name = "blueCircle"
    playerCircle.fillColor = UIColor.blueColor()
    playerCircle.strokeColor = UIColor.blackColor()
    playerCircle.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2)
    playerCircle.physicsBody?.categoryBitMask = PhysicsCategory.redBall
    playerCircle.physicsBody?.contactTestBitMask = PhysicsCategory.worldBorder | PhysicsCategory.redBall
    playerCircle.physicsBody?.collisionBitMask = PhysicsCategory.blueBall | PhysicsCategory.worldBorder

    addChild(playerCircle)

    let enemyCircle = SKShapeNode(circleOfRadius: 50)
    enemyCircle.name = "redCircle"
    enemyCircle.fillColor = UIColor.redColor()
    enemyCircle.strokeColor = UIColor.blackColor()
    enemyCircle.physicsBody = SKPhysicsBody(circleOfRadius: 50)
    enemyCircle.position = CGPointMake(self.frame.size.width / 3, self.frame.size.height / 2)
    enemyCircle.physicsBody?.affectedByGravity = true
    enemyCircle.physicsBody?.dynamic = true
    enemyCircle.physicsBody!.mass = 0.05
    enemyCircle.physicsBody?.categoryBitMask = PhysicsCategory.blueBall
    enemyCircle.physicsBody?.contactTestBitMask = PhysicsCategory.worldBorder | PhysicsCategory.blueBall
    enemyCircle.physicsBody?.collisionBitMask = PhysicsCategory.worldBorder | PhysicsCategory.blueBall

    addChild(enemyCircle)
    enemyCircle.physicsBody?.applyForce(CGVectorMake(-2, -3))



  }


func didBeginContact(contact: SKPhysicsContact) {

    let firstBody = contact.bodyA
    let secondBody = contact.bodyB

    if(contact.bodyA.node?.name == "redCircle") && (contact.bodyB.node?.name == "world") || (contact.bodyA.node?.name == "world") && (contact.bodyB.node?.name == "redCircle"){

        print("Contact Made")


    }






}


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {


    let touch = touches.first! as UITouch
    let touchLocation = touch.locationInNode(self)




}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {


    let touch = touches.first! as UITouch
    let touchLocation = touch.locationInNode(self)

}


}
Charles
  • 31
  • 3

2 Answers2

0

Your red circle has a category bit mask of blueBall and has a contact bit mask to only interact with the worldBorder and other blueBall. Your blue circle has a category bit mask of redBall and will only contact the worldBorder and other blueBall.

Set your red circle's category to actually be a redBall, and you set your blue circle's category to actually be a blueBall, then all of your collisions should be working. You may wish to run through your bit masks again now that those two were swapped to make sure that everything is colliding with everything else as it should, as you did not mention how it should be set up.

However, one quick note in your didBeginContact method, you do not wrap your if statement checks (IMO) properly. In fact, you don't at all. I recommend wrapping your checks as such:

if ((contact.bodyA.node?.name == "redCircle") && (contact.bodyB.node?.name == "world")) || ((contact.bodyA.node?.name == "world") && (contact.bodyB.node?.name == "redCircle")) {

This will check everything on one side of the || to everything on the other side, which then will allow your && to reside by itself only checking everything in its parenthesis pair.

Gliderman
  • 1,195
  • 9
  • 18
0

In DidMoveToView you need to call

physicsWorld.contactDelegate = self

otherwise the Contact method will never fire.

Furthermore for your player circle you are not giving it a physics body like

 playerCircle.physicsBody = SKPhysicsBody(...)

Than change your DidBeginContact method to this so you do not have to do 2 checks for each collision. Also use the PhysicsCategory to identify them instead of names.

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 == PhysicsCategory.redBall) && (secondBody.categoryBitMask == PhysicsCategory.worldBorder) {

        // red ball hit world border, do something
    }

    if (firstBody.categoryBitMask == PhysicsCategory.blueBall) && (secondBody.categoryBitMask == PhysicsCategory.worldBorder) {

        // blue ball hit world border, do something
    }
}

Also as a tip, on some physicsBodies you are force unwrapping with a !

self.physicsBody!.node?.name = "world"
enemyCircle.physicsBody!.mass = 0.05.

which could cause a crash if no physicsBody is found.

Its better to always use ? whenever you can, which you are already doing for most of them.

Also try to give your sprite their position before giving them a physicsBody because otherwise you could get some unexpected results.

 enemyCircle.position = CGPointMake(self.frame.size.width / 3, self.frame.size.height / 2)
 enemyCircle.physicsBody = SKPhysicsBody(circleOfRadius: 50)
 enemyCircle.physicsBody.categoryBitMask = ...
 ...

Hope this helps

crashoverride777
  • 10,581
  • 2
  • 32
  • 56