Игра «Тетрис» на Arduino
В этом проекте мы создадим классическую игру «Тетрис» на платформе Arduino. Игровое поле и фигуры будут отображаться на LED матрице 8x8 с драйвером MAX7219, а для управления движением и вращением будет использоваться джойстик. Этот проект поможет вам освоить работу с матрицами LED и управлением пользователем с использованием Arduino.
1. Необходимые компоненты
Arduino Uno
LED матрица 8x8 с драйвером MAX7219
Джойстик
Соединительные провода
Макетная плата
2. Подключение компонентов
Подключение LED матрицы MAX7219:
VCC к 5V Arduino
GND к GND Arduino
DIN к цифровому пину 12 Arduino
CS к цифровому пину 10 Arduino
CLK к цифровому пину 11 Arduino
Подключение джойстика:
VCC к 5V Arduino
GND к GND Arduino
Ось X к аналоговому пину A0 Arduino
Ось Y к аналоговому пину A1 Arduino
Кнопка джойстика к цифровому пину 2 Arduino

3. Установка библиотеки LedControl
Для работы с матрицей MAX7219 нам понадобится библиотека LedControl. Установите её следующим образом:
Откройте Arduino IDE
Перейдите в «Скетч» → «Подключить библиотеку» → «Управлять библиотеками»
Введите “LedControl” в строке поиска
Найдите библиотеку LedControl by Eberhard Fahle и установите её
4. Программирование Arduino
Загрузите следующий код в ваш Arduino. Этот код реализует простую игру «Тетрис» с управлением через джойстик и отображением на матрице MAX7219.
#include <LedControl.h>
#define DATA_IN 12
#define CLK 11
#define LOAD 10
LedControl lc = LedControl(DATA_IN, CLK, LOAD, 1);
#define JOYSTICK_X A0
#define JOYSTICK_Y A1
#define JOYSTICK_BTN 2
#define MATRIX_SIZE 8
int field[MATRIX_SIZE][MATRIX_SIZE] = {0};
int tetromino[4][4];
int tetrominoX = 2, tetrominoY = 0;
unsigned long lastMoveDown = 0;
unsigned long lastMoveSide = 0;
bool gameOver = false;
void setup() {
lc.shutdown(0, false);
lc.setIntensity(0, 8);
lc.clearDisplay(0);
pinMode(JOYSTICK_BTN, INPUT_PULLUP);
newTetromino();
}
void loop() {
if (gameOver) {
delay(2000);
resetGame();
return;
}
int xValue = analogRead(JOYSTICK_X);
int yValue = analogRead(JOYSTICK_Y);
bool buttonPressed = digitalRead(JOYSTICK_BTN) == LOW;
if (millis() - lastMoveSide > 250) {
if (xValue < 400) moveLeft();
else if (xValue > 600) moveRight();
lastMoveSide = millis();
}
if (millis() - lastMoveDown > 700) {
moveDown();
lastMoveDown = millis();
}
if (buttonPressed) {
rotateTetromino();
delay(200);
}
drawField();
delay(100);
}
void drawField() {
lc.clearDisplay(0);
// Отображение игрового поля
for (int y = 0; y < MATRIX_SIZE; y++) {
for (int x = 0; x < MATRIX_SIZE; x++) {
if (field[y][x]) lc.setLed(0, y, x, true);
}
}
// Отображение текущей фигуры
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
if (tetromino[y][x]) {
lc.setLed(0, tetrominoY + y, tetrominoX + x, true);
}
}
}
}
void newTetromino() {
// Определение форм тетромино
int tetrominoShapes[7][4][4] = {
{{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {1, 1, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {1, 1, 1, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {1, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {0, 1, 1, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}},
{{0, 0, 0, 0}, {1, 1, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}}
};
// Выбор случайной формы
int shape = random(7);
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
tetromino[y][x] = tetrominoShapes[shape][y][x];
}
}
// Начальная позиция фигуры
tetrominoX = 2;
tetrominoY = 0;
if (collides()) {
gameOver = true; // Игра окончена, если новая фигура сталкивается
}
}
void rotateTetromino() {
int rotated[4][4];
// Вращение фигуры
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
rotated[x][3 - y] = tetromino[y][x];
}
}
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
tetromino[y][x] = rotated[y][x];
}
}
// Проверка столкновений после вращения
if (collides()) {
// Восстановление предыдущего состояния, если есть столкновение
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
tetromino[y][x] = rotated[3 - x][y];
}
}
}
}
void moveLeft() {
tetrominoX--; // Движение влево
if (collides()) {
tetrominoX++; // Отмена движения, если есть столкновение
}
}
void moveRight() {
tetrominoX++; // Движение вправо
if (collides()) {
tetrominoX--; // Отмена движения, если есть столкновение
}
}
void moveDown() {
tetrominoY++; // Движение вниз
if (collides()) {
tetrominoY--; // Отмена движения, если есть столкновение
placeTetromino(); // Установка фигуры на поле
clearLines(); // Очистка заполненных линий
newTetromino(); // Создание новой фигуры
}
}
void placeTetromino() {
// Размещение текущей фигуры на поле
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
if (tetromino[y][x]) {
field[tetrominoY + y][tetrominoX + x] = 1;
}
}
}
}
void clearLines() {
// Очистка заполненных линий
for (int y = 0; y < MATRIX_SIZE; y++) {
bool fullLine = true;
for (int x = 0; x < MATRIX_SIZE; x++) {
if (!field[y][x]) {
fullLine = false;
break;
}
}
// Сдвиг линий вниз, если линия заполнена
if (fullLine) {
for (int ny = y; ny > 0; ny--) {
for (int x = 0; x < MATRIX_SIZE; x++) {
field[ny][x] = field[ny - 1][x];
}
}
// Очистка верхней линии
for (int x = 0; x < MATRIX_SIZE; x++) {
field[0][x] = 0;
}
}
}
}
bool collides() {
// Проверка на столкновения
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
if (tetromino[y][x]) {
int nx = tetrominoX + x;
int ny = tetrominoY + y;
if (nx < 0 || nx >= MATRIX_SIZE || ny < 0 || ny >= MATRIX_SIZE || field[ny][nx]) {
return true;
}
}
}
}
return false;
}
void resetGame() {
// Сброс игрового поля
for (int y = 0; y < MATRIX_SIZE; y++) {
for (int x = 0; x < MATRIX_SIZE; x++) {
field[y][x] = 0;
}
}
gameOver = false; // Сброс флага окончания игры
newTetromino(); // Создание новой фигуры
}
5. Пояснения к коду
Инициализация библиотеки LedControl: используется для управления матрицей MAX7219
Настройка матрицы: установка яркости и очистка экрана
Создание переменных: игровое поле, фигура, координаты
Управление джойстиком: считывание X, Y и кнопки
Движение и вращение: реализация движений и поворотов фигуры
Отображение: функция drawField() рисует поле и фигуру
Обработка столкновений: проверка границ и наложения
Перезапуск игры: функция resetGame() очищает поле и начинает заново
6. Заключение
Проект «Тетрис на Arduino с использованием матрицы MAX7219 и джойстика» предоставляет увлекательный способ изучения основ программирования и работы с аппаратными компонентами. Этот проект подходит как для начинающих, так и для опытных пользователей, интересующихся созданием интерактивных игр и работой с микроконтроллерами.
Вы также можете расширить проект:
Подключить дополнительные матрицы
Добавить LCD-дисплей
Реализовать уровни сложности и счёт
Добавить музыку и звуковые эффекты
✨ Всё ограничивается лишь вашей фантазией!