Styling the Game

In this lesson, you will learn about the Tetris game board and style it with an 80's feel.

Project structure

It’s good practice to split code into different files even if the project is not that big:

  • constants.js is where we put the configurations and rules of the game.
  • board.js is for board logic.
  • piece.js is for piece logic.
  • main.js has code to initialize the game and the overall game logic.
  • The order of the scripts that we add at the end is essential in index.html.
  • styles.css contains all the beautifying styles.
  • The README.md is the markdown info. file that is the first page in the repository.

Modern styling

Just like modern JavaScript, the world around styling the web has also progressed in the past years. First came Flexbox, which aims to provide a more efficient way to layout, align, and distribute space among items in a container. It is largely a one-dimensional system.

Then, came CSS Grid, a two-dimensional system that handles both columns and rows. They work well together; a grid item can be a flexbox container. Since this is a JavaScript course, we will not delve into it, but notice the use of CSS Grid and Flexbox for the layout:

Press + to interact
.grid {
display: grid;
grid-template-columns: 320px 200px;
}
.right-column {
display: flex;
flex-direction: column;
justify-content: space-between;
}
Press + to interact
<div class="grid">
<canvas id="board" class="game-board"></canvas>
<div class="right-column">
<div>
<h1>TETRIS</h1>
<p>Score: <span id="score">0</span></p>
<p>Lines: <span id="lines">0</span></p>
<p>Level: <span id="level">0</span></p>
<canvas id="next" class="next"></canvas>
</div>
<button onclick="play()" class="play-button">Play</button>
</div>
</div>

We can link to the styles file from the HTML file by adding a link in the <head> section:

<link rel="stylesheet" type="text/css" href="styles.css" />

The font

It’s nice to have a bit of an 80’s feel to our game. Press Start 2P is a bitmap font based on the font design from the 1980s Namco arcade games. We can link to it in the <head> section and add the arcade-style font to our styles:

// index.html
<link
  href="https://fonts.googleapis.com/css?family=Press+Start+2P"
  rel="stylesheet"
/>

// styles.css
* {
  font-family: 'Press Start 2P', cursive;
}

The JavaScript

At the end of the HTML file, we add a reference to our JavaScript files. <script> elements contain JavaScript code that’s executed by the browser.

The order is important here. Since we are using constants in the main file, we need to put contants first.

    <script type="text/javascript" src="constants.js"></script>
    <script type="text/javascript" src="board.js"></script>
    <script type="text/javascript" src="piece.js"></script>
    <script type="text/javascript" src="main.js"></script>
  </body>
</html>

If we do it in the wrong order, we get an error like this: Uncaught ReferenceError: KEY is not defined

Let’s start with some code to draw the board in the correct size. The playing board consists of ten columns and twenty rows, and we can add them to constants.js together with the size of the blocks:

const COLS = 10;
const ROWS = 20;
const BLOCK_SIZE = 30;

The document object provides a programmable interface for the HTML document. The document has a tree-like structure and is often referred to as the DOM (Document Object Model).

We can call the getElementById method to access elements from the DOM. Here, we use it to get a reference to the <canvas> element and its 2D context; this allows a variety of methods for drawing lines and shapes on the canvas:

Press + to interact
const canvas = document.getElementById('board');
const ctx = canvas.getContext('2d');
// Calculate size of canvas from constants.
ctx.canvas.width = COLS * BLOCK_SIZE;
ctx.canvas.height = ROWS * BLOCK_SIZE;
// Scale blocks
ctx.scale(BLOCK_SIZE, BLOCK_SIZE);

By using the scale, we can always give the size of the blocks as one (1) instead of having to calculate with BLOCK_SIZE everywhere, which simplifies our code.

With this, we have our game container styled and ready, awaiting code. You can always see the full code in the JavaScript widget below by clicking the tabs.