iOS

January 28, 2019

Implementing collision detection with SpriteKit

When developing games for iOS it can be very handy to use SpriteKit since it makes it easy to render and manipulate nodes, apply textures, work with light, control cameras, and a lot of other cool stuff usually needed when making a game.

Furthermore, the graphic interface in Xcode makes map creation easy. Add a SpriteKitScene file and start dragging and dropping your elements where they need to be for the starting scene.

For collision detection we are going to use SKPhysicsBody. Every element that has a SKPhysicsBody will be able to collide with each other.

If all you want is just simple collision behavior then all you need to do is to select your desired node, go to the Attributes Inspector, look under Physics Definition and set Body Type to Bounding Rectangle. Or if you have a texture on that node you can select Alpha mask.

But sometimes you want more than just a simple collision. Maybe you want the character to take damage if he is hit by a bullet. To achieve this we can assign a custom class to our node in the Custom Class inspector. This class has to be a SKSpriteNode. To simplify further we will also make it conform to our own protocol Obstacle which looks like the following:


1
2
3
4
5
6
7
8
import Foundation
import SpriteKit

protocol Obstacle
{    
    func setupNode(in view: GameScene);
    func collisionBegan(with other: SKPhysicsBody);
}

Next, we will make our GameScene (the SKScene that controls the SpriteKitScene) conform to the SKPhysicsContactDelegate and add the following line under the didMove method


1
physicsWorld.contactDelegate = self

Then we will add our implementation of didBegin for collision detection


1
2
3
4
5
6
7
8
9
10
11
12
13
14
func didBegin(_ contact: SKPhysicsContact)
    {
        // Handle the collitions in each nodes class
       
        if let obsticle = contact.bodyA.node as? Obstacle
        {
            obsticle.collisionBegan(with: contact.bodyB)
        }
       
        if let obsticle = contact.bodyB.node as? Obstacle
        {
            obsticle.collisionBegan(with: contact.bodyA)
        }
    }

This will let the GameScene take care of whenever there is a collision detected and pass that information along to the node that is affected.

Now we can add a crystal node to our game that gives the player 1 point each time one is collected.


1
2
3
4
5
6
7
8
9
10
11
12
func collisionBegan(with other: SKPhysicsBody)
    {
        if other.node?.name == PLAYER_NODE
        {
            if let game = self.scene as? GameScene
            {
                game.totalPoints += 1
                sounds?.playSound(sound: .Crystal)
            }
            self.removeFromParent()
        }
    }

The above code is inserted into the Custom node class.

And there you have it! Now custom collision behavior can be added to nodes in your SpriteKit game.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *