Implementing snake 🐍 in React

Recreating a classic mobile game in modern technologies

Play at: https://reactrangers.github.io/snake/

React is a solution for building graphical user interfaces that makes it easy to render any kind of a dynamic view. To illustrate this idea better, we’ll guide you step by step through the process of creating our own version of the game that many have once enjoyed.

Groundwork

We are going to write code in JavaScript and you will need the latest stable version of the Node.js, a popular runtime for JavaScript programs. The game itself will run in a browser (another JavaScript runtime), yet its development tools require Node.js.

To get off to a good start, we’ll use create-react-app, a command line tool which offers a convenient environment to work on a new React project.

npx create-react-app snake
cd snake
npm start

This will start a local development server available at http://localhost:3000/ on your computer that will automatically refresh whenever we make changes to the app.

Board

Websites are built with different HTML elements such us p, div, a, table. Probably the ones best suited for the job are those used for displaying images in Scalable Vector Grapics format.

Cherries made by Smashicons from www.flaticon.com
Files under src/SnakeGame/

The goal of the game is to grow the snake (i.e. number of its segments) by directing its head so that it eats as many fruits as possible while not biting its own tail. We’ll use the following collidesWith method to detect collisions:

Files under src/SnakeGame/

Properties x, y are the coordinates of the centre of an object in the game (such as a snake’s segment or a fruit) and r is the radius of the circle that best approximates its shape.

State

We’re now going to leverage mutable state to make the game respond to user’s action. Here’s what we’ll need to keep track of and update throughout the game:

  • fruits — an array of SnakeObject objects representing fruits
  • segments — an array of SnakeObject objects representing snake segments ordered by their distance from the head which is the first element
  • direction — a direction in which the snake’s head is currently moving (angle between its direction and “up”),
  • trail — a list of vectors representing snake’s trail starting from its head
  • running — a boolean flag denoting whether the game is currently running
  • time — a amount of time that has passed since the start of the game
  • growth — a number of segments that the snake will grow in the following turns (one by one)

Ruleset

Success of the player depends on the choices she or he makes. Every turn (i.e. once another unit of time passes) the state of the game will transform according to the following ruleset:

  • snakeMoves snake’s head moves by its length in the direction set by the player
  • fruitsDrop a new fruit may appear in a place that doesn’t collide with any other fruit or the snake
  • snakeEats any fruit colliding with snake’s head gets eaten and disappears increasing snake’s growth potential
  • snakeGrows snake grows by one if it has eaten another fruit
  • fruitsAge fruits age and those not eaten for too long will disappear
  • noCrossing the game will stop if snake’s head crosses its body

All these rules will be implemented as functions taking state and props as arguments and returning the transformed state.

Files under src/SnakeGame/rules/

Putting it all together

Every animation frame, we’ll update the state according to the ruleset above.

src/SnakeGame/index.js

You can find the complete code for working game on our GitHub. Feel free to fork the repository and add your own rules! Let us know how you liked this article in the comments below.

Shoutout to some very bright attendees of a WarsawJS workshop on Oct 7th, 2018 who spent whole day practising React while implementing this game while being mentored by Konrad Kowalski and me! You can find their work on GitHub as well.