Sam
Sam

Reputation: 161

Gap between SKSpriteNodes in SpriteKit collision detection

I've been trying to figure this out for quite a while now -- I have a game with simple platformer physics where a player falls onto a block, which stops him from falling. This works, however there is a noticeable gap between where the player stops, and where the actual object/spritenode is. Here is a screenshot, it should be self-explanatory:

enter image description here

class GameScene: SKScene {

override init(){
    super.init(size: UIScreen.mainScreen().bounds.size)
    self.physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
func genBlock(iteration: CGFloat){
    let block = SKSpriteNode(color: UIColor.blackColor(), size: CGSizeMake(100,50))
    block.position = CGPointMake((iteration*50)-block.size.width/2,0)
    block.physicsBody = SKPhysicsBody(edgeLoopFromRect: CGRectMake(0,0,block.size.width,block.size.height))
    self.addChild(block)
}
func genPlayer(){
    let char = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(100,100))
    char.position = CGPointMake(0,500)
    char.physicsBody = SKPhysicsBody(rectangleOfSize: char.size)
    self.addChild(char)
}
override func didMoveToView(view: SKView) {
    /* Setup your scene here */
    view.backgroundColor = UIColor.whiteColor()
    self.view?.backgroundColor = UIColor.whiteColor()
    genBlock(0)
    genBlock(1)
    genBlock(2)
    genBlock(3)
    genBlock(4)
    genPlayer()
}
}

I feel as though this isn't an issue with SpriteKit and is instead an issue with my code. Any advice on how to remove this gap between the nodes would be greatly appreciated.

EDIT: I've submitted this to Apple's bug reporter, but I don't expect to receive anything in reply. If anyone is coming here long after this was posted, it would be great if you could submit your suggestions here.

Upvotes: 4

Views: 279

Answers (1)

Trent Sartain
Trent Sartain

Reputation: 446

I believe it has to do with physicsBodies built from a CGPath. For instance, using the code below to create 6 squares:

override func didMoveToView(view: SKView) {
    self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    self.physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
    self.backgroundColor = UIColor.whiteColor()

    let square1 = SKSpriteNode(color: UIColor.blackColor(), size: CGSize(width: 50, height: 50))
    square1.physicsBody = SKPhysicsBody(edgeLoopFromRect: CGRect(x: -25, y: -25, width: square1.size.width, height: square1.size.height))
    square1.position = CGPoint(x: self.size.width/2 - 75, y: 25)
    self.addChild(square1)

    let square2 = SKSpriteNode(color: UIColor.greenColor(), size: CGSize(width: 50, height: 50))
    square2.physicsBody = SKPhysicsBody(rectangleOfSize: square2.size)
    square2.position = CGPoint(x: self.size.width/2 - 75, y: 200)
    self.addChild(square2)

    let square3 = SKSpriteNode(color: UIColor.blueColor(), size: CGSize(width: 50, height: 50))
    square3.physicsBody = SKPhysicsBody(rectangleOfSize: square3.size)
    square3.position = CGPoint(x: self.size.width/2 + 75, y: 200)
    self.addChild(square3)

    let squarePath = getSquarePath()
    let square4 = SKSpriteNode(color: UIColor.redColor(), size: CGSize(width: 50, height: 50))
    square4.physicsBody = SKPhysicsBody(polygonFromPath: squarePath)
    square4.position = CGPoint(x: self.size.width/2 + 75, y: 400)
    self.addChild(square4)

    let square5 = SKSpriteNode(color: UIColor.orangeColor(), size: CGSize(width: 50, height: 50))
    square5.physicsBody = SKPhysicsBody(rectangleOfSize: square5.size)
    square5.position = CGPoint(x: self.size.width/2, y: 200)
    self.addChild(square5)

    let square6 = SKSpriteNode(color: UIColor.purpleColor(), size: CGSize(width: 50, height: 50))
    square6.physicsBody = SKPhysicsBody(rectangleOfSize: square6.size)
    square6.position = CGPoint(x: self.size.width/2, y: 400)
    self.addChild(square6)
}

func getSquarePath() -> CGPath {
    let path = CGPathCreateMutable()
    CGPathMoveToPoint(path, nil, -25, -25)
    CGPathAddLineToPoint(path, nil, -25, 25)
    CGPathAddLineToPoint(path, nil, 25, 25)
    CGPathAddLineToPoint(path, nil, 25, -25)
    CGPathCloseSubpath(path)

    return path
}

you can see that the squares with physicsBodies created from CGPath (this includes edgeLoopFromRect) have that gap issue. Even the physicsBody for the scene's edge loop has this issue. This also shows up for me when I build the physicsBody using the texture constructors which appears to build a CGPath under the hood.

I haven't found a fix for it other than to not use those types of physicsBodies for long term (visible) collisions.

Upvotes: 2

Related Questions