Tetris, in TypeScript
With the intention of getting more familiarized with TypeScript, I decided to start a new project. It’s been many years since the last time I made a game from scrath so it seemed fitting to give that a go. I chose Tetris because it’s a well known game, with a defined set of problems and functionality. All I had to worry about was to code their solutions.
The TypeScript Lesson⌗
I did get more familiar with TypeScript, some of its strengths, caveats and tooling. Still, it would be hard (or overengineered) to cover all of the language features in a project. One important feature I left out is generics, perhaps I need to start working on Space Invaders now so I can give it a try?
Implementation Details⌗
I tried to keep it as lean as possible, therefore this is the tech I used:
- TypeScript 🪛
- HTML Canvas and CSS for drawing and coloring 🎨
- Webpack for bundling everything 📦
Favorite part⌗
The most fun part of the project was to write the function to create the possible rotations for each piece. I could have used a hard-coded two dimensional array with all of them in there but where’s the fun in that?i Another downside of that approach is that I would have to limit the shapes of Tetris pieces I could use. Thanks to this function, I can create my custom shaped Tetris pieces! Anyway, here’s the function:
generateRotations(): Cell[][][] {
let rots: Cell[][][] = []
let nextBase: Cell[][]
for (let rotationCounter = 0; rotationCounter < 4; rotationCounter++) {
rots[rotationCounter] = new BlankPiece(this.rows, this.columns).shape
let destY = this.columns - 1
for (let i = 0; i < this.columns; i++) {
let destX = 0
for (let j = 0; j < this.rows; j++) {
if (!nextBase) {
rots[rotationCounter][destY][destX] = this.shape[j][i]
} else {
rots[rotationCounter][destY][destX] = nextBase[j][i]
}
destX++
}
destY--
}
nextBase = rots[rotationCounter]
}
return rots
}
I enjoyed working on this function because I had to keep track of how the Tetris piece was moving on every iteration at the cell level. It also forced me to initialize the rots
array with a BlankPiece
. This is an object that extends Piece
. Initializations of the same type aren’t required in JavaScript but they are in TypeScript. It was a nice reminder that I had to think about the type system once again.
Demo⌗
Game available here (limited mobile support because that was out of the scope 😆)