Building a Tetris-like Web Game
Currently me and my team are working on a jelly like soft body tetris-like game. There's actually even more than just softbody sim in this game, but for now it's a secret. MEanwhile I've decided to build couple of prototypes to understand how tetris and tetris like game work, and as I'm doing it in a way that it should be avaialble for my distributed team all the prototypes are done using web technologies.
Introduction
In this post, we’ll walk through building a basic version of the classic game Tetris using JavaScript and HTML5 Canvas. We’ll cover the key steps, starting with setting up the project and ending with implementing the basic game loop, movement of pieces, and score tracking. The original Tetris was created by Alexey Pajitnov in 1984, and it has since become one of the most iconic games in the world. Our goal here is to recreate its core mechanics and take some creative liberties along the way.
Step 1: Project Setup — HTML, CSS, and Basic Structure
First, we need to set up the project with three core files:
- HTML for the structure.
- CSS for the styling.
- JavaScript for the game logic.
HTML
We’ll start by creating a simple HTML page with a canvas for the game and a sidebar to display score, level, and the next piece:
<meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tetris</title> <link rel="stylesheet" href="style.css"> <div class="tetris-container"> <canvas id="gameCanvas" width="300" height="600"></canvas> <div class="sidebar"> <h2>Next Piece:</h2> <canvas id="nextPieceCanvas" width="120" height="120"></canvas> <div> <h2>Score: <span id="score">0</span></h2> <h2>Level: <span id="level">1</span></h2> <button id="pauseButton">Pause</button> <button id="resetButton">Reset</button> </div> </div> </div> <script src="script.js"></script>
CSS
For the basic styling, we can use the following CSS:
body { font-family: Arial, sans-serif; background-color: #000; color: #fff; text-align: center; } .tetris-container { display: flex; justify-content: center; align-items: center; margin-top: 50px; } canvas { border: 1px solid #fff; } .sidebar { margin-left: 20px; text-align: left; } button { margin-top: 10px; padding: 10px; background-color: #333; color: white; border: none; cursor: pointer; }
Now we have a basic page structure with two canvases — one for the game and the other to show the next piece.
Step 2: Basic Game Loop and Drawing Pieces
The core idea of Tetris is that pieces (Tetrominos) fall from the top of the screen and the player can control them. We need a game loop that updates the game at regular intervals.
In the JavaScript
file, we start by adding the basic code to draw pieces on the canvas:
const canvas = document.getElementById("gameCanvas"); const context = canvas.getContext("2d"); const COLS = 10; const ROWS = 20; const BLOCK_SIZE = 30; function drawBlock(x, y, color) { context.fillStyle = color; context.fillRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); context.strokeRect(x * BLOCK_SIZE, y * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); } // Example of drawing a block: drawBlock(1, 1, '#00f0f0');
This allows us to draw individual blocks on the canvas, each representing a part of a Tetromino.
Step 3: Adding Movement and Rotation Logic
Now that we can draw pieces, it’s time to add movement logic. Pieces should move left, right, and down, and players should be able to rotate them.
We can handle player input through the keyboard by listening for arrow key presses:
document.addEventListener("keydown", handleKeyPress); function handleKeyPress(event) { switch (event.key) { case 'ArrowLeft': // Move piece left break; case 'ArrowRight': // Move piece right break; case 'ArrowDown': // Move piece down faster break; case 'ArrowUp': // Rotate piece break; } }
This gives the player control over the movement and rotation of pieces as they fall.
Step 4: Collision Detection and Locking Pieces
Next, we need to handle what happens when a piece hits the bottom of the board or another piece. When this happens, the piece should "lock" in place, and a new piece should spawn at the top.
function moveDown() { currentPiece.y++; if (!pieceFits(currentPiece)) { currentPiece.y--; // Move piece back lockPiece(); // Lock the piece in place currentPiece = nextPiece; nextPiece = randomPiece(); } }
This ensures that the pieces are properly placed and that the game continues with a new piece once the current one locks.
Step 5: Scoring and Level System
To add some fun, we’ll implement a score system. Players earn points when they clear lines, and as they score more points, the level increases, speeding up the game.
let score = 0; let level = 1; function clearLines() { let linesCleared = 0; for (let y = 0; y < ROWS; y++) { if (board[y].every(cell => cell)) { board.splice(y, 1); board.unshift(new Array(COLS).fill(0)); linesCleared++; } } if (linesCleared > 0) { score += linesCleared * 100; if (score >= level * 1000) { level++; dropSpeed = Math.max(100, dropSpeed - 100); // Increase speed } } }
Much like in Tetris 99, the increase in speed as levels go up adds to the challenge, and players need to react quickly.
Step 6: Pause and Reset
Finally, let’s add the ability to pause and reset the game using buttons. This is useful for when players need a break or want to start over.
let isPaused = false; pauseButton.addEventListener("click", () => { isPaused = !isPaused; pauseButton.textContent = isPaused ? "Resume" : "Pause"; }); resetButton.addEventListener("click", () => { board = []; createBoard(); score = 0; level = 1; gameOver = false; currentPiece = randomPiece(); nextPiece = randomPiece(); gameLoop(); });
End of Tetrision
The falling blocks, each with distinct colors, can be likened to vibrant anime hairstyles — from cyan-blue hair (like Ayanami) to fiery red (a nod to Aska). You might even say the falling pieces resemble characters embarking on an endless adventure, much like a scene from an Isekai anime where every choice matters.
In future posts, we’ll dive deeper into adding more advanced functionality, including soft-body physics, to bring even more life to the game.
Tetramino tool
Tool to check if pixelart canvas can be filled with tetramino blocks
Status | In development |
Category | Tool |
Author | Stonehill Games |
Genre | Puzzle |
Tags | Pixel Art, tool |
More posts
- Creating Obj from Web and Bugfixing44 days ago
- Building a Tetramino Fitting Tool44 days ago