I have a bomb spawner in GameScene.swift that adds SKShapeNodes to the Scene. Each SKShapeNode is a physics object that falls and has the name set to "bomb". I want to detect when the user touches these nodes (mid-fall using touchesBegan), but it doesn't work. What am I doing wrong?
// Bomb Spawner Function
func spawnBomb() {
let bombHeight = 80
let bomgWidth = 40
// Define Bomb
let bomb = SKShapeNode(rectOf: CGSize(width: bomgWidth,
height: bombHeight))
bomb.name = "bomb"
bomb.zPosition = 10
bomb.isUserInteractionEnabled = true
bomb.position = CGPoint(x: size.width / 2, y: size.height / 2)
bomb.fillColor = SKColor.blue
// Add Physics Body
bomb.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: bomgWidth,
height: bombHeight))
// Determine Random Position
let randomPosition = abs(CGFloat(random.nextInt()).truncatingRemainder(dividingBy: size.width))
bomb.position = CGPoint(x: randomPosition, y: size.height)
// Add Category BitMask
bomb.physicsBody?.categoryBitMask = BombCategory
bomb.physicsBody?.contactTestBitMask = WorldFrameCategory
// Add to the scene
addChild(bomb)
}
Touch Detection
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if let name = touchedNode.name
{
if name == "bomb"
{
print("bomb Touched")
}
}
}
My suspicion is that your problem stems from the fact that atPoint returns an SKNode. You have two ways of getting the topmost node:
if atPoint(touch.location(in: self)) == childNode(withName: "bomb"){
//run your code
}
That's fine for individual nodes. Personally, I like using a subclass, so I would use
class Bomb: SKShapeNode
and simply see whether the topmost node under my touch can be cast to Bomb.
if let bomb = atPoint(touch.location(in: self)) as? Bomb {
//...
}
This lets you move your bomb-typical settings into the subclass and makes for more readable code overall.