Now Reading
AR Madness — our open source ARKit game tutorial! Part Three — Collision Detection

AR Madness — our open source ARKit game tutorial! Part Three — Collision Detection

This is part three of an epic tutorial, comparable only in scale and scope to other epics like the Iliad and the Odyssey, showing how to build an ARKit game!

TL:DR

If you want to skip the tutorial and just get the code to run on your phone — get it here on Github.

In part three, we’re going to learn about collision detection i.e. how to handle objects hitting other objects in our game.

Collision Detection

Collision in ARKit is handled using bitmasks. Each type of object has its own bitmask and if they collide, the bitmasks can be compared.

First, we need to define some bitmasks, then we’ll assign them to our four types of objects — banana, axe, shark and bathtub.

At the end of the ViewController.swift, file, after the final closing bracket, add this:

struct CollisionCategory: OptionSet {
let rawValue: Int
static let missileCategory = CollisionCategory(rawValue: 1 << 0)
static let targetCategory = CollisionCategory(rawValue: 1 << 1)
}

Here we define three two bitmasks:

  • missileCategory for bananas and axes
  • targetCategory for bathtubs and sharks

To assign them to the right objects, we’re going to edit some function we wrote earlier.

In the createMissile function, before the “return node” statement, add these lines highlighted in bold:

node.physicsBody?.categoryBitMask = CollisionCategory.missileCategory.rawValue
node.physicsBody?.collisionBitMask = CollisionCategory.targetCategory.rawValue
return node
}

and in the addTargetNodes function, add these lines highlighted in bold:

node.physicsBody?.categoryBitMask = CollisionCategory.targetCategory.rawValue
node.physicsBody?.contactTestBitMask = CollisionCategory.missileCategory.rawValue
//add to scene
sceneView.scene.rootNode.addChildNode(node)
}

To detect physics collisions we need to implement the SCNPhysicsContactDelegate, so in the class signature add in the text highlighted in bold:

class ViewController: UIViewController, ARSCNViewDelegate, SCNPhysicsContactDelegate {

Now in our viewDidLoad function, add this code highlighted in bold:

//set the physics delegate
sceneView.scene.physicsWorld.contactDelegate = self

addTargetNodes()
}

and then we add another important function:

This function is part of the SCNPhysicsContactDelegate and it is called when collisions are detected in the scene between objects. Going through it line by line:

print("** Collision!! " + contact.nodeA.name! + " hit " + contact.nodeB.name!)

simply prints to the log in Xcode the “name” of the two objects involved in the competition. If you remember back to the createMissile function where we included

node.name = “banana”

and the same for the other three types of objects.

The function gives us a parameter contact, of type SCNPhysicsContact. This has two handy properties — nodeA and nodeB; the two nodes in contact / collision! So we can then use them in the if statement:

if contact.nodeA.physicsBody?.categoryBitMask == CollisionCategory.targetCategory.rawValue            
|| contact.nodeB.physicsBody?.categoryBitMask == CollisionCategory.targetCategory.rawValue {

to check that we’ve hit a “target”. If so we then check whether it’s a shark or a bathtub, using the SCNNode ‘name’ property again:

if (contact.nodeA.name! == "shark" || contact.nodeB.name! == "shark") {                
score+=5
}else{
score+=1
}

and then increment the score variable (which we haven’t created yet but will shortly!).

Then we remove the two nodes involved in the collision:

DispatchQueue.main.async {
contact.nodeA.removeFromParentNode()
contact.nodeB.removeFromParentNode()
self.scoreLabel.text = String(self.score)
}

and update the score label on the screen so the player can see their score go up.

That score label doesn’t exist yet of course, so lets add it now! While we are at it, we’ll also add a label for the timer (that will eventually count down from 60 seconds) and two more labels that will tell the user what the Score and Timer labels are! Basically, like this:

Note that we’ve created two new UILabel outlets — timerLabel and scoreLabel and also created that score variable we mentioned:

var score = 0

Ok, run the app! and fire some bananas and axes at the bathtubs and sharks! You should see the score being changed and objects disappear when they hit each other.

If so, YES!!! You have the basics of an Augmented Reality game!!


So ends Part Three of the The Tutorial That Just Won’t Quit

Author Bio —  Andy O’Sullivan

Innovation in Liberty IT | Creator of http://appsandbiscuits.com | Gaeilge | all content my own opinion

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.