Reputation: 323
I have been developing a 2D SpriteKit
game that makes use of tile maps. I gave to my tile maps an SKPhysicsBody
with this func:
import SpriteKit
func giveTileMapPhysicsBody(map: SKTileMapNode) {
let tileMap = map
let tileSize = tileMap.tileSize
let halfWidth = CGFloat(tileMap.numberOfColumns) / 2.0 * tileSize.width
let halfHeight = CGFloat(tileMap.numberOfRows) / 2.0 * tileSize.height
for col in 0..<tileMap.numberOfColumns {
for row in 0..<tileMap.numberOfRows {
if let tileDefinition = tileMap.tileDefinition(atColumn: col, row: row)
{
//let isEdgeTile = tileDefinition.userData?["AddBody"] as? Int //uncomment this if needed, see article notes
//if (isEdgeTile != 0) {
let tileArray = tileDefinition.textures
let tileTexture = tileArray[0]
let x = CGFloat(col) * tileSize.width - halfWidth + (tileSize.width/8)
let y = CGFloat(row) * tileSize.height - halfHeight + (tileSize.height/8)
_ = CGRect(x: 0, y: 0, width: tileSize.width, height: tileSize.height)
let tileNode = SKNode()
tileNode.position = CGPoint(x: x, y: y)
tileNode.physicsBody = SKPhysicsBody(texture: tileTexture, size: CGSize(width: (tileTexture.size().width), height: (tileTexture.size().height)))
tileNode.physicsBody?.linearDamping = 0.8 //60.0
tileNode.physicsBody?.affectedByGravity = false
tileNode.physicsBody?.allowsRotation = false
tileNode.physicsBody?.restitution = 0.2
tileNode.physicsBody?.isDynamic = false
tileNode.physicsBody?.categoryBitMask = PhysicsCategory.tileMap
tileNode.physicsBody?.contactTestBitMask = PhysicsCategory.player
tileNode.physicsBody?.collisionBitMask = PhysicsCategory.player
tileNode.physicsBody?.friction = 0.8 // 3.0
tileMap.addChild(tileNode)
//}
}
}
}
}
As you can see on the first screenshot, when i run my game on the simulator everything works properly, but when i run it on my real iPhone or iPad there is a bug on the tile map physics (second image). As you can on the second image there is a physics gap when running it on my real devices. Do you know what it could be?
EDIT:
unfortunately it does not work on my project. The physics shape won't match the map correctly.
Upvotes: 2
Views: 84
Reputation: 1292
Try implementing it like this
typealias TileCoordinates = (column: Int, row: Int)
func giveTileMapPhysicsBody(map: SKTileMapNode) {
let tileMap = map
var physicsBodies = [SKPhysicsBody]()
for row in 0..<tileMap.numberOfRows {
for column in 0..<tileMap.numberOfColumns {
guard let tile = tile(in: tileMap, at: (column, row)) else { continue }
let center = tileMap.centerOfTile(atColumn: column, row: row)
let body = SKPhysicsBody(rectangleOf: tile.size, center: center)
physicsBodies.append(body)
}
}
tileMap.physicsBody = SKPhysicsBody(bodies: physicsBodies)
tileMap.physicsBody?.categoryBitMask = PhysicsCategory.tileMap
tileMap.physicsBody?.contactTestBitMask = PhysicsCategory.player
tileMap.physicsBody?.collisionBitMask = PhysicsCategory.player
tileMap.physicsBody?.linearDamping = 0.8 //60.0
tileMap.physicsBody?.affectedByGravity = false
tileMap.physicsBody?.allowsRotation = false
tileMap.physicsBody?.restitution = 0.2
tileMap.physicsBody?.isDynamic = false
tileMap.physicsBody?.friction = 0.8 // 3.0
}
func tile(in tileMap: SKTileMapNode, at coordinates: TileCoordinates) -> SKTileDefinition? {
return tileMap.tileDefinition(atColumn: coordinates.column, row: coordinates.row)
}
Upvotes: 1