I'm coding a simple game where the player must avoid obstacles as he plays, so I need to be able to check when the player makes contact with an obstacle. After following countless tutorials, I'm still not able to make it work. This is my code right now (I've taken out anything not relating to contact detection):
import SpriteKit
class GameScene: SKScene {
struct PhysicsCategory {
static let none : UInt32 = 0
static let all : UInt32 = UInt32.max
static let MrPig : UInt32 = 0b1 // 1
static let obstacle: UInt32 = 0b10 // 2
}
let airObstacles = ["spikeRectangle", "spikeSquare", "topSpikes", "bottomSpikes"]
let mrPig = SKSpriteNode(imageNamed: "mrPig")
var touching = false
override func didMove(to view: SKView) {
mrPig.physicsBody = SKPhysicsBody(circleOfRadius: projectile.size.width/2)
mrPig.physicsBody?.isDynamic = true
mrPig.physicsBody?.categoryBitMask = PhysicsCategory.MrPig
mrPig.physicsBody?.contactTestBitMask = PhysicsCategory.obstacle
mrPig.physicsBody?.collisionBitMask = PhysicsCategory.none
mrPig.physicsBody?.usesPreciseCollisionDetection = true
mrPig.position = CGPoint(x: 100, y: 80)
mrPig.zPosition = 2
mrPig.setScale(0.2)
addChild(mrPig)
physicsWorld.gravity = .zero
physicsWorld.contactDelegate = self
run(SKAction.repeatForever(
SKAction.sequence([
SKAction.run(moveDown),
SKAction.wait(forDuration: 0.1)
])
))
run(SKAction.repeatForever(
SKAction.sequence([
SKAction.run(createObstacle),
SKAction.wait(forDuration: TimeInterval(objectSpeed))
])
))
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if touches.first != nil {
touching = true
mrPig.run(SKAction.moveTo(y: size.height - 20, duration: 0.8))
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if touches.first != nil {
touching = false
}
}
func moveDown() {
if touching == false && mrPig.position.x > 80 {
mrPig.run(SKAction.moveTo(y: 80, duration: 0.5))
}
}
func createObstacle() {
let airObstacle = SKSpriteNode(imageNamed: airObstacles.randomElement()!)
airObstacle.physicsBody = SKPhysicsBody(rectangleOf: airObstacle.size) // 1
airObstacle.physicsBody?.isDynamic = true // 2
airObstacle.physicsBody?.categoryBitMask = PhysicsCategory.obstacle // 3
airObstacle.physicsBody?.contactTestBitMask = PhysicsCategory.MrPig // 4
airObstacle.physicsBody?.collisionBitMask = PhysicsCategory.none // 5
airObstacle.position = CGPoint(x: size.width, y: 200)
airObstacle.zPosition = 2
addChild(airObstacle)
let moveAirObstacle = SKAction.moveTo(x: 0, duration: 2)
let moveAirObstacleDone = SKAction.removeFromParent()
airObstacle.run(SKAction.sequence([moveAirObstacle, moveAirObstacleDone]))
}
}
}
extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
// 1
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// 2
if ((firstBody.categoryBitMask & PhysicsCategory.obstacle != 0) &&
(secondBody.categoryBitMask & PhysicsCategory.MrPig != 0)) {
print("game over")
}
}
}
I'm relatively new to coding, and this is the first game I've ever made with swift. Any help would be much appreciated!