Cat hungry.png
Здравствуйте! Собираем деньги на перевод материалов по электронике(https://www.allaboutcircuits.com/education/). Реквизиты указаны здесь.

Arduino:Примеры/TFTPong

Материал из Онлайн справочника
Перейти к: навигация, поиск

Перевод: Максим Кузьмин (Cubewriter)
Перевел 2686 статей для сайта.

Контакты:

Проверка/Оформление/Редактирование: Мякишев Е.А.


Вариация Pong на TFT-экране[1]

GLCD PongDemosm.png

Этот скетч является примитивной вариацией игры Pong с использованием TFT-экрана Arduino.

В коде создается два объекта: прямоугольная платформа, способная двигаться в двух направлениях (по осям X и Y), а также мячик, способный отскакивать от этой платформы и от краев экрана. Позиция платформы управляется двумя потенциометрами (или другими аналоговыми сенсорами).

Кроме того, этот пример демонстрирует использование так называемого «обнаружения столкновений» объектов на экране, а также то, как быстро обновить изображения без необходимости стирать весь экран при каждом проходе через loop().

Необходимое оборудование

  • Плата Arduino Uno;
  • TFT-экран Arduino;
  • Макетная плата Breadboard;
  • Провода-перемычки
  • Два потенциометра на 10 кОм;

Цепь

Подключите контакты с питанием и «землей» к макетной плате.

GLCD pong1.png

Подключите оба потенциометра к макетной плате: их боковые контакты к «земле» и питанию, а центральные – к 0-ому и 1-ому аналоговым контактам.

GLCD pong2.png

Подключите TFT-экран к макетной плате. Подключить его нужно той стороной, где находятся стрелочка и маленькая голубая полоска. Также обратите внимание на ориентацию экрана. На этих рисунках он подсоединен вверх тормашками.

GLCD pong3.png

Контакты BL и +5V подключите к питанию, а GND – к «земле». CS-LD подключите к 10-ому контакту, DC – к 9-ому, RESET – к 8-ому, MOSI – к 11-ому, а SCK – к 13-ому. В случае с Leonardo вам надо будет использовать другие контакты, читайте об этом на странице о TFT-экране или в коде ниже.

GTFT pong large.png

Код

Чтобы использовать экран, подключаем библиотеки SPI и TFT.

  1. #include <SPI.h>
  2. #include <TFT.h>

Определяем контакты, которые будут использоваться для управления экраном, а затем создаем экземпляр класса TFT под названием TFTscreen. Будем обращаться к этому объекту каждый раз при работе с экраном.

  1. #define cs   10
  2. #define dc   9
  3. #define rst  8  
  4.  
  5. TFT TFTscreen = TFT(cs, dc, rst);

Задаем переменные для текущих и предыдущих координат (X и Y) платформы и мяча, а также для направления полета мяча.

  1. int paddleX = 0;
  2. int paddleY = 0;
  3. int oldPaddleX, oldPaddleY;
  4. int ballDirectionX = 1;
  5. int ballDirectionY = 1;
  6.  
  7. int ballX, ballY, oldBallX, oldBallY;

В блоке setup() инициализируем дисплей и очищаем фон экрана.

  1. void setup() {
  2.   TFTscreen.begin();
  3.   TFTscreen.background(0,0,0);
  4. }

Секция loop() начинается с создания переменных, хранящих ширину и высоту экрана. Далее считываем данные с потенциометров и приспосабливаем их к необходимому диапазону.

  1. void loop() {
  2.   int myWidth = TFTscreen.width();
  3.   int myHeight = TFTscreen.height();
  4.  
  5.   paddleX = map(analogRead(A0), 0, 1023, 0, myWidth) - 20/2;
  6.   paddleY = map(analogRead(A1), 0, 1023, 0, myHeight) - 5/2;

Задаем фоновый цвет (черный) и стираем предыдущую позицию платформы (если она сдвинулась).

  1. TFTscreen.fill(0,0,0);
  2.  
  3.   if (oldPaddleX != paddleX || oldPaddleY != paddleY) {
  4.     TFTscreen.rect(oldPaddleX, oldPaddleY, 20, 5);
  5.   }

Делаем цвет заливки белым, а затем рисуем платформу.

  1. TFTscreen.fill(255,255,255);
  2.   TFTscreen.rect(paddleX, paddleY, 20, 5);

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

  1. oldPaddleX = paddleX;
  2. oldPaddleY = paddleY;

В конце блока loop() используем значение из переменной ballSpeed, чтобы определить, как быстро будет обновляться дисплей. Кроме того, разобравшись с этим примером, вы можете добавить еще один потенциометр и менять скорость обновления дисплея уже с его помощью, да еще и в реальном времени.

Для обновления позиции мяча воспользуемся пользовательской функцией moveBall().

  1. if (millis() % ballSpeed < 2) {
  2.   moveBall();
  3.   }
  4. }

Она работает следующим образом – просто стирает предыдущую позицию мяча, а затем рисует новую. Кроме того, в этой же функции проверяется, не вылетел ли мячик за пределы экрана, и если вылетел, то направление его полета реверсируется. Кроме того, здесь же вызывается вторая пользовательская функция этого скетча – inPaddle() – в которой проверяется, не пересекаются ли позиции мяча и платформы.

  1. void moveBall() {
  2.   if (ballX > TFTscreen.width() || ballX < 0) {
  3.     ballDirectionX = -ballDirectionX;
  4.   }
  5.   if (ballY > TFTscreen.height() || ballY < 0) {
  6.     ballDirectionY = -ballDirectionY;
  7.   }  
  8.   if (inPaddle(ballX, ballY, paddleX, paddleY, 20, 5)) {
  9.     ballDirectionY = -ballDirectionY;
  10.   }
  11.  
  12.   ballX += ballDirectionX;
  13.   ballY += ballDirectionY;
  14.  
  15.   TFTscreen.fill(0,0,0);
  16.  
  17.   if (oldBallX != ballX || oldBallY != ballY) {
  18.     TFTscreen.rect(oldBallX, oldBallY, 5, 5);
  19.   }
  20.  
  21.   TFTscreen.fill(255,255,255);
  22.   TFTscreen.rect(ballX, ballY, 5, 5);
  23.  
  24.   oldBallX = ballX;
  25.   oldBallY = ballY;
  26. }

То есть, в функции inPaddle() проверяется, не занимают ли платформа и мяч одно и то же место в пространстве. Если да, то она возвращает значение TRUE, благодаря чему направление полета мяча реверсируется, как если бы он ударился о край экрана.

  1. boolean inPaddle(int x, int y, int rectX, int rectY, int rectWidth, int rectHeight) {
  2.   boolean result = false;
  3.  
  4.   if ((x >= rectX && x <= (rectX + rectWidth)) &&
  5.     (y >= rectY && y <= (rectY + rectHeight))) {
  6.     result = true;
  7.   }
  8.   return result;  
  9. }

Весь код полностью – ниже:

  1. /*
  2. Игра в Pong на TFT-экране Arduino
  3.  
  4. Этот пример для TFT-экрана Arduino считывает данные
  5. от двух потенциометров, чтобы перемещать по осям X и Y
  6. прямоугольную платформу. Эта платформа может взаимодействовать
  7. с мячиком – ударяясь о нее, он будет отскакивать и лететь дальше.
  8.  
  9. Этот пример кода не защищен авторским правом.
  10.  
  11. Создан в декабре 2012 Томом Иго (Tom Igoe),
  12. модифицирован 15 апреля 2013 Скоттом Фитцджеральдом (Scott Fitzgerald).
  13.  
  14. http://www.arduino.cc/en/Tutorial/TFTPong
  15. */
  16.  
  17. #include <TFT.h>  // библиотека для TFT-экрана Arduino
  18. #include <SPI.h>
  19.  
  20. // Определяем контакты для Arduino Uno:
  21. #define cs   10
  22. #define dc   9
  23. #define rst  8
  24.  
  25. // Определяем контакты для Arduino Leonardo (раскомментируйте, чтобы использовать):
  26. // #define cs   7
  27. // #define dc   0
  28. // #define rst  1
  29.  
  30. TFT TFTscreen = TFT(cs, dc, rst);
  31.  
  32. // Переменные для позиции мяча и платформы, а также для направления полета мяча:
  33. int paddleX = 0;
  34. int paddleY = 0;
  35. int oldPaddleX, oldPaddleY;
  36. int ballDirectionX = 1;
  37. int ballDirectionY = 1;
  38.  
  39. int ballSpeed = 10; // чем ниже это число, тем быстрее скорость мячика
  40.  
  41. int ballX, ballY, oldBallX, oldBallY;
  42.  
  43. void setup() {
  44.   // Инициализируем дисплей:
  45.   TFTscreen.begin();
  46.   // Делаем экран черным:
  47.   TFTscreen.background(0, 0, 0);
  48. }
  49.  
  50. void loop() {
  51.  
  52.   // Сохраняем ширину и высоту экрана:
  53.   int myWidth = TFTscreen.width();
  54.   int myHeight = TFTscreen.height();
  55.  
  56.   // Подстраиваем позицию платформы к позициям потенциометров:
  57.   paddleX = map(analogRead(A0), 512, -512, 0, myWidth) - 20 / 2;
  58.   paddleY = map(analogRead(A1), 512, -512, 0, myHeight) - 5 / 2;
  59.  
  60.   // Делаем цвет заливки черным и стираем предыдущую позицию платформы,
  61.   // если ее новые координаты отличаются от предыдущих:
  62.   TFTscreen.fill(0, 0, 0);
  63.  
  64.   if (oldPaddleX != paddleX || oldPaddleY != paddleY) {
  65.     TFTscreen.rect(oldPaddleX, oldPaddleY, 20, 5);
  66.   }
  67.  
  68.   // Рисуем платформу и сохраняем ее текущие координаты как предыдущие:
  69.   TFTscreen.fill(255, 255, 255);
  70.  
  71.   TFTscreen.rect(paddleX, paddleY, 20, 5);
  72.   oldPaddleX = paddleX;
  73.   oldPaddleY = paddleY;
  74.  
  75.   // Обновляем позицию мяча и рисуем его на экране:
  76.   if (millis() % ballSpeed < 2) {
  77.     moveBall();
  78.   }
  79. }
  80.  
  81. // Эта функция определяет позицию мяча на экране:
  82. void moveBall() {
  83.   // Если мячик улетает за пределы экрана, реверсируем направление его полета:
  84.   if (ballX > TFTscreen.width() || ballX < 0) {
  85.     ballDirectionX = -ballDirectionX;
  86.   }
  87.  
  88.   if (ballY > TFTscreen.height() || ballY < 0) {
  89.     ballDirectionY = -ballDirectionY;
  90.   }
  91.  
  92.   // Проверяем, не занимают ли мячик и платформа одно и то же место на экране:
  93.   if (inPaddle(ballX, ballY, paddleX, paddleY, 20, 5)) {
  94.     ballDirectionX = -ballDirectionX;
  95.     ballDirectionY = -ballDirectionY;
  96.   }
  97.  
  98.   // Обновляем позицию мяча:
  99.   ballX += ballDirectionX;
  100.   ballY += ballDirectionY;
  101.  
  102.   // Стираем предыдущую позицию мяча:
  103.   TFTscreen.fill(0, 0, 0);
  104.  
  105.   if (oldBallX != ballX || oldBallY != ballY) {
  106.     TFTscreen.rect(oldBallX, oldBallY, 5, 5);
  107.   }
  108.  
  109.  
  110.   // Рисуем текущую позицию мяча:
  111.   TFTscreen.fill(255, 255, 255);
  112.   TFTscreen.rect(ballX, ballY, 5, 5);
  113.  
  114.   oldBallX = ballX;
  115.   oldBallY = ballY;
  116.  
  117. }
  118.  
  119. // Эта функция проверяет, не пересекаются ли позиции мяча и платформы:
  120. boolean inPaddle(int x, int y, int rectX, int rectY, int rectWidth, int rectHeight) {
  121.   boolean result = false;
  122.  
  123.   if ((x >= rectX && x <= (rectX + rectWidth)) &&
  124.       (y >= rectY && y <= (rectY + rectHeight))) {
  125.     result = true;
  126.   }
  127.  
  128.   return result;
  129. }

См.также

Внешние ссылки

  1. Arduino - TFT Pong