Make Your Own Tetris Game With Meadow

Photo of jorgedevs

Made by jorgedevs

About the project

Learn how easy is to make a Tetris game with a joystick and an LED matrix.

Project info

Difficulty: Easy

Platforms: MicrosoftMeadowWilderness Labs

Estimated time: 1 hour

License: MIT license (MIT)

Items used in this project

Hardware components

Pimoroni Micro Dot pHAT w/Red LEDs Pimoroni Micro Dot pHAT w/Red LEDs x 4
Tiny Breadboard Tiny Breadboard x 1
Tiny Breadboard Tiny Breadboard x 1
Jumper Wire Kit - 140pcs Jumper Wire Kit - 140pcs x 1
Raspberry Pi 4 Model B 1GB, 2GB, 4GB or 8GB RAM Raspberry Pi 4 Model B 1GB, 2GB, 4GB or 8GB RAM x 1

Software apps and online services

Microsoft Visual Studio 2019 Microsoft Visual Studio 2019

Story

In this project we're going to learn how easy is to make our very own Tetris game with a 2 axis analog joystick and a MAX7219 LED dot matrix display. To write the logic for these peripherals, we'll use Meadow.Foundation, and use the Graphics Library to implement the gameplay (which we've made an intro project on a TFT SPI display).

Meadow.Foundationa platform for quickly and easily building connected things using.NET on Meadow. Created by Wilderness Labs, it's completely open source and maintained by the Wilderness Labs community.

If you're new working with Meadow, I suggest you go to the Getting Started w/ Meadow by Controlling the Onboard RGB LEDproject to properly set up your development environment.

Step 1 - Assemble the circuit

Wire your project like this:

Fritzing Diagram for the Tetris game

Fritzing Diagram for the Tetris game

Fritzing Diagram for the Tetris game

Step 2 - Create a Meadow Application project

Create a new Meadow Application project in Visual Studio 2019 for Windows or macOS and name it MeadowTetris.

Step 3 - Add the required NuGet packages

Windows

Right-click on your MeadowTetris project and click Manage NuGet Packages. In the Browse tab, search for Meadow.Foundation.Displays.GraphicsLibrary and Meadow.Foundation.Displays.Max7219 and click Install to add it to your project.

macOS

Alt-click on your MeadowTetris project in the Solution Explorer, and click Add => Add Nuget Package to open the NuGet Package window. Search for Meadow.Foundation.Displays.GraphicsLibrary and Meadow.Foundation.Displays.Max7219 and click Install to add it to your project.

Step 4 - Write the code for MeadowTetris

Copy the following code below:

Add TetrisGame class

Add a new TetrisGame class, and copy the game logic from the TetrisGame class source in GitHub.

MeadowApp class

In the MeadowApp class, copy the following code:

public class MeadowApp : App<F7Micro, MeadowApp>{    Max7219 display;    GraphicsLibrary graphics;    AnalogJoystick joystick;    TetrisGame game = new TetrisGame(8, 24);    public MeadowApp()    {        Console.WriteLine("Tetris");        Init();        Console.WriteLine("Start game");        StartGameLoop();    }    int tick = 0;    void StartGameLoop()    {        while (true)        {            tick++;            CheckInput(tick);            graphics.Clear();            DrawTetrisField();            graphics.Show();            Thread.Sleep(50);        }    }    async Task CheckInput(int tick)    {        if (tick % (21 - game.Level) == 0)        {            game.OnDown(true);        }        var pos = await joystick.GetPosition();        if (pos == AnalogJoystick.DigitalJoystickPosition.Left)        {            game.OnLeft();        }        if (pos == AnalogJoystick.DigitalJoystickPosition.Right)        {            game.OnRight();        }        if (pos == AnalogJoystick.DigitalJoystickPosition.Up)        {            game.OnDown();        }        if (pos == AnalogJoystick.DigitalJoystickPosition.Down)        {            game.OnRotate();            await Task.Delay(500);        }    }    void DrawTetrisField()    {        graphics.DrawText(0, 0, $"{game.LinesCleared}");        int yOffset = 8;        //draw current piece        for (int i = 0; i < 4; i++)        {            for (int j = 0; j < 4; j++)            {                if (game.IsPieceLocationSet(i, j))                {                    graphics.DrawPixel((game.CurrentPiece.X + i),                    game.CurrentPiece.Y + j + yOffset);                }            }        }        //draw gamefield        for (int i = 0; i < game.Width; i++)        {            for (int j = 0; j < game.Height; j++)            {                if (game.IsGameFieldSet(i, j))                {                    graphics.DrawPixel(i, j + yOffset);                }            }        }    }    void Init()    {        Console.WriteLine("Init");        display = new Max7219(            device: Device,            spiBus: Device.CreateSpiBus(),            csPin: Device.Pins.D01,            deviceCount: 4,            maxMode: Max7219.Max7219Type.Display);        graphics = new GraphicsLibrary(display);        graphics.CurrentFont = new Font4x8();        graphics.Rotation = GraphicsLibrary.RotationType._180Degrees;        joystick = new AnalogJoystick(Device, Device.Pins.A00, Device.Pins.A01, null);    }}

Init method

Initializes the Max7219 LED dot matrix, passing an SPI bus, chip select pin, and device count four (4), since we have four connected side by side. We also create a GraphicLibrary object so we can easily draw the gameplay.

After display and graphics initialized, we create a AnalogJoystick object, which we only pass the two (2) analog ports is connected to Meadow.

StartGameLoop method

The app enters a infinite while loop in which it does two things: checks for the user's input as he/she moves the joystick, and based on the position, it calls DrawTetrisField to redraw the state of the game.

CheckInput method

In each iteration of the game loop, we check if we should check that depending on which cycle we are, we call the game.OnDown(true) method to slowly move the piece down, and after that we call await joystick.GetPosition(); to get the position of the joystick in that instant, and we use a switch case to see which one of the four directions to trigger the corresponding game event to update the state of the game logic.

DrawTetrisField method

This method draws the latest update of the state of the Game. We first print the number of lines cleared on the top of the screen using the DisplayText API method provided by GraphicsLibrary, and after we draw pixel by pixel on the Tetris board to draw redraw the whole screen.

Step 5 - Run the project

Click the Run button in Visual Studio. It should look like to the following GIF:

Tetris project running...

Tetris project running...

Tetris project running...

Check out Meadow.Foundation!

This project is only the tip of the iceberg in terms of the extensive exciting things you can do with Meadow.Foundation.

  • It comes with a huge peripheral driver library with drivers for the most common sensors and peripherals.
  • The peripheral drivers encapsulate the core logic and expose a simple, clean, modern API.
  • This project is backed by a growing community that is constantly working on building cool connected things and are always excited to help new-comers and discuss new projects.

References

Schematics, diagrams and documents

Tetris circuit diagram

Code

Tetris complete project

You can check the Tetris project in Meadow_Samples/Source/MeadowSamples/Meadow.Foundation/Tetris

Credits

Leave your feedback...