I'll be honest: I didn't think much of the portable Tetris game when my kids's friend brought it to our house. I happened to walk by him as my children formed a tiny crowd, listening to the tinny music and watching their friend try to clear the board, row by multicolored row.

But that song! That song got stuck in my head for days. I found myself humming it while walking the neighborhood and doing the dishes. It's just so, dang, catchy!

Over the next few weeks, while I was humming away, it struck me that Tetris is a relatively simple game. Four-part blocks slowly fall, the player rotates and moves them, and tries to make complete rows which then disappear. My wife loves Tetris, and I've played quite a bit over the years. It's a fun, timeless game.

You can probably guess where this is going.

A game of Tetris in progress, showing a partially-filled game grid and a single falling tetromino.
Noon: oh cool, I can sneak in a quick game. Midnight: just one more level!

I spent the next three weeks working on a Blazor WebAssembly version of Tetris for my BlazorGames.net project, and I'm happy to say that I think it's pretty neat! It's not quite perfect, but it's playable and pretty darn fun, and that's good enough for me.

So come along as I show how we can make the first true video game we've ever made in Blazor WebAssembly! Let's build Tetris in Blazor!

The Breakdown

Unlike the other Blazor Games series, for our Tetris series we will do very little modeling up front. Each of the subsequent parts in this series will handle their portions of the model.

One part we do need to do, though, is make sure everyone understands what Tetris is, and thereby what our scope is.

For those who might not be familiar with it, Tetris is a video game in which you move little four-part blocks (called tetrominos) around a grid comprised of cells. At any given time, a single tetromino is "falling" or moving slowly, row-by-row, down the grid.

I am the man who arranges the blocks / that descend upon me from up above

Once the falling tetromino can no longer move, it becomes "solidified" or stuck, and another piece starts to drop from the top of the grid.

They come down and I spin them around / till they fit in the ground like hand in glove

The tetrominos have different shapes, but they are always made up of four pieces.

The player can move the falling tetromino left and right across the grid, as well as rotate them, until the tetromino becomes stuck. That happens when it runs into either the bottom of the grid or another, already-stuck tetromino; in other words, when the tetromino cannot go any lower.

Sometimes it seems that to move blocks is fine / and the lines will be formed as they fall

The player's goal is to fill in an entire row of the grid with the tetrominos. Once you do so, that row disappears and you score points.

The more points you have, the higher your level becomes, and the faster the tetrominos will drop. As they get faster, it gets harder to move them into the right place, but you also score more points for each cleared row.

Then I see that I have misjudged it / I should not have nudged it after all

The game ends once any part of a tetromino sticks up past the top of the board.

Can I have a long one please? / Why must these infernal blocks tease?

Sounds simple, right? It's actually the most complex game I've modeled in Blazor yet. This is because our Tetris in Blazor project has something that none of the other projects had: a game loop.

Game Loop

In video game terminology, a game loop is a set of tasks that must done while the game is running. This usually includes taking user input, updating the game state, and re-drawing the game in that order. The loop runs very quickly, many times per second.

In our implementation, the game loop will need to:

  • Take user input from a keyboard
  • Modify the game per the input (e.g. rotating a tetromino, toggling the music, etc.)
  • Re-draw the game using Blazor's StateHasChanged() method.

We must keep the game loop in mind until we explicitly implement it later in this series.

Goals

The overall goal of this series is to produce a working, playable version of Tetris coded in Blazor WebAssembly using C# and ASP.NET. Due to limitations in Blazor, we will also need a bit of JavaScript.

Our game must:

  1. Be playable by a single player.
  2. Allow for falling tetrominos to be rotated and moved left and right.
  3. Allow for tetrominos to be "hard dropped", or dropped until they "hit" something, whether that's the bottom of the grid or another tetromino.
  4. Display the next three tetrominos that will be dropped on the game grid.
  5. Clear rows that are completely filled.
  6. Toggle the famous theme music on and off.
  7. Keep a score for the current game.
  8. Implement levels, so that the game gets more difficult the higher the level.
  9. Save the player's top score in a cookie.

If we can implement all of these goals, we will have a working game of Tetris in Blazor WebAssembly!

Series Outline

This series attempts to break down a large project into six distinct parts, each of which represents a portion of the overall project.

In Part 2, we will create the first set of C# classes we need, including the game grid, the cells, and a representation of "occupied" cells for both the grid and the tetrominos.

In Part 3, we will create the tetrominos themselves, discuss the differences between them, and implement C# methods that will allow them to be rotated, moved, and dropped.

In Part 4, we will begin building the Blazor components for the grid and tetrominos display. At the end of this part, we'll have a partial game, one that can display the grid and a falling tetromino.

In Part 5, we'll finish the first-pass implementation of the game by implementing the controls, showing the upcoming tetrominos, and clearing finished rows.

In Part 6, the last part, we'll complete the entire Tetris in Blazor game by coding up scoring, levels, the music, and a few ease-of-use features.

The Sample Project

As always, there's a sample project on GitHub that has all the code we will use in this series. If you just can't wait to check out the code, click here:

exceptionnotfound/BlazorGames
Contribute to exceptionnotfound/BlazorGames development by creating an account on GitHub.

Play Now!

The completed Tetris game is playable right now on my sister project site, BlazorGames.net.

BlazorGames.net
Come play Tetris, Blackjack, Minesweeper and more to learn about Blazor in ASP.NET Core.

The Rest of the Series

Now that the series is fully published, check out each of the remaining parts:

Tetris in Blazor Part 2: Cells, the Grid, and the Game State
Let’s start the process of making Tetris in Blazor by building the C# classes for the grid, the cells, and the game state.
Tetris in Blazor Part 3: Tetrominos
Four parts each, in different layouts. Let’s build them all!
Tetris in Blazor Part 4: Displaying the Grid and a Falling Tetromino
Let’s write up Blazor components to show the game grid, and write a game loop to make the tetrominos fall!
Tetris in Blazor Part 5: Controls, Upcoming Tetrominos, and Clearing Rows
Let’s implement more major features, like keyboard controls, grid focus, clearing rows, and more!
Tetris in Blazor Part 6: Scoring, Levels, Music, and Other Features
All that’s left to do is implement scoring, levels, music, the grace period, a new game button, and a previous high score cookie.

Stick Around

Want to make sure you get the rest of the series right in your inbox? Sign up for my mailing list, completely free!

This series was a load of fun to code and write, and I hope you'll stick with me as we get it going. We're going to make our first true video game in Blazor WebAssembly, ASP.NET and C#! It'll be super cool once we're done, trust me.

Next Monday, we'll dive into Part 2 of this series, and start writing up C# classes for the game grid, the cells, and the game state.

One last word of warning: be careful around that song. It'll never leave your head.

Don't say I didn't warn you.

Happy Coding!