0

This is the setup

    // Create a scene
    scene = SKScene(size: self.view.frame.size)

    let sceneHeight = scene.frame.height
    let sceneWidth = scene.frame.width

    // Create nodes
    // Rectangle
    let shapeWidth: CGFloat = 100
    let shapeHeight = shapeWidth
    let shapeNode = SKShapeNode(rect: CGRectMake(0, 0, shapeWidth, 100))
    shapeNode.position = CGPoint(x: sceneWidth/2 - shapeWidth/2, y: 300)
    shapeNode.fillColor = UIColor.redColor()
    shapeNode.strokeColor = UIColor.redColor()

    // Floor
    let floorWidth: CGFloat = sceneWidth
    let floorHeight: CGFloat = 10
    let floorNode = SKShapeNode(rect: CGRectMake(0, 0, floorWidth, floorHeight))
    floorNode.position = CGPoint(x: 0, y: 100)
    floorNode.fillColor = UIColor.greenColor()
    floorNode.strokeColor = UIColor.greenColor()

    // Create the node tree
    scene.addChild(floorNode)
    scene.addChild(shapeNode)

Then I define and add two physics bodies to my two nodes.

    // Create physics
    let shapePhysicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: shapeWidth, height: shapeHeight))
    shapePhysicsBody.dynamic = true
    shapePhysicsBody.categoryBitMask = PhysicsCategory.Shape
    shapePhysicsBody.contactTestBitMask = PhysicsCategory.Floor
    shapePhysicsBody.collisionBitMask = PhysicsCategory.None
    shapePhysicsBody.usesPreciseCollisionDetection = true

    let floorPhysicsBody = SKPhysicsBody(rectangleOfSize: CGSize(width: floorWidth, height: floorHeight))
    floorPhysicsBody.dynamic = true
    floorPhysicsBody.categoryBitMask = PhysicsCategory.Floor
    floorPhysicsBody.contactTestBitMask = PhysicsCategory.Shape
    floorPhysicsBody.collisionBitMask = PhysicsCategory.None
    floorPhysicsBody.usesPreciseCollisionDetection = true
    floorPhysicsBody.affectedByGravity = false

    // Add physics
    shapeNode.physicsBody = shapePhysicsBody
    floorNode.physicsBody = floorPhysicsBody
    scene.physicsWorld.gravity = CGVector(dx: 0, dy: -1)
    scene.physicsWorld.contactDelegate = self

This sort of works, that is the rectangle shape does fall from it's initial position and the collision delegate is called when a collision happens.

The contents of my didBeginContact: method.

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.Floor != 0) && (secondBody.categoryBitMask & PhysicsCategory.Shape != 0)) {
        secondBody.dynamic = false
        println("collision")
    }
}

But the shape node stops way before there's a visual contact. I hope these images give an impression of how that looks.

Starts here Initial state

This is where the contact happens Final state

Why is there such a gap between them? What am I missing? I want them to visually touch each other before the rectangle stops moving.

Morgan Wilde
  • 16,795
  • 10
  • 53
  • 99
  • 1
    Have you checked is everything is in place with physics bodies? Turn on physics visual representation in your view controller skView.showsPhysics = YES; – Whirlwind Mar 04 '15 at 17:29
  • @Whirlwind that is probably the first thing anyone dealing with SpriteKit should do :) thanks! – Morgan Wilde Mar 04 '15 at 18:54
  • Make sure to use SKShapeNode wisely, because shape nodes cannot be drawn in a single pass. Take a look at this : http://stackoverflow.com/questions/23344235/skshapenode-consuming-too-much-memory-and-slowing-down-animation-spritekit-ios Using SKSpriteNode and initializing it with color would be a better way if you just need colored sprites like in your example. – Whirlwind Mar 04 '15 at 22:57

1 Answers1

1

SKShapeNode(rect:) draws the SKShapeNode with the node.position as origin. For the SKPhysicsBody position corresponds to the center of the rectangle. This creates an offset between the physics body and the actual node. You can see that if you enable

scene.view?.showsPhysics = true.

You can correct the offset by creating the SKShapeNode using following code.

let shapeNode = SKShapeNode(rect: CGRectMake(-shapeWidth/2, -50, shapeWidth, 100))
// Other code
let floorNode = SKShapeNode(rect: CGRectMake(-floorWidth/2, -floorHeight/2, floorWidth, floorHeight))
rakeshbs
  • 24,392
  • 7
  • 73
  • 63
  • Still seems a bit strange that they position the `SKPhysicsBody` to the center of the rectangle. Is there a good reason why? – Morgan Wilde Mar 04 '15 at 18:54