Arduino:Примеры/Esplora TFT Pong

Материал из Онлайн справочника
Версия от 12:34, 8 июля 2023; EducationBot (обсуждение | вклад)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигацииПерейти к поиску

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


Игра в Pong на TFT-экране Esplora[1]

Этот пример для платы Arduino (и подключенного к ней TFT-экрана Arduino) является упрощенной вариацией на тему игры Pong.

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

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

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

  • Плата Arduino Esplora;
  • TFT-экран Arduino;

Цепь

Подключите TFT-экран к сокету на Esplora – так, чтобы надпись «SD Card» смотрела вверх.

Код

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

#include <Esplora.h>
#include <TFT.h>
#include <SPI.h>

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

int paddleX = 0;
int paddleY = 0;
int oldPaddleX, oldPaddleY;
int ballDirectionX = 1;
int ballDirectionY = 1;

int ballX, ballY, oldBallX, oldBallY;

В секции setup() запускаем последовательную передачу данных, инициализируем дисплей и очищаем фон экрана.

void setup() {
  Serial.begin(9600);
  EsploraTFT.begin();
  EsploraTFT.background(0,0,0); 
}

В блоке loop() будет код для считывания данных от джойстика, затем стирание предыдущей позиции платформы и, наконец, прорисовка новой позиции платформы.

void loop() {
  int myWidth = EsploraTFT.width();
  int myHeight = EsploraTFT.height();

  paddleX = map(Esplora.readJoystickX(), 512, -512, 0, myWidth) - 20/2; 
  paddleY = map(Esplora.readJoystickY(), -512, 512, 0, myHeight) - 5/2; 
  Serial.print(paddleX);
  Serial.print(" ");
  Serial.println(paddleY);

  EsploraTFT.fill(0,0,0);

  if (oldPaddleX != paddleX || oldPaddleY != paddleY) {
    EsploraTFT.rect(oldPaddleX, oldPaddleY, 20, 5);
  }

  EsploraTFT.fill(255,255,255);
  EsploraTFT.rect(paddleX, paddleY, 20, 5);

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

oldPaddleX = paddleX;
  oldPaddleY = paddleY;

В конце блока loop() считываем позицию слайдера, чтобы определить скорость мяча. Также вызываем пользовательскую функцию под названием moveBall() – с ее помощью мы будем обновлять позицию мяча.

int ballSpeed = map(Esplora.readSlider(), 0, 1023, 0, 80)+1;
  if (millis() % ballSpeed < 2) {
    moveBall();
  }
}

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

void moveBall() {
  if (ballX > EsploraTFT.width() || ballX < 0) {
    ballDirectionX = -ballDirectionX;
  }
  if (ballY > EsploraTFT.height() || ballY < 0) {
    ballDirectionY = -ballDirectionY;
  }  
  if (inPaddle(ballX, ballY, paddleX, paddleY, 20, 5)) {
    ballDirectionY = -ballDirectionY;
  }

  ballX += ballDirectionX;
  ballY += ballDirectionY;

  EsploraLCD.fill(0,0,0);

  if (oldBallX != ballX || oldBallY != ballY) {
    EsploraTFT.rect(oldBallX, oldBallY, 5, 5);
  }

  EsploraLCD.fill(255,255,255);
  EsploraLCD.rect(ballX, ballY, 5, 5);

  oldBallX = ballX;
  oldBallY = ballY;
}

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

boolean inPaddle(int x, int y, int rectX, int rectY, int rectWidth, int rectHeight) {
  boolean result = false;

  if ((x >= rectX && x <= (rectX + rectWidth)) && 
    (y >= rectY && y <= (rectY + rectHeight))) {
    result = true; 
  }
  return result;  
}

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

