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.
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!
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.
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.
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.
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.
The game ends once any part of a tetromino sticks up past the top of the board.
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.
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
We must keep the game loop in mind until we explicitly implement it later in this series.
Our game must:
- Be playable by a single player.
- Allow for falling tetrominos to be rotated and moved left and right.
- Allow for tetrominos to be "hard dropped", or dropped until they "hit" something, whether that's the bottom of the grid or another tetromino.
- Display the next three tetrominos that will be dropped on the game grid.
- Clear rows that are completely filled.
- Toggle the famous theme music on and off.
- Keep a score for the current game.
- Implement levels, so that the game gets more difficult the higher the level.
- 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!
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:
The completed Tetris game is playable right now on my sister project site, BlazorGames.net.
The Rest of the Series
Now that the series is fully published, check out each of the remaining parts:
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.