Tetris on Gumstix

Abstract

We recreated Tetris from scratch using the Gumstix board, a LCD screen, and hardware buttons. We implemented basic gameplay movements while allowing customization of the block’s color scheme. The software heavily relies on QT and kernel modules to recreate the grid and block movements found in the original Tetris game. With features, such as hard drop, soft drop, and a next block indicator, Tetrix is a fully functional recreation of the classic game.

1. Introduction

Ever since the creation of the game, Tetris has been a staple in many arcades and gaming consoles. Modern versions of the classic game still offer significant entertainment value to this day. From Tetris in VR to Tetris with Friends, the game continues to evolve. We chose this timeless game so that we could create our own spin on it. We wanted a project that is not only fun to implement, but also brings joy to our fellow classmates. This project serves as a perfect application of the material we have learned in class.

The player controls the Tetris game through the use of hardware buttons that are read in by our game engine through a device driver file. Based on the button pressed, the game would update accordingly by translating horizontally or vertically, rotating, or performing a soft or hard drop. These changes are all reflected on our LCD screen.

Additionally, we allow the user to choose between three different color schemes. Our first color scheme is that of the original Tetris, with seven different colors representing the seven different blocks. The second scheme is in grayscale. The last one presents an extremely difficult level with all blocks being transparent. This scheme is feasible as we have a next block widget on our LCD screen that lets the user know which block and orientation will be dropped next. The location to drop the next block is also always constant.

Our final product offers a fully functioning game in the classic tetris scheme that increases in difficulty level as the game progresses.

2. Design Flow

This shows the basic design of our game of tetris

Our design for the project can be broken up into three main categories: User Input (buttons), Backend Game Machine, and the GUI.

Both the buttons and our timing module are in a kernel module. The buttons serve as the only user input to the game and communicates with the backend game machine through the device driver file. Every time a button is pressed, the user level program is signaled and the button pressed is written to the dev file. For the timing module, we use timers to create our tick system for determining when the active block should be translated vertically down. Additionally, writing to the dev file changes the speed of the tick system. In the game, the speed increases as the score progresses.

The backend game machine handles all the boundary checks and game logic. It reads and write to the kernel module’s dev file and changes state according to the button pressed. The machine also generates blocks and keeps track of the orientation and position as it drops down. Additionally, it implements features, such as removing lines that are full, calculating the score, and setting the next block widget. The entire gameplay is displayed on the lcd screen which displays the running game and score.

Lastly, the GUI relies heavily on QFrame objects and QGridLayout objects to generate blocks and the grid that the blocks occupy. By coloring each QFrame object, we were able to simulate the movement of blocks across the screen.

3. Project Details

Black and white version of Tetrix

Buttons

Buttons Layout

Classic version of Tetrix

Game Logic (See /game/game.cpp for the source code)

This file houses the main game logic omitting the scoring mechanism. It holds information retaining to the game state in a 2D array. This file also keeps a state of the current game and block in play. By keeping track of the rows, it removes rows that are full once the a block has been installed permanently on the grid. By reading the dev file after the program has been signaled by the kernel module, it modifies the grid state by calling on the respective translate and rotate functions.

The grid system is a 2D matrix that stores QFrames that are colored. This file doesn’t deal with this directly, but rather calls on Grid functions to update the QT grid. An array with the translation from the block type and the block color are used to edit the grid.

Furthermore, we have another 2D matrix that stores the occupied slots of the grid. This is used to check boundaries, which determine whether a block can legally rotate or translate in a certain direction without exceeding the grid border or invading another block. An array with the translation from the block type and the block color is applied to display in the GUI.

Scoring (See /game/score.cpp for the source code)

The scoring GUI utilizes a Qt label that dynamically changes based on number of rows removed. If a function to change the score is called, then the score label reflects that change. We created a painter object that allows us to rotate the score block to align below the Qt Grid. The score then can be updated with a setScore() function. Rotating the painter object was very challenging to figure out as it is not immediately supported.

Block Object (See /game/block.cpp for the source code)

This file generates a random block out with the use of a pseudorandom generator. We seed the generator with the time in the main function. We never destroy the game object, hence resetting the game doesn’t reset the seed.

This file generates not only a random block, but it also generates an orientation that the block starts at. We hardcoded the different orientation for each type of block. This ensures that when we do the translation or rotate functions, the state is always accurately reflected. It also offers a performance gain since the state is already computed.

Device Driver for Hardware Buttons and Timing Module (See /kernel/tetrix.c and /kernel/Makefile for the source code)

The kernel driver handled the interactions for all the buttons as well as the timing module. The timing module determines the time it takes for a block to translate down. For the buttons, we set up irq and irq handlers for all the buttons. When a button is pressed it sends a SIGIO back to the user level program and also modifies a variable based on the button pressed. This variable is read in by the user level program which can distinguish between button presses and can assign specific functions for each button.

It also handles the timing module in which it installed a kernel timer to run constantly at the moment the modules was inserted. This also writes to the dev file but is handled differently so that it won’t interfere with button inputs. The timing module also has a speed up function which takes the current speed and changes it to 66% of the previous value when called. This is used by the user level program to speed up the game as it progresses. It also is used to implement the soft drop feature in tetris. One of hardware buttons is not attached to an interrupt handler and is polled every tick to check the state. When pressed temporarily, it speeds up the game by a factor of 4 until the button is released.

There was a problem where pressing the buttons fast enough or at the right time, the user level program would not be able to translate down since pressing the button would overwrite the value which indicates that a block has to translate down. This was solved by resetting the section of code earlier in the user level program which checked for signals from the kernel. We also separated the button and the timing module variables so that when read from the dev file they would be distinct.

GUI (See /game/main.cpp and /game/grid.cpp for the source code)

The GUI utilizes the Qt library. We use the Qt grid class for displaying the grids. The first block appears in a designated four by four grid in the center of the game. Based on the tick system from kernel module and game state, the grid is updated accordingly in timed intervals.

Creation of the GUI was by far one of the most challenging parts of this project. Because our game of tetris wants to utilize the largest area of the screen as possible, it made sense to rotate the entire screen vertically. This caused major headaches because the Qt support for the rotation of different objects such as buttons and labels isn’t standardized. The hardware also was a major obstacle because our first screen had color inaccuracies.

Summary

For our final implementation, we implemented a version that randomly generated the type of blocks and its corresponding starting orientation on the screen. The block would then gradually translate downwards. The user would have the option to maneuver the blocks by translating it to the left or right, rotating the block clockwise or counterclockwise, dropping the block immediately (hard drop), or accelerating the block downwards (soft drop). A button was designated to resetting the game and another button was reserved for toggling between different game mode customizations. For customizations, we added a black and white mode that showcased the blocks as black and background as white. For the more advanced players, we offered a difficult transparent mode where the blocks are white, the same color as the background. The entire game will need to be based on the player creating a full mental image of the game and will be true challenge testing the player’s memory!

One of the challenges we faced was implementing a touch screen that could display text vertically while being formatted to the placement of our liking. We were able to successfully create a responsive button and display it on the screen but we were unable to translate the button accordingly and rotate the text on the button to our liking. We eventually decided to map the functions of the touch screen buttons to our remaining physical buttons otherwise we would have wanted to implement the touch screen and customization as a menu option.

Contributors:

Devin Chen
June Hua
Phillip Teng

Source Code:

https://github.com/phillipteng/Tetrix_EC535

Author: Phillip Teng
Link: http://phillipteng.github.io/2019/05/01/Tetris-on-Gumstix/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • Donate if you like