How to make Slither.io with JavaScript: Part 4 - Collisions

7/20/17

This is the fourth part of our tutorial series on creating Slither.io with JavaScript and Phaser! Take a look at Part 1 if you are just starting with this series, or jump back to Part 3 if you need to.

Look at the example and also look at the source code for this part.

Collision Concepts

In this part, we will just be modifying snake.js. Essentially, what we want to do is add a point on the front of the snake that can collide with the sections of other snakes. It will look like this:

You can see the circular physics body "point" at the front of each snake. Set the debug property of snakes to true if you want to see these physics bodies in your game.

Since we already added physics bodies to the snake sections in Part 2, all we will need to do is create the circle body at the front of the snake. We will call this circle the snake's "edge", so we are interested in when the edge of the snake collides with section bodies. To keep the edge in front of the head, we will use a lock constraint, so that the snake can turn or move and this edge will remain at the front.

Creating the Edge

Take a look at snake.js. First, we added these lines to the Snake function:

//the edge is the front body that can collide with other snakes
//it is locked to the head of this snake
this.edgeOffset = 4;
this.edge = this.game.add.sprite(x, y - this.edgeOffset, this.spriteKey);
this.edge.name = "edge";
this.edge.alpha = 0;
this.game.physics.p2.enable(this.edge, this.debug);
this.edge.body.setCircle(this.edgeOffset);

//constrain edge to the front of the head
this.edgeLock = this.game.physics.p2.createLockConstraint(
    this.edge.body, this.head.body, [0, -this.head.width*0.5-this.edgeOffset]
);

this.edge.body.onBeginContact.add(this.edgeContact, this);

We make the sprite invisible, then we give the edge a circular physics body. We create a lock constraint that locks this body in front of the head at a specific offset. We add a callback for when this edge begins contact with another body.

Edge Contact

Let's take a look at what we do when the edge collides with something:

edgeContact: function(phaserBody) {
    //if the edge hits another snake's section, destroy this snake
    if (phaserBody && this.sections.indexOf(phaserBody.sprite) == -1) {
        this.destroy();
    }
    //if the edge hits this snake's own section, a simple solution to avoid
    //glitches is to move the edge to the center of the head, where it
    //will then move back to the front because of the lock constraint
    else if (phaserBody) {
        this.edge.body.x = this.head.body.x;
        this.edge.body.y = this.head.body.y;
    }
}

We find out whether the edge hit the section of another snake, or a section of this snake. If it hit another snake, we destroy this snake using our destroy method. If it hit this snake, we move the edge to the center of the head simply to reset it. This solution is an alternative to preventing this snake's edge from hitting its own sections using collision groups. While the solution we use is less foolproof, it is much easier to implement.

Destruction

When the snake is destroyed, we need to also destroy the edge. I added this code to the destroy method:

this.game.physics.p2.removeConstraint(this.edgeLock);
this.edge.destroy();

It is always important to destroy constraints along with the sprite bodies that they constrain.

Scaling

As a snake's head gets bigger, its edge will have to be constrained further and further it. Add this code to the setScale method:

//update edge lock location with p2 physics
this.edgeLock.localOffsetB = [
    0, this.game.physics.p2.pxmi(this.head.width*0.5+this.edgeOffset)
];

We use pure P2 physics to update the lock constraint, placing the edge at a further offset from the head based on the new scale of the head. You can read about the P2 lock constraint properties here.

And that's all it takes to implement snake collisions in our game. Most of our work was already done by just creating a thorough Snake class with physics bodies and destroy methods. In Part 5, we will work on adding eyes to our snakes.

Until next time,

Loonride

Up Next

Subscribe

  • No spam
  • Update information
  • Free newsletters

Invalid Email

Subscribed

Try Again Later