I'm working on a Shooter Game coded in Swift 4, using SKSpriteNodes.
I've tried to make my game stop when an enemy, and to show the GameOverScene, but it does not work, and I don't understand why.
I've used the same kind of functions for the collision of the projectiles and the enemies, and it works well.
Here's my code, from the GameScene :
struct PhysicsCategory {
static let None : UInt32 = 0
static let All : UInt32 = UInt32.max
static let Monster : UInt32 = 0b1 // 1
static let Projectile: UInt32 = 0b10 // 2
static let Player : UInt32 = 0b01
}
override func didMove(to view: SKView) {
player.position = CGPoint(x: size.width * 0.1, y: size.height * 0.5)
player.zPosition = 2
player.physicsBody = SKPhysicsBody(rectangleOf: player.size) // 1
player.physicsBody?.isDynamic = true // 2
player.physicsBody?.categoryBitMask = PhysicsCategory.Monster // 3
player.physicsBody?.contactTestBitMask = PhysicsCategory.Projectile // 4
player.physicsBody?.collisionBitMask = PhysicsCategory.None // 5
addChild(player)
}
func addMonster() {
// Create sprite
let monster = SKSpriteNode(imageNamed: "monster")
monster.zPosition = 2
monster.physicsBody = SKPhysicsBody(rectangleOf: monster.size) // 1
monster.physicsBody?.isDynamic = true // 2
monster.physicsBody?.categoryBitMask = PhysicsCategory.Monster // 3
monster.physicsBody?.contactTestBitMask = PhysicsCategory.Projectile // 4
monster.physicsBody?.collisionBitMask = PhysicsCategory.None // 5
// Determine where to spawn the monster along the Y axis
let actualY = random(min: monster.size.height/2, max: size.height - monster.size.height/2)
// Position the monster slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
monster.position = CGPoint(x: size.width + monster.size.width/2, y: actualY)
// Add the monster to the scene
addChild(monster)
// vitesse augmentée
let actualDuration = random(min: CGFloat(1), max: CGFloat(4))
// Create the actions
let actionMove = SKAction.move(to: CGPoint(x: -monster.size.width/2, y: actualY), duration: TimeInterval(actualDuration))
let actionMoveDone = SKAction.removeFromParent()
monster.run(SKAction.sequence([ actionMove, actionMoveDone]))
}
func ennemyCollidesWithPlayer(monster: SKSpriteNode, player: SKSpriteNode){
print("Game Over")
let reveal = SKTransition.flipHorizontal(withDuration: 0.5)
let gameOverScene = GameOverScene(size: self.size, won: false)
self.view?.presentScene(gameOverScene, transition: reveal)
}
func didBegin(_ contact: SKPhysicsContact) {
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
}
//collision player et enemy
if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
(secondBody.categoryBitMask & PhysicsCategory.Player != 0)) {
if let player = firstBody.node as? SKSpriteNode, let
monster = secondBody.node as? SKSpriteNode {
ennemyCollidesWithPlayer(monster: monster, player: player)
}
}
}
categoryBitMask is the classification of the physics body on the current object it also the identifier used when checking the type of physics body
contactBitMask is setting the which objects will report in didBegin upon contact
both your player and monster have the same categoryBitMask set
change player to type PhysicsCategory.Player
you will also need to set the player contactBitMask to
contactTestBitMask = PhysicsCategory.Monster