Below is my "Floor.swift" class below which is basically a bunch of walls. I have objects coming from the top of the screen and once the Floor and SKSpriteNodes collide, I'd like the SKSpriteNode to be removed. Below is my Floor class.
import Foundation
import SpriteKit
class Floor: SKNode {
override init() {
super.init()
let leftWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 5, height: 50))
leftWall.position = CGPoint(x: 0, y: 50)
leftWall.physicsBody = SKPhysicsBody(rectangleOf: leftWall.size)
leftWall.physicsBody!.isDynamic = false
self.addChild(leftWall)
let rightWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 5, height: 50))
rightWall.position = CGPoint(x: 375, y: 50)
rightWall.physicsBody = SKPhysicsBody(rectangleOf: rightWall.size)
rightWall.physicsBody!.isDynamic = false
self.addChild(rightWall)
let bottomWall = SKSpriteNode(color: UIColor.clear, size: CGSize(width: 500, height: 10))
bottomWall.position = CGPoint(x: 150, y: -5)
bottomWall.physicsBody = SKPhysicsBody(rectangleOf: bottomWall.size)
bottomWall.physicsBody!.isDynamic = false
self.addChild(bottomWall)
self.physicsBody = SKPhysicsBody(bodies: [leftWall.physicsBody!, rightWall.physicsBody!, bottomWall.physicsBody!])
self.physicsBody?.categoryBitMask = floorCategory
self.physicsBody?.contactTestBitMask = nailDropCategory | pointCategory | lifeCategory
self.physicsBody?.collisionBitMask = balloonCategory
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemted")
}
}
GameScene class under "func didBegin(_ contact: SKPhysicsContact)" I wrote:
func didBegin(_ contact: SKPhysicsContact) {
if (contact.bodyA.categoryBitMask == nailDropCategory | pointCategory | lifeCategory) && (contact.bodyB.categoryBitMask == floorCategory) {
// contact.bodyB.node!.removeFromParent()
print("COLLISION")
}
}
As you can see, in my Floor class I set the object as "self.physicsBody = SKPhysicsBody(bodies:)" with all my SKSpriteNode. But for some reason I'm not getting any detection what's so ever. I made my "Floor" class be a "contactTestBitMask" on each class of my objectCategory, pointCategory, lifeCategory. This has been an issue I've been stuck on for a minute now, any ideas?
Update:
So I'm using this code below now and it's working! Only issue is, the default case is removing my "balloonCategory" also and I don't want it to do that. How can I make it ignore only that category but also act as a wall to the balloon?
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case balloonCategory | nailDropCategory:
print("nailDrop and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
self.run(SKAction.playSoundFileNamed("lostlifesound.mp3", waitForCompletion:false))
lifeLost -= 1
case balloonCategory | pointCategory:
print("point and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
totalPoints += 2
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
case balloonCategory | lifeCategory:
print("life and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
lifeLost += 1
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
default:
contact.bodyB.node!.removeFromParent()
print("Removed \(String(describing: contact.bodyB.node!.name))")
}
}
It sounds like you would benefit from assigning names to all your object types, like so:
class Balloon: SKSpriteNode {
init() {
super.init(texture: nil, color: .blue, size: CGSize(width: 50, height: 50))
self.name = "balloon"
}
}
Now when you make your check in the switch, you can verify the identity of objects before deciding to delete them. See the change I made to the default case in your switch statement, below. This way, the node will not be removed if it is a balloon. The physics collisions will continue to work.
func didBegin(_ contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case balloonCategory | nailDropCategory:
print("nailDrop and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
self.run(SKAction.playSoundFileNamed("lostlifesound.mp3", waitForCompletion:false))
lifeLost -= 1
case balloonCategory | pointCategory:
print("point and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
totalPoints += 2
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
case balloonCategory | lifeCategory:
print("life and balloon have contacted.")
contact.bodyB.node!.removeFromParent()
lifeLost += 1
self.run(SKAction.playSoundFileNamed("pointsound.mp3", waitForCompletion:false))
default:
if contact.bodyB.node!.name == "balloon" {
print("Balloon collided but we will not remove it.")
return
} else {
contact.bodyB.node!.removeFromParent()
print("Removed \(String(describing: contact.bodyB.node!.name))")
}
}
You can't guarantee that nodeB is the floor and is nodeA really nailDropCategory | pointCategory | lifeCategory
?
I'm assuming that naildDrop
, point
and life
are 3 objects that you want to be notified for when any one touches the floor
, so try structuring your didBegin(contact:)
like this:
func didBegin(_ contact: SKPhysicsContact) {
print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case nailDropCategory | FloorCategory:
print("nailDrop and floor have contacted.")
case pointCategory | FloorCategory:
print("point and floor have contacted.")
case lifeCategory | FloorCategory:
print("life and floor have contacted.")
default:
print("Undetected collision occurred")
}
}
Have you actually created an object from your Floor
class?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With