Snake Game with JavaScript. Part 3

This is part of the course “Snake Game with JavaScript”.

Image for post
Image for post
GitHub Repository and Deployed Game

In this series, we are building a Snake Game with JavaScript without any libraries. We are utilizing functional and immutable programming, learn canvas rendering, applications of vectors, and basics of game development. You can find the source code in this GitHub repository, and check out the game here.

In this part, we will implement the part that deals with the game state. It includes detecting collisions, calculating the new position of the snake, and finding a free place to place food. Let’s jump in!

Constants

First, let’s fill the region with constants that we will need throughout the code.

main.js

The first two variables we will use to see if the pressed key was space or a, w, d, s or left, top, right, down.

We can see that objects with movement keys, direction, and movement have the same keys. It will help us to escape typing errors.

A default config is an object. We will use it in the function that will generate the initial state for the game.

We are measuring time in the game in milliseconds and will update the state of the game and re-render everything 60 times per second, so that movement will look super-smooth.

Core

We start the core region with a function that will find a free from the snake spot on the field to place food.

main.js

The function receives the width and height of the game with the snake. Worth to mention that the game coordinates don’t have any business with coordinates on the screen. In the core region, we don’t care if the game renders on canvas, SVG, or some virtual reality space. We measure distance in-game field cells. On the example below, we can see the game the width equal to 17 and height equal to 15.

Image for post
Image for post
game field

First, we ignore the snake and generate all possible positions for food in the center of each cell. Then we filter all the points so that they are not inside some segment of the snake and randomly pick one of them.

Image for post
Image for post
free positions

When we can place food on the game field, we are ready to write the function that will create an initial state for the game.

main.js

In this function, we merge in a received state default state, create a snake, take food, and return an initial state.

Image for post
Image for post
creating the snake

Next, the function that will return a new direction given old direction in the form of vector and movement in the form of string.

main.js

It checks that movement is defined and direction is not opposed to the old one.

We have different logic for updating the position of the snake head and the rest of the body. To update the tail, we go over each snake segment and make it shorter or remove it at all.

main.js

Process of new state generation consists of three parts:

  1. Receive state after processing movement.
  2. Receive state after processing possible collisions with food.
  3. Check if the game is over.

The function for movement processing receives old state, movement in the form of a string, and calculated distance.

main.js

Here we need to catch the right moment for changing snake direction according to player movement. We are doing this by calculating a new position if so there was no movement change and then checking if the snake head crossed the center of the cell.

On the second stage, we make the snake tail on one unit longer and generate a new position for the food if segment with snake head intersect food.

main.js

Here we are leveraging our geometry functionality to detect intersection and calculate a new position for the tail.

Game is over when the snake goes outside the game field or when there is a self-intersection.

main.js

To see if snake crosses boundaries, we take coordinates of the head and see if they are in the range between zero and width, height appropriately. Self-intersection can happen only when the number of points is more or equal to five. To see if the head intersects some segment we project head to the segment line, and if the projected point is inside of the segment and distance between it and the head is less than half of the cell it means that the game is over.

Image for post
Image for post
detecting self-intersection

It receives an old state, movement in the form of string and time from the previous update.

To calculate distance, we multiple speed on the timespan. After updating the state, we check if the game is over and if so return the initial state.

Reach the next level of focus and productivity with increaser.org.

Image for post
Image for post
Increaser

Written by

Software engineer, creator of increaser.org. More at geekrodion.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store