Search code examples
swiftsprite-kitgame-physics

Physics Body not lining up with texture image on grid pattern for spritekit Swift


I'm working on a game, I've setup a grid pattern. Right now you can see in the screenshot, the small squares are the physicsBody where the collision is happening, these are not lining up with the images for some reason.

enter image description here

Here is the relevant code:

    override func didMove(to view: SKView) {
        ....
        let rockTexture = SKTexture(imageNamed: "pathrocks")
        let gapTexture = SKTexture(imageNamed: "claybricks")
        
        let tileSet = SKTileSet(tileGroups: [])
        let tileSize = CGSize(width: 32, height: 32)
        
        let rockTileGroup = SKTileGroup(rules: [])
        let rockTextureRule = SKTileGroupRule(adjacency: .adjacencyAll, tileDefinitions: [SKTileDefinition(texture: rockTexture)])
        rockTileGroup.rules.append(rockTextureRule)
        tileSet.tileGroups.append(rockTileGroup)
        
        let gapTileGroup = SKTileGroup(rules: [])
        let gapTextureRule = SKTileGroupRule(adjacency: .adjacencyAll, tileDefinitions: [SKTileDefinition(texture: gapTexture)])
        gapTileGroup.rules.append(gapTextureRule)
        tileSet.tileGroups.append(gapTileGroup)
        
        let columns = 20
        let rows = 10 // Increase the number of rows
        let tileMapNode = CustomTileMapNode(tileSet: tileSet, columns: columns, rows: rows, tileSize: tileSize)

        for x in 0..<columns {
            for y in 0..<rows {
                // Determine if it's a gap tile or a rock tile
                let isGapTile = (x == 4 || x == 5 || x == 6)
                let tileGroup = isGapTile ? gapTileGroup : rockTileGroup

                // Set the appropriate tile group for the tile
                tileMapNode.setTileGroup(tileGroup, forColumn: x, row: y)

                // Store the coordinates of gap tiles in the custom tile map node
                if isGapTile {
                    tileMapNode.gapTileCoords.append(TileCoord(column: x, row: y))
                }

                if !isGapTile {
                    let tileRect = CGRect(x: CGFloat(x) * tileSize.width,
                                          y: CGFloat(y) * tileSize.height,
                                          width: tileSize.width,
                                          height: tileSize.height)
                    
                    let tilePhysicsBody = SKPhysicsBody(edgeLoopFrom: tileRect)
                    tilePhysicsBody.categoryBitMask = 4 // You can set it to any appropriate bitmask value
                    tilePhysicsBody.contactTestBitMask = 1 // The car's categoryBitMask
                    let physicsBodyNode = SKNode()
                    physicsBodyNode.physicsBody = tilePhysicsBody
                    tileMapNode.addChild(physicsBodyNode)
                }
            }
        }

        tileMapNode.position = CGPoint(x: 0, y: 0)
        addChild(tileMapNode)


Solution

  • I fixed this by adding an Anchor Point, I added tileMapNode.anchorPoint = CGPoint(x: 0, y: 0) right after initializing the timeMapNode