Tetris game in JavaScript – Open source

In this post I will show you the Tetris game programmed in pure JavaScript, totally free and open source.

This block game is programmed with JavaScript and uses canvas to paint the game. I also use Bootstrap for the layout of the buttons and the page in general, with a bit of SweetAlert for the alerts.

Although it seems simple to do, it is one of the jobs that has cost me the most and of which I am most proud. It was complex (for me) to understand all the logic for collisions, rotations, row deletion, part movement, limits, etc.

Among the features of the game we find:

  • Sounds: background music, sound when the piece cannot be rotated, when a complete row is made and when the tetromino touches the ground
  • Colors: each piece has a random color chosen at runtime
  • Rotations: pieces can be rotated to accommodate them and accumulate points
  • Mobile compatible: because it is web, I have added some buttons to be able to play it on mobile phones and tablets, but it can also be played with the keyboard
  • Open source: you can modify the game, the board, the length, speed, pieces, rotations, etc.
  • Tetris port: behaves like any normal tetris game
  • Game pause: the game can be paused or resumed at any time

Let’s see then the details of this game programmed in JS. Throughout the post I will show you how this game is programmed, I will also leave you a demo and the complete code which is FOSS.

Note: figure, piece and tetromino will be used synonymously in this post.

General algorithm of the Tetris game

The algorithm is simple. We have a Cartesian plane where the coordinates X and Y exist. We have 3 things:

  1. Game board: the board where everything will be drawn or displayed
  2. Existing pieces: the points or pieces that have already fallen before; that is, the figures that stayed there
  3. Current piece: the piece that is currently going down and that the player can move or rotate

Now we do the following: we draw the game board (empty), then we overlap the existing pieces and finally we place the current piece (the one that is going down).

In each movement or attempted rotation, we check if the piece does not collapse with the wall or with another figure below. When the part is rotated, we do a simulation to see if the points, after being rotated, will not collapse with another part.

Furthermore, when it is detected that the piece has hit the ground, a timer is started that will put the next piece in certain milliseconds (this way the player has time to move the piece).

Before displaying another shape, the points of the current shape are moved to the existing parts.

The rest are collisions and work with arrays. For example, to check if a row is full, we go through each point of the array at a certain position of Y and check if it is taken.

All the game drawing is done in a requestAnimationFrame and we draw an array on Canvas using JavaScript.

Game music

The game has various sounds. All sounds are injected and hidden in the DOM. They are init like this:

In this case the background sound is reproduced in a loop, so that it repeats infinitely. Then, we reproduce it like this (line 1):

Helper classes


A point has two things: X and Y coordinates. And a Tetromino has several points that make it up.


Like I said, a tetris figure is made up of several points. In addition, it has several rotations. The Z, for example, has only 2, but the J has 4. The rotations are also defined as a Tetromino, and they are exchanged when rotating.

To keep track of the rotation the figure is in, an index is kept. The rotations are nothing more than an array that has several Tetrominos, which represents all possible rotations.

As you can see, the color is chosen in line 6. At the moment of choosing the figure, each point of each rotation of the same is colored with the random color.

Useful functions

Before continuing, let’s look at the useful functions. Among them we have the function that loads the sound, the one that chooses a random color or the one that chooses a random number to know which figure to choose:

For example, the getRandomColor function chooses a random color from the static array of the Game class that we will see next. And this function reuses the function called getRandomNumberInRange which returns a number in a certain range.

Game operation

Tetris in JavaScript – Welcome to the game

Let’s start by looking at the constants of the game, such as the size of the board, the colors, the score that is given to the user when he makes a row of points or the random colors to choose from:

The color array can be modified to your liking, either by changing the colors or adding more, to add randomness.

We also have certain interesting parameters such as the size of each square in pixels (this affects the size of the board) or the milliseconds to indicate the speed at which the piece moves down, the duration of the animation or the time the player has to move the piece if it has touched the ground.

Game init function

It all starts in the init function, but the constructor where we define several things is also important:

The game receives the id of the canvas where it is going to be drawn. In this way we could make them two Tetris game boards, using the same code.

We also have various flags, the definition of the board, the sounds, and so on. Now let’s see the init and restart of this open source tetris game:

One important thing to note here is the syncExistingPiecesWithBoard function. What this function does is clean the board and place on it (that is, modify the indexes of the array) the existing pieces.

Draw on canvas

The function that draws the entire tetris game on the canvas is the following. It will be invoked every 17 milliseconds using requestAnimationFrame:

This function is the one that you can modify if you want to draw the game in another place; for example in a table, with SVG, in the console, and so on.

Get random figure

We have the function where we define the figures and their rotations. This method will return a random Tetromino on each invocation:

Right here is where we are using the Point class and the Tetromino class. Remember that each Tetromino will receive an array of all possible rotations. And each rotation is in turn an array of points that have different coordinates.

These coordinates are not modified internally at the point, but are placed from a global X and Y on the board.

If you want to define other shapes or modify the rotations, this is where you have to make the changes.

Collisions and movements

I know that there are engines for video game development but in this case I wanted to do everything by hand. Therefore I have created my own functions to know if a point is out of bounds, if a point is valid, and so on.

Let’s first look at the point collision functions that check the existing board and pieces:

We are using the global coordinates of X and also of Y, because remember that each point in the figure is independent.

Now let’s see the functions to move or rotate the figure:

What we do is simulate the movement and check if each point is still valid. We also play a sound in case the figure cannot be rotated.

Deleting full rows

Deleting full rows in this blocks game written in JavaScrtipt

This is one of the functions that took me the most work to program. What it does is check and remove the filled rows. It looks like this:

We must obtain the Y coordinate of all the rows that are already filled. For each one, we check if we can move all the points down. In case they are, we lower them, but we do not lower them beyond the number of deleted rows.

Also, this feature increases the score. The function that refreshes it is:

The score is calculated according to the number of points that were removed multiplied by the score per square removed.

Game loop

Now let’s look at the game loop. According to the interval in milliseconds defined above, we are lowering the tetromino while possible. In case the piece can no longer be moved, a timer is started to give the player an opportunity to move the piece.

When the timer runs out, if the tetromino still can’t move, we add the current part to the existing parts and then select another shape:

It is also in this loop where we check if the player loses.

Tetris game – Player loses

I must admit that this feature needs to be improved as it currently checks for pieces in the second row, but it should be smarter.

Controls for playing blocks in JavaScript

The block game or tetris in JavaScript that I have programmed can be played with the keyboard or with the buttons. It is a good time to show the HTML code of the game, where we see the canvas and the buttons:

Each button has an id, which I then retrieve within the game using querySelector:

Now let’s see the controls, both the keyboard and the buttons. Each invokes the “try to move right” functions and all other positions:

Here you can see that we use the canPlay flag, which we deactivate or activate according to our convenience. For example, it cannot be played while the game is paused or while the row removal animation is playing.

Putting it all together

Parzibyte playing tetris game written in JavaScript (open source software)

I can’t put or explain all the code here. Remember that the only thing we need is a canvas where we can draw the whole set of blocks. The rest is in the code, especially in the Game class. You are free to explore it.

It really took me a lot of time and effort to make this game; you can see all its evolution through commits.

I leave you a YouTube video for the demonstration (in spanish):

The complete and open source code is on my GitHub: https://github.com/parzibyte/tetris-javascript

You can try the demo here: https://parzibyte.github.io/tetris-javascript/

I also take the opportunity to invite you to read more about JavaScript and Videogames on my blog.

I am available for hiring if you need help! I can help you with your project or homework feel free to contact me.
If you liked the post, show your appreciation by sharing it, or making a donation

Leave a Comment

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