swiftsprite-kitskphysicsbody

How can I position two SKSpritenodes on top of each other, if they both have an SKPhysicsBody set?


Am working, at a beginner's level, on a simple game. I have slots, and five balls for each slot.

The idea being that the balls go into the slots, and yes the balls have a zPosition that is one higher that the slots. But they are both children of the invisible slot holder underneath.

The balls fit into the slots if neither the slots or the balls has a physicsBody set. But if I give them a physicsBody then they push each other out of the way.

So obviously I still have some physics property I don't understand. If someone could point me in the way?

No Physics

Both with Physics set


Solution

  • You have collisions enabled between those 2 bodies.

    Collisions are handled by the physics engine and a collision occurs when 2 bodies bounce off each other. Bodies which are set up to collide cannot occupy the same space. Place 2 nodes on top of one another when they are set to collide and they will be pushed apart until no longer colliding.

    Contacts are when you want your code to be notified when 2 bodies make contact. Bodies can be set to make contact but not collide, collide but not make contact, collide and register contact or neither. Additionally one body can collide with a second body without the second body colliding with the first (the second body's movement will be unaffected by the collision, whilst the first body may go flying off).

    If you do nothing when creating your Sprite Kit environment, collision are enabled between all bodies (everything bounces off everything) and contacts are not enabled for any body (your code will never be called when bodies touch), so during set up is usual to have to turn off certain collisions and turn on certain contacts.

    Collisions between bodies can be turned off (leaving existing collisions unchanged) using:

    nodeA.physicsBody?.collisionBitMask &= ~nodeB.category
    

    We logically AND nodeA's collision bit mask with the inverse (logical NOT, the ~ operator) of nodeB's category bitmask to 'turn off' that bit nodeA's bitMask. e.g to stop the red circle from colliding with a 'slot':

    redCircle.physicsBody?.collisionBitMask = redCircle.physicsBody?.collisionBitMask & ~slotCategory
    

    which can be shortened to:

    redCircle.physicsBody?.collisionBitMask &= ~slotCategory
    

    this assumes that redCircle and slotCategory are the names you are using for the node and the category bit masks.

    This will stop the red circle from 'bouncing off' a slot, but won't stop a 'slot' bouncing off the red circle, so you may also need:

    slotX.physicsBody?.collisionBitMask &= ~circleCategory
    

    for every slot and assuming every circle shares the same category.

    More information here:

    my step-by-step guide for collisions and contacts: https://stackoverflow.com/a/51041474/1430420

    And a guide to collision and contactTest bit masks: https://stackoverflow.com/a/40596890/1430420

    Manipulating bit masks to turn individual collision ans contacts off and on. https://stackoverflow.com/a/46495864/1430420