Reputation: 6707
I have a Tile Map Node
that covers my entire game scene (GameScene.sks
). There's an enemy at the top of the screen. And there are tiny houses that are laid out at the bottom. Only these houses come from the tile map node. The enemy is supposed to fire a shot at any of those houses. contactBitMask
is set to both fired shots and house tiles. And I want to remove the house that is being hit by the shot with contactBitMask
. Anyway, I have the following lines code.
class GameScene: SKScene, SKPhysicsContactDelegate {
var destructibleCount = Int() // destructibleCount
func setupDestructiblePhysics() {
guard let obstaclesTileMap = obstaclesTileMap else { return }
for row in 0..<obstaclesTileMap.numberOfRows {
for column in 0..<obstaclesTileMap.numberOfColumns {
guard let tile = tile(in: obstaclesTileMap, at: (column, row)) // a function returning SKTileDefinition
else { continue }
guard tile.userData?.object(forKey: "destructible") != nil // 'destructible' is set through TileSet
else { continue }
let node = SKNode()
node.physicsBody = SKPhysicsBody(rectangleOf: tile.size)
node.physicsBody?.isDynamic = false
node.physicsBody?.categoryBitMask = PhysicsCategory.Building
node.position = obstaclesTileMap.centerOfTile(atColumn: column, row: row)
node.name = "building"
obstaclesTileMap.addChild(node)
destructibleCount += 1
}
}
}
func didBegin(_ contact: SKPhysicsContact) {
let enemyBeamContact = contact.bodyA.categoryBitMask == PhysicsCategory.EnemyShot ? contact.bodyB : contact.bodyA
switch enemyBeamContact.categoryBitMask {
case PhysicsCategory.Building:
if let nodeA = contact.bodyA.node {
let column = obstaclesTileMap!.tileColumnIndex(fromPosition: nodeA.position)
let row = obstaclesTileMap!.tileRowIndex(fromPosition: nodeA.position)
print(column, row)
enumerateChildNodes(withName: "building", using: { node, _ in
if node.position == nodeA.position {
node.removeFromParent()
}
})
if let tile = tile(in: obstaclesTileMap!, at: (column, row)) {
// not being used
}
}
if let nodeB = contact.bodyB.node {
// bullet //
if nodeB.name == "beam" {
nodeB.removeFromParent()
}
}
default:
break
}
}
}
When a shot hits a house, the didBegin
physics methods does tell me the tile that is being hit. (See print(column, row)). What I have difficulty with is how to remove the tile that is being hit. node.removeFromParent() isn't effective. And I cannot remove any of the tiles. I have a feeling that you cannot remove one tile. Or can we? I thought use of tiles is an efficient way of developing SpriteKit games. But it seems otherwise to me. I guess I could just add those houses to the scene programatically. Thanks.
Upvotes: 2
Views: 729
Reputation: 696
An SKTilemapNode
is a whole in itself, so contact test will only tell you when you make contact with the tile map, not the individual tiles.
What you can do though, is use a tilemap to design the levels, but in the didMove(to:)
function, you walk the tile map and create individual SKSpriteNode
for each house you find. You can use SKTilemapNode
's functions to get the info you need (which texture you used, position, etc):
Once you are done walking the tilemap and all your houses are created, remove the tilemap from the scene and make contact with the houses as you would normally.
Hope it helps!
Upvotes: 2