# Lesson 6 - Tetris in MonoGame: Block

In the previous lesson, Dividing a MonoGame Project into Components, we showed how to divide a game project into several components.

Today we're finally starting with the Tetris logic, more precisely with the falling block.

There will always be only two block instances during gameplay - the one that is currently falling down, and the other one that will be next. Since there's going to be more than one block instance in our game, we'll represent the block by a standard class, instead of a game component. Components usually contain a major part of the game logic. After the block hits the "ground", it becomes part of the game board, which isn't a block collection, but a two-dimensional tile array. There certainly are many other solutions to implement this, but this appears to be the simplest one to me.

Let's add a new class that'll represent the Tetris block into the `Robotris` project. We'll name it `Block` and and set its access modifier to `public`.

`public class Block`

We'll add a public `Tiles` property to it, which will be a two-dimensional `int` type array. This will store the individual tiles that the block is made of. The array size is 4x4 (because of the I-block, which is the longest one). We could imagine the S-block like this:

```0110
1100
0000
0000```

`1` represents a used tile, while `0` represents an empty one. We'll set the property setter to private, but it's not completely necessary, since we'd achieve a similar result using an ordinary field. In games, properties aren't used as much as we're used to. That's because they're slower, and video games usually require maximum performance.

`public int[,] Tiles { get; private set; }`

Next, we'll add the block's position on the game board, making it a regular public field of the `Vector2` type. Since `Vector2` is a structure (a value type), it'd be a problem to modify its components if we made it a property. So don't worry to use standard public fields in your game projects. Also, we'll add the necessary `using` statement:

`using Microsoft.Xna.Framework;`

and the field itself:

`public Vector2 position;`

Since we know that arrays in C# are passed by reference, we can't simply assign the tiles of one block into another. The problem would be that both blocks would use the same tiles, and if one of them was rotated, the other block would rotate as well. Because we'll copy the block tiles often, we'll create a method for it. It'll create a new tiles array and assign the values of those we want to copy. The tiles array copy will be then returned. We only need two nested `for` loops for the whole process.

```private int[,] CopyTiles(int[,] tiles)
{
int [,] newTiles = new int [4, 4];
for (int j = 0; j < 4; j++)
for (int i = 0; i < 4; i++)
newTiles[i, j] = tiles[i, j];
return newTiles;
}```

Now, let's implement a class constructor that will take the tiles as a parameter to create its tiles based on it. We'll also reset the block position:

```public Block(int[,] tiles)
{
Tiles = CopyTiles(tiles);

position = new Vector2(0, 0);
}```

## Falling

Let's add a simple method named `Fall()` that'll move the block one row downward:

```public void Fall()
{
position.Y++;
}```

## Rotating

That was very easy Now let's try something more challenging. We'll write a method that rotates our tiles array clockwise. We'll rotate the block by copying its tiles array and use this copy to replace the original array. The trick is that while doing it, we'll also swap the X and Y coordinates and then subtract the Y coordinate from the number 3. For better understanding, see the illustration below: If you're still confused, try to draw it on a piece of paper and rotate it. If that doesn't help, you just have to trust me The method looks like this:

```public void Rotate()
{
// temp array
int[,] a = CopyTiles(Tiles);
// rotate the array by swapping coordinates, like it was a matrix
for (int y = 0; y < 4; y++)
for (int x = 0; x < 4; x++)
Tiles[x, y] = a[y, 3 - x];
}```

The block rotation has a problem that we'll ignore for the sake of tutorial simplicity. Some blocks are 2x2 tiles large (only the O-block in the original version), some are 3x3 tiles large and some even 4x4 (the I-block in the original version). The method above always rotates the block as it was 4x4, so smaller blocks aren't centered properly. This could be solved by adding some additional check. If you demand it, I can add it after the course is completed.

Now we just need to render the block. We've already shown how to render components. The block rendering will be very similar. Let's start by adding the `Draw()` method to it, with a `SpriteBatch` and the corresponding tile texture as parameters. In components, we injected dependencies by passing the game instance in the component's constructor. Now we pass references via method parameters, which is another way to deal with dependencies. This way is better for individual game objects (e.g. individual tiles). Components, on the other hand, are much larger logical parts (e.g. a level containing tiles, the game board, ...). Since the block coordinates are the coordinates in the game board (i.e. [6; 10]) and not the coordinates on the screen, we'll add the border parameter that'll allow us to shift the block. The method will loop through all individual tiles and render those that have their value greater than `0`. Inside the loops, we'll calculate the render position using the tile size to place the tiles side by side next to each other. We'll get the size from the `Width` and the `Height` properties of the texture instance.

```public void Draw(Vector2 border, BetterSpriteBatch spriteBatch, Texture2D sprite)
{
for (int j = 0; j < 4; j++)
for (int i = 0; i < 4; i++)
if (Tiles[i, j] > 0)
spriteBatch.Draw(sprite, new Vector2(border.X + (i + position.X) * sprite.Width,
border.Y + (j + position.Y) * sprite.Height), Color.White);
}```

We'll add the following `using` statement to use the `Texture2D` type

`using Microsoft.Xna.Framework.Graphics;`

Now, let's test the class. Download the tile sprites from the archive below this article. It's a set of 15 tile sprites. Open the `Tiles/` folder and drag it into the `Sprites/` folder in MonoGame Pipeline Tool. This is how it should look like: Let's go to the `LevelComponent` class and add 3 private fields to it:

```private Block block;
private Vector2 gameBoardPosition;
private Texture2D tileSprite;```

The first one is the currently falling block instance, the second one is the game board position in the level background, and the third one is the tile sprite.

In `Initialize()`, we'll assign a new `Block` class instance into the `block` field. Since we don't have a generator that would create blocks from certain patterns yet, we'll create one such pattern ourselves for testing purposes. Since we know that a new .NET integer array contains only zeros, we just need to set 4 specific values to form the S-block (the block shown in the block rotation picture above):

```int[,] pattern = new int[4, 4];
pattern[1, 0] = 1;
pattern[2, 0] = 1;
pattern[0, 1] = 1;
pattern[1, 1] = 1;
block = new Block(pattern);```

We'll also set the `gameBoardPosition` field right after it:

`gameBoardPosition = new Vector2(366, 50);`

Inside `LoadContent()` we'll load one of the tile sprites into the respective field we defined:

`tileSprite = robotisGame.Content.Load<Texture2D>(@"Sprites\Tiles\5");`

Now let's move into `Draw()` and add the block rendering right after the background rendering:

`block.Draw(gameBoardPosition, robotrisGame.spriteBatch, tileSprite);`

Although we have to call the `Draw()` method, the block still handles all the rendering operations itself. This is how it should be with all game objects.

Now let's try: As the last thing, we'll add the rotation logic. Inside `Update()` we'll update the rotation when either the Enter key or the up arrow cursor key is pressed:

```if (robotrisGame.NewKey(Keys.Enter) || robotrisGame.NewKey(Keys.Up))
block.Rotate();```

You can try again. Except for the problem of rotating 3x3 block as 4x4 block, it works pretty well.

In the next lesson, Tetris in MonoGame: Block Generator, we'll implement a block generator, and make the block render its tile sprites randomly.

Application includes source codes

Article has been written for you by David Capka The author learned IT at the Unicorn University - a prestigious college providing education on IT and economics.