This implementation of the beloved Tetris game is a single page application built using React and Redux.
The website is responsive and thus allows both PC and mobile users to play the game.
To offer the best support to both PC and mobile users, users have the option to either use the directional and rotate icons to interact with each block, or to use the arrow keys on their keyboard.
The App is able to keep a track of a user's high scores by taking advantage of the local storage.
And as the final cherry on the top, a rendition of the original Korobeiniki soundtrack is used to induce feelings of nostalgia.
At the time of starting this project, I had just finished Maximilian Schwarzmüller's amazing React and Redux course on Udemy and was eager to practice some of the skills I had learnt.
As with all projects, I wanted to ensure that the project is a "stretch project" so that I learn something new as well as practicing. I was certain that I was already going to learn something as I had only recently finished the course and I expected myself to forget certain bits of information, but I still wanted to ensure that I add some more complexity to the project.
And hence I decided to build a Tetris game. What made this more challenging than the projects in the course was that as well as user interactions, I would periodically have to manage the state as the blocks drop and the user progresses through the level.
Tetris was also a childhood favourite of mine and quite possibly the first game I ever played, it therefore felt fitting that the first react/redux application I build would be the Tetris game.
Containers and Components
I implemented a system where I would have containers which contain multiple components. Each container would represent a different part of the website.Collectively I had three containers: the game grid, the controls and the game information including score, level, etc.
Game Grid Container
The game grid container controlled the physical game and each
blocks element. The container itself is a
div component, the underlying CSS for which sets it
to become a grid.
The grid container is responsible for periodically rendering block components by calling a factory class which would return a random block.
As each block component shared similar methods, they all inherit from a base block. These methods include methods which decide whether or not a block should drop and how to move left or right. The main method each individual block has defined is the rotation method as this varies from block to block.
Each block manages its own state as certain information regarding the block is only needed by that individual block. The inherited class does contain methods which dispatch actions to the store such as updating the current score or letting the game know that it is game over.
The controls allow the user to interact with the blocks allowing them to move the block left or right, rotate the block or pause the game.
As I wanted to contain information about a blocks movement within its own state, I ensured that each block rendered hidden buttons to move left, right and rotate. In doing so, I was able to have the on-click actions on the UI controls to click the hidden buttons rather than having to move block specific states to the redux store.
Game Information Container
This container updates user score, level and high scores based on information it receives from the store. The container is more of stateless component, however I have saved it as a container as I felt that it is easier to understand that there is always one container for each part of the website as supposed to dig through the components directory.