» » » Делаем Тетрис на Arduino

Делаем Тетрис на Arduino

Приветствую, Самоделкины!
Сегодня мы займемся изучением внутренностей игры Тетрис, написанной под платформу arduino и светодиодную матрицу.

Автором данной самоделки является AlexGyver, автор одноименного YouTube канала. Добро пожаловать в удивительный мир квадратных пикселей.

Начнем, пожалуй, с истории. Тетрис - это игра, в которой сверху вниз падают фигуры, состоящие из 4-х квадратиков. В разных сочетаниях эти фигуры можно поворачивать и перемещать вправо-влево. Цель игры собирать горизонтальные уровни, которые очищаются и вам начисляются очки. Проигрышем считается момент, когда новой фигуре уже некуда упасть. Придумал тетрис советский программист Алексей Леонидович Пажитнов.

Первоначальная версия на языке Паскаль (Pascal) появилась 6 июня 1984 года. С тех пор тетрис проделал огромный путь и был портирован на все платформы, на которых вообще можно играть в игры, а также на устройства вовсе для игр не предназначенные, например, такие как инженерный калькулятор, осциллограф и, вы не поверите, паяльник.



По количеству проданных коммерческих версий, тетрис превосходит любую другую игру в истории человечества. Лишь для одной Game Boy было продано 35 миллионов копий, не говоря о портативной Brick Game, которая в свое время была практически у всех.
Реализацию тетриса на arduino и цветной матрицы начнем с разбора «костылей». Матрица состоит из трехцветных адресных светодиодов. Проблема у данного типа матриц и в том, что она слишком крутая. Цвет каждого пикселя кодируется 24 битами, то есть по 8 бит на каждую составляющую: красный, зеленый и синий. Такого типа данных на arduino нет, есть следующий - 32 бита.

Цвета всех светодиодов должны храниться в оперативной памяти, так как мы будем их менять. И того, для матрицы 16 на 16 имеем ровно 1 Кб занятой динамической памяти, а у arduino nano их всего 2.

Добавим еще несколько библиотек и начнем писать код, память и во все закончится. Автор принципиально не использует, например, arduino mega, где памяти больше. Цель сделать игру именно на arduino nano, используя простые, стандартные и всем известные инструменты, но в то же время нестандартные подходы и «костыли» и с их помощью добиться максимально оптимального кода.

Первым «костылем» будет отказ от отдельного хранение в памяти позиций фигур и вообще всего, что творится на экране. Нам нужно хранить координаты точек подающей фигуры и координаты точек уже упавших фигур, то есть как максимум нам нужен еще 1 массив, двумерный 16 на 16, а это еще целых 256 байт.

У нас с вами уже есть массив цветов всех пикселей, давайте использовать его. Ведь помимо того, что мы можем поставить на матрицу цветную точку, мы можем измерить свет уже имеющейся точки так, что работать будем именно с цветами.

Тетрис начинается с падающего блока, который управляется кнопками и имеет 2 координаты в системе координат матрицы. Это очень просто, возводим таймер, по которому будет падать блок. Это библиотека автора, можете почитать на сайте.

Для обработки кнопок, автор также использует свою библиотеку. Схема подключения кнопок до смешного проста: 4 кнопки, 8 проводов.

Каждый шаг таймера мы рисуем точку на пиксель ниже старой, а старую точку рисуем черным цветом, то есть выключаем светодиод. По нажатию на кнопку делаем то же самое, но с горизонтальной координатой. Ну и для приличия, ограничим по размерам матрицы, чтобы точка не вышла за пределы поля.

Видите, ничего сложного. Но это ненадолго потому, что настало время рисовать фигуры. Работать будем следующим образом: сохраним привязку к подающей точке, которая у нас уже написана, назовем ее главная точка или главный блок. Главный блок двигается в системе координат матрицы, это мы уже сделали. Все фигуры тетриса состоят из 4-ех блоков, именно поэтому, кстати, он и называется Тетрис.

Соответственно, нам осталось дорисовать главному блоку еще 3 блока. Давайте напишем их координаты в системе координат главного блока, причем так, чтобы главный блок всегда находился снизу. Это очень просто, возьмем фигуру перевернутая буква Т. Главный блок снизу в центре, имеет координаты 0.0 в своей системе координат.

Верхний блок 0.1, правый 1.1 и левый -1.1.

Возьмем букву Г. Нижний блок 0.0, следующий 0.1, следующий 0.2 и краешек буквы 1.2.

Эти координации запишем в массив вот в таком виде: {0.1, 0.2, 1.2} и массив закинем во флэш-память чтобы не тратить память динамическую. Что касается поворота фигур. Именно поворачивать фигуры у нас не получится. Банально очень трудно объяснить микроконтроллеру как это сделать. Для этого нужно задавать центр вращения, как-то раскладывать фигуру на части и у каждой части искать новые координаты с учетом сильной пикселизации, что явно приведет к ошибкам и получится ерунда. Проблема решается очень просто, будем хранить в памяти все 4 положения для всех фигур и всё.

Собственно, теперь осталось случайно выбирать номер фигуры и отрисовывать ее вокруг падающего блока. Здесь мы для всех 3-ех оставшихся блоков берем из флеш-памяти координаты, переводим их в глобальные координаты матрицы и включаем светодиоды. Кстати, цвет тоже выбирается случайно из 6-ти самых простых и ярких цветов пространства rgb. Угол поворота фигуры при начале раунда тоже задается случайно, а при нажатии кнопки вверх, просто берем для отрисовки следующий набор координат и вращаем по часовой стрелке. Перемещение фигуры работает все также. Сначала стираем фигуру на предыдущем положении, то есть рисуем ее черным цветом, затем в новом положении рисуем уже текущим цветом фигуры. При повороте, опять же, стираем старое положение и просто рисуем новое.

Прошивку можно скачать на странице проекта. Разберем только самую суть. Начнем с проверки левой и правой стенки и днища. С днищем все очень просто, каждый шаг падения смотрим, не достиг ли базовый блок отметки 0 по высоте, это несложно, а вот каждое нажатие на кнопку управления нам нужно смотреть не коснулась ли крайняя точка фигуры боковых стенок матрицы.

Если коснулась, то фигуру не двигать. То же самое касается вращения фигур. Например, если новое положение фигуры будет выходить за стенки, то поворот запретить, а так как все фигуры у нас разной формы, то и крайние блоки у них у всех разные. Можно было бы для каждой фигуры расписать отдельные крайние блоки, чтобы упростить работу микроконтроллеру, но пусть считает, его для этого и придумали.

Все очень просто. А вот следующая задача гораздо более интересная. Нам нужно проверять столкновение с уже лежащими снизу блоками. Если бы у нас был массив, в котором содержится состояние всех клеток поля, то было бы проще, но мы будем использовать массив цветов пикселей ленты, поэтому нас ждет самый крутой «костыль». В чем собственно проблема. Вроде бы все просто, падает у нас скажем зеленая фигура и мы каждый шаг падения, каждое смещение в бок и каждую попытку поворота, должны проверять, не упирается ли фигура в новом положении в уже лежащие фигуры. Если для всех блоков окружающей цвет равен черному или равен цвету фигуры, то разрешаем перемещение в нужном направлении. Это будет работать до тех пор, пока фигура под нами не будет того же цвета, что и падающая фигура. Вот собственно и «костыль»: упавшую фигуру будем перекрашивать в другой цвет. Перекрашивать незаметно для глаз, но заметно для программы. Все, что нужно сделать, это чуть-чуть увеличить яркость текущего цвета фигуры и все.


Фигура упала на днище или другую фигуру, ее яркость не заметно увеличилась и в новом раунде падающие фигуры уже не перепутают ее цвет со своим, будут падать на нее и точно также фиксироваться, слегка прибавляя яркость.

Кстати, при нажатии кнопки вниз, фигура с большой скоростью устремляется вниз и занимает свое место.

Остался нашему тетрису последний штрих, а именно проверка и очистка заполненных уровней по горизонтали. Тут все просто. После фиксации фигуры в текущем раунде, мы продвигаемся по строкам и сравниваем цвета пикселей с черным. Если во всей строке нет ни одного черного пикселя, то всю строку будем очищать.


Обнаруженные строки заливаются белым, затем яркость плавно падает до нуля и получается анимация. Далее все пиксели, начиная с первой заполненной линии и до верха, смещаются вниз на и количество строк, которое было очищено. Этот процесс повторяется до тех пор, пока не останется заполненных уровней. Также проверяем не достигли ли мы верха, что означает проигрыш. В этом случае на экран выводится счет, равный количеству очищенных уровней.

Счет выводится цифрами, которые хранятся в памяти как набор единиц и нулей, по которым далее включаются или не включаются светодиоды. Собственного так выглядит тетрис, написанный под адресную матрицу. Благодарю за внимание. До новых встреч!

Видео:

Источник
Становитесь автором сайта, публикуйте собственные статьи, описания самоделок с оплатой за текст. Подробнее здесь.

Часы метеостанция на Arduino

3D цифровой песок

10
Идея
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
10
Описание
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
10
Исполнение
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
Итоговая оценка: 10 из 10 (голосов: 1 / История оценок)

Добавить комментарий

    • smilesmilesxaxaokdontknowyahoonea
      bossscratchfoolyesyes-yesaggressivesecret
      sorrydancedance2dance3pardonhelpdrinks
      stopfriendsgoodgoodgoodwhistleswoontongue
      smokeclappingcraydeclarederisivedon-t_mentiondownload
      heatirefullaugh1mdameetingmoskingnegative
      not_ipopcornpunishreadscarescaressearch
      tauntthank_youthisto_clueumnikacuteagree
      badbeeeblack_eyeblum3blushboastboredom
      censoredpleasantrysecret2threatenvictoryyusun_bespectacled
      shokrespektlolprevedwelcomekrutoyya_za
      ya_dobryihelperne_huliganne_othodifludbanclose

Привет, Гость!


Зарегистрируйтесь

Или войдите на сайт, если уже зарегистрированы...

Войти

Добавьте самоделку

Добавьте тему

Онлайн чат

Опрос
А Вы уже рассказали на сайте о своей самоделке?

Последние комментарии

Все комментарии
Новые самоделки на почту

Введите электронную почту и получайте письма с новыми самоделками. Не более одного письма в день.