Handle Contact Between Physics Bodies

Your next step is to write the methods that handle what happens when the player misses and catches a drop. Rather than stuff these actions inside the didBegin(_:) method of the SKPhysicsContactDelegate extension, you’ll place them inside the Collectible class.

Open the Collectible.swift file, and at the end of the class, add two functions—one to handle the collected event and one to handle the missed event:

 // Handle Contacts
 func​ ​collected​() {
 let​ removeFromParent = ​SKAction​.​removeFromParent​()
 self​.​run​(removeFromParent)
 }
 
 func​ ​missed​() {
 let​ removeFromParent = ​SKAction​.​removeFromParent​()
 self​.​run​(removeFromParent)
 }

These two methods handle removing the nodes from the scene. Although you could have combined them into a single method and processed the outcome using an if statement and a parameter, it’s best to keep these events separate for clarity, making it easier to modify them later.

Now that the Collectible class has the methods for handling what to do when a collectible item hits either the player (collected) or the foreground (missed), you can call these methods when contact occurs.

Open the GameScene.swift file, and inside the didBegin(_:) method, add the following code inside the first if block:

 // Find out which body is attached to the collectible node
 let​ body = contact.bodyA.categoryBitMask == ​PhysicsCategory​.collectible ?
  contact.bodyA.node :
  contact.bodyB.node
 
 // Verify the object is a collectible
 if​ ​let​ sprite = body ​as?​ ​Collectible​ {
  sprite.​collected​()
 }

With this code, when contact occurs between the player and a collectible, it will verify that the sprite object is a Collectible object and run its collected() method.

Next up: handling the missed event. Scroll down to the second if statement and add this block of code:

 // Find out which body is attached to the collectible node
 let​ body = contact.bodyA.categoryBitMask == ​PhysicsCategory​.collectible ?
  contact.bodyA.node :
  contact.bodyB.node
 
 // Verify the object is a collectible
 if​ ​let​ sprite = body ​as?​ ​Collectible​ {
  sprite.​missed​()
 }

Like the code in the first if statement, this code calls the missed() method on either bodyA or bodyB depending on which node is the collectible node.

For reference, the complete function looks like this:

 func​ ​didBegin​(_ contact: ​SKPhysicsContact​) {
 // Check collision bodies
 let​ collision = contact.bodyA.categoryBitMask |
  contact.bodyB.categoryBitMask
 
 // Did the [PLAYER] collide with the [COLLECTIBLE]?
 if​ collision == ​PhysicsCategory​.player | ​PhysicsCategory​.collectible {
 print​(​"player hit collectible"​)
 
 // Find out which body is attached to the collectible node
 let​ body = contact.bodyA.categoryBitMask == ​PhysicsCategory​.collectible ?
  contact.bodyA.node :
  contact.bodyB.node
 
 // Verify the object is a collectible
 if​ ​let​ sprite = body ​as?​ ​Collectible​ {
  sprite.​collected​()
  }
  }
 
 // Or did the [COLLECTIBLE] collide with the [FLOOR]?
 if​ collision == ​PhysicsCategory​.floor | ​PhysicsCategory​.collectible {
 print​(​"collectible hit foreground"​)
 
 // Find out which body is attached to the collectible node
 let​ body = contact.bodyA.categoryBitMask == ​PhysicsCategory​.collectible ?
  contact.bodyA.node :
  contact.bodyB.node
 
 // Verify the object is a collectible
 if​ ​let​ sprite = body ​as?​ ​Collectible​ {
  sprite.​missed​()
  }
  }
 }

Build and run the project. This time, notice that when the collectible hits the player or the foreground, the node is removed from the scene. Not only does this action show the player that something’s happened, but it always frees up your scene’s resources by removing unnecessary nodes from the node tree.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset