# Stécker vum Himmel

Stécker vum Himmel (Items from the Sky) is a Tetris clone. Tetris is the perfect game to begin our journey on the path to becoming a game developer, as Tetris contains all the elements found in every game (game loop, input processing, updating of the game world, …), minus all the fancy graphic stuff — and Tetris is straightforward to implement nowadays.

This is just a quick and dirty tutorial on the basics of Tetris based on this great tutorial by Javier López.

## Tetronimo

There are five basic tetronimos, two of them have mirror shapes, thus there are seven different types of pieces in a standard Tetris game: the square, the I-shape, the L-shape, the mirrored L-shape, the N-shape, the mirrored N-shape and the T-shape. The following picture shows the five basic Tetronimos (without the mirrored shapes):

To define those, simple matrices are sufficient. Here is the square shape in matrix form, for example:

where an entry of means no block, means a normal block and stands for the pivot centre or the centre of rotation of the Tetronimo. To store this information in C++, we simply use a two-dimensional array:

To be able to rotate the pieces, we could use some linear algebra and use rotation matrices, but in this case, that would clearly be overkill. It is way easier to simply store each possible rotation of each piece in different matrices — that is, each piece will have four matrices associated to it. This is also the reason we are using matrices.

Here is the C++-code for the L-shape:

That was rather easy, wasn’t it? There is another important question to consider, however: The correct position of each piece at the top of the screen, once it enters the game. The piece should start at the centre of the screen. As each piece is different, each piece needs different offset variables, which we will also store in an array:

I suggest you take a piece of paper and draw each Tetronimo to really understand what just happened. ^^

To easily use the newly defined Tetronimos in our game, we combine all of the above information into the Tetronimo class.

## The Tetronimo Class

The TetronimoPiece structure simply holds the basic information about each Tetronimo, i.e. its shape, its current rotation, its current position as well as for long it has been in its current position. The latter information is used to make the Tetronimos fall down over time.

The three public methods in the Tetronimo class are the ones we actually will need later in the game; basically they are just getters.

### getBlockType

Taking the type of a Tetronimo, its rotation and its position as input, this method simply returns the block type of the given tetronimo at the current position. The return value is the 0, if there is no block, 1 if it is a normal block and 2 if the requested block is the actual pivot center of the Tetronimo:

### getStartingX

Based on the type of the Tetronimo and its rotation, this method returns the horizontal offset that must be applied for the Tetronimo to enter the game in the middle of the screen:

### getStartingY

Based on the type of the Tetronimo and its rotation, this method returns the vertical offset that must be applied to the Tetrimo to make sure that only one row of the Tetronimo is visible once it enters the game:

As you can see, creating the Tetronimos really wasn’t that difficult. Now we need to create a playing field for them.

## The Game Board

To create the game board we will need, as you can surely guess, yet another array. The array will be filled with 0s or 1s, depending on whether the particular spot on the game board is filled with a Tetronimo or not:

### Filling the Board

Storing the Tetronimos on the game board (once they can no longer move) is very straightforward, for each block of the Tetronimo, the array of the game board is set to “PositionFilled”:

Obviously, once a Tetronimo is “stored” in the upper row, the game is over:

### Clearing Lines

In order for the player to survive as long as possible, they have to clear lines. To delete a single line, or row, we simply shift all the blocks above that line down by one:

Good players can clear multiple rows at a time (up to four rows). We thus have to check for possibly completed lines, and delete them, at each update. To check whether a line is complete, we simply loop through its array:

The function monitors how many lines are to be deleted and depending on whether the player managed to clear four lines at the same time or not, different animations and sounds are tasked to be played. The method also updates the current score and searched for the highest row that is occupied by a Tetronimo block (this information is used to animate the game bucket).

### Initialization

Initializing the game board is effortless, we simply chose random Tetronimos to appear:

### Collision Detection

The player can translate and rotate a Tetronimo piece. Before actually moving or rotation a piece, it is important to check for collisions with pieces already stores on the board, or, for example, when trying to rotate against the borders of the bucket:

Basically this method simply compares all the blocks of a Tetronimo pieces against the blocks already stores in the game board to see whether a desired movement, rotation or translation, is possible or not.

Imagine the player wanting to rotate a Tetronimo. We would simply call this function with the desired rotation and if the function return false, we discard the player’s wish to rotate the piece!

Creating new Tetronimos once in a while is equally easy:

### Movement

The following three straightforward methods allow the player to translate a Tetronimo piece:

And here are the methods to rotate a Tetronimo:

Notice how the isPossibleMovement function is used to check whether the desired action is possible or not.

The player can also decide to let the piece fall down immediately:

### Game Logic

Most of the work needs to be done while updating the game:

### Drawing

Now all that is left to do is to actually draw the game board. There are two methods, the first is responsible to draw a Tetronimo piece by simply running through its defining matrix:

The second method is used to draw the entire board:

To bring those two methods together, a third draw methods calls them in the correct order:

## Gameplay Features

### Game Score and Levels

To make the game a bit more interesting, the player can accumulate points while playing the game. Each time he reaches a certain number of points or clears a certain number of lines, the game level increases, that is, the game will become faster, i.e. the Tetronimos will fall down more quickly. To reflect the increase in game difficulty, the player will be awarded with more points at higher levels:

### Oracle

One new feature is to allow the player to see where the current Tetronimo would land if left alone.

To do so, we not only keep track of the current and the next piece, but of a third piece called the previewPiece, which basically is just a copy of the current piece in play:

During the game update, we will simply update the position of the preview piece based on the current Tetronimo and then tell the game to let it fall down to get a preview of where it would land:

When drawing the preview piece, we only draw the outlines of the Tetronimo:

### Switch / Shift

In many modern Tetris games, the player can switch the current piece with the next piece, but not twice in a row. The game must does keep track whether the piece was already switched or not, which can easily be done with a boolean.

Performing the shift itself is conceptually easy, the game only needs to swap the two pieces - making sure there are no collisions. The collision detection was already implemented in the “isPossibleMovement” method:

### Highscore

The game now also keeps track of the highest scores achieved, this is done via marshalling (as seen in previous tutorials).

While there are many other features, such as some graphical tweaks (changing background images, moving dots around the bucket, the bucket colours changing with the fill of the bucket) and music (the music speeds up as the levels increase), as well as an intro, menus and credits, I don’t want to elaborate on all of them, you can simply read the source code to learn how they work. All of these features simply build upon the previous tutorials. Katy wrote about some of these features on her blog.

Here is a gameplay video of an alpha version of the game:

## References

### Literature

(in alphabetic order)

• Game Programming Algorithms, by Sanjay Madhav
• Game Programming Patterns, by Robert Nystrom
• Javier López
• Katy
• Microsoft Developer Network (MSDN)
• Tricks of the Windows Game Programming Gurus, by André LaMothe
• Wikipedia