Search code examples
iosobjective-csprite-kitgame-physics

Adjacent SKPhysicsBody not working properly


I am having a problem when trying to put two blocks that have physics bodies on top of one another.

http://s1173.photobucket.com/user/Kyle_Decot/media/example_zps02f027fe.mp4.html

As you can see in the video I am able to place my block on top of the stacked blocks even though they are placed right on top of one another.

Both the player block and the other blocks inherit from a base Block class which looks like this

#import "Block.h"

@implementation Block

+ (void)loadSharedAssets {

}

- (id)initWithColor:(UIColor *)color size:(CGSize)size {

    self = [super initWithColor:color size:size];

    if (self) {

        self.texture = [SKTexture textureWithImageNamed:@"tile"];

        self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: self.size];
        self.physicsBody.usesPreciseCollisionDetection = YES;
        self.physicsBody.dynamic = NO;


    }

    return self;
}

@end

Update

I've added a picture to make the problem a little more clear. Essentially the problem is that even though the blue blocks are right above one another, I am still able to jump up (w/ the red block) and sit on the edge of the bottom blue block (which shouldn't be possible). It seems something is off w/ the physics bodies or something.

enter image description here

You can see that the red block is slightly higher than the adjacent blue block for some reason and "sits" on the edge of the bottom blue block. when I jump up against it.


Solution

  • EDIT: replaced original suggestion with answer

    Scrolling to section 4.5 Edge Shapes of the box2d documentation and you will find the cause of this (SpriteKit uses Box2D under the hood for it's physics implementation)

    In many cases a game environment is constructed by connect several edge shapes end-to-end. This can give rise to an unexpected artifact when a polygon slides along the chain of edges. In the figure below we see a box colliding with an internal vertex. These ghost collisions are caused when the polygon collides with an internal vertex generating an internal collision normal.

    The two edges here (edge1 and edge2) are the left hand side edges of the two blue boxes in your game (so picture it rotated 90 digs counter-clockwise)

    Box2D introduced ChainShapes to get around this issue (which you can find referenced in section 5.6 Edge Shapes.

    The idea is to replace groups of square physics bodies with a chain of these vertices whenever generating more than one box at the same time.

    I believe you can access these within SpriteKit by using bodyWithEdgeChainFromPath and passing in a Core Graphics path consisting of the corner points of the boxes you want to combine to form the collision chain