/*
Игра в Pong на TFT-экране Esplora

Это пример для платы Esplora и TFT-экрана Arduino.
Он считывает данные, поступающие от джойстика, чтобы перемещать
прямоугольную платформу по осям X и Y. Платформа может
взаимодействовать с мячом – ударившись о нее, он будет отскакивать.
Скорость мяча регулируется линейным потенциометром Esplora.

Этот код не защищен авторским правом.

Создан в декабре 2012 Томом Иго (Tom Igoe),
модифицирован 15 апреля 2013 Скоттом Фитцджеральдом (Scott Fitzgerald).

http://www.arduino.cc/en/Tutorial/EsploraTFTPong
*/

#include <Esplora.h>
#include <TFT.h>            // библиотека для TFT-экрана Arduino
#include <SPI.h>

// переменные для координат мяча и платформы:
int paddleX = 0;
int paddleY = 0;
int oldPaddleX, oldPaddleY;
int ballDirectionX = 1;
int ballDirectionY = 1;

int ballX, ballY, oldBallX, oldBallY;

void setup() {

  Serial.begin(9600);

  // Инициализируем дисплей:
  EsploraTFT.begin();
  // Закрашиваем фон черным цветом:
  EsploraTFT.background(0, 0, 0);
}

void loop() {
  // Сохраняем ширину и высоту экрана:
  int myWidth = EsploraTFT.width();
  int myHeight = EsploraTFT.height();

  // Приспосабливаем диапазон хода джойстика к размерам экрана:
  paddleX = map(Esplora.readJoystickX(), 512, -512, 0, myWidth) - 20 / 2;
  paddleY = map(Esplora.readJoystickY(), -512, 512, 0, myHeight) - 5 / 2;
  Serial.print(paddleX);
  Serial.print(" ");
  Serial.println(paddleY);

  // Делаем цвет заливки черным и стираем предыдущую позицию платформы, 
  // если она отличается от текущей:
  EsploraTFT.fill(0, 0, 0);

  if (oldPaddleX != paddleX || oldPaddleY != paddleY) {
    EsploraTFT.rect(oldPaddleX, oldPaddleY, 20, 5);
  }

  // Рисуем на экране платформу, сохраняем ее текущую позицию как предыдущую:
  EsploraTFT.fill(255, 255, 255);
  EsploraTFT.rect(paddleX, paddleY, 20, 5);
  oldPaddleX = paddleX;
  oldPaddleY = paddleY;

  // Считываем данные от слайдера, чтобы определить скорость мяча:
  int ballSpeed = map(Esplora.readSlider(), 0, 1023, 0, 80) + 1;
  if (millis() % ballSpeed < 2) {
    moveBall();
  }
}

// Функция для определения позиции мяча на экране:
void moveBall() {
  // Если мяч улетел за пределы экрана, реверсируем его направление:
  if (ballX > EsploraTFT.width() || ballX < 0) {
    ballDirectionX = -ballDirectionX;
  }

  if (ballY > EsploraTFT.height() || ballY < 0) {
    ballDirectionY = -ballDirectionY;
  }

  // Проверяем, не занимают ли платформа и мяч одно и то же место в пространстве:
  if (inPaddle(ballX, ballY, paddleX, paddleY, 20, 5)) {
    ballDirectionY = -ballDirectionY;
  }

  // Обновляем позицию мяча:
  ballX += ballDirectionX;
  ballY += ballDirectionY;

  // Стираем предыдущую позицию мяча:
  EsploraTFT.fill(0, 0, 0);

  if (oldBallX != ballX || oldBallY != ballY) {
    EsploraTFT.rect(oldBallX, oldBallY, 5, 5);
  }

  // Рисуем текущую позицию мяча:
  EsploraTFT.fill(255, 255, 255);

  EsploraTFT.rect(ballX, ballY, 5, 5);

  oldBallX = ballX;
  oldBallY = ballY;

}

// Функция для проверки того, не пересекаются ли позиции мяча и платформы:
boolean inPaddle(int x, int y, int rectX, int rectY, int rectWidth, int rectHeight) {
  boolean result = false;

  if ((x >= rectX && x <= (rectX + rectWidth)) &&
      (y >= rectY && y <= (rectY + rectHeight))) {
    result = true;
  }

  return result;
}

См.также

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