Arduino:Примеры/TFTPong
Содержание | Знакомство с Arduino | Продукты | Основы | Справочник языка Arduino | Примеры | Библиотеки | Хакинг | Изменения | Сравнение языков Arduino и Processing |
Вариация Pong на TFT-экране[1]
Этот скетч является примитивной вариацией игры Pong с использованием TFT-экрана Arduino.
В коде создается два объекта: прямоугольная платформа, способная двигаться в двух направлениях (по осям X и Y), а также мячик, способный отскакивать от этой платформы и от краев экрана. Позиция платформы управляется двумя потенциометрами (или другими аналоговыми сенсорами).
Кроме того, этот пример демонстрирует использование так называемого «обнаружения столкновений» объектов на экране, а также то, как быстро обновить изображения без необходимости стирать весь экран при каждом проходе через loop().
Необходимое оборудование
- Плата Arduino Uno;
- TFT-экран Arduino;
- Макетная плата Breadboard;
- Провода-перемычки
- Два потенциометра на 10 кОм;
Цепь
Подключите контакты с питанием и «землей» к макетной плате.
Подключите оба потенциометра к макетной плате: их боковые контакты к «земле» и питанию, а центральные – к 0-ому и 1-ому аналоговым контактам.
Подключите TFT-экран к макетной плате. Подключить его нужно той стороной, где находятся стрелочка и маленькая голубая полоска. Также обратите внимание на ориентацию экрана. На этих рисунках он подсоединен вверх тормашками.
Контакты BL и +5V подключите к питанию, а GND – к «земле». CS-LD подключите к 10-ому контакту, DC – к 9-ому, RESET – к 8-ому, MOSI – к 11-ому, а SCK – к 13-ому. В случае с Leonardo вам надо будет использовать другие контакты, читайте об этом на странице о TFT-экране или в коде ниже.
Код
Чтобы использовать экран, подключаем библиотеки SPI и TFT.
#include <SPI.h>
#include <TFT.h>
Определяем контакты, которые будут использоваться для управления экраном, а затем создаем экземпляр класса TFT под названием TFTscreen. Будем обращаться к этому объекту каждый раз при работе с экраном.
#define cs 10
#define dc 9
#define rst 8
TFT TFTscreen = TFT(cs, dc, rst);
Задаем переменные для текущих и предыдущих координат (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() {
TFTscreen.begin();
TFTscreen.background(0,0,0);
}
Секция loop() начинается с создания переменных, хранящих ширину и высоту экрана. Далее считываем данные с потенциометров и приспосабливаем их к необходимому диапазону.
void loop() {
int myWidth = TFTscreen.width();
int myHeight = TFTscreen.height();
paddleX = map(analogRead(A0), 0, 1023, 0, myWidth) - 20/2;
paddleY = map(analogRead(A1), 0, 1023, 0, myHeight) - 5/2;
Задаем фоновый цвет (черный) и стираем предыдущую позицию платформы (если она сдвинулась).
TFTscreen.fill(0,0,0);
if (oldPaddleX != paddleX || oldPaddleY != paddleY) {
TFTscreen.rect(oldPaddleX, oldPaddleY, 20, 5);
}
Делаем цвет заливки белым, а затем рисуем платформу.
TFTscreen.fill(255,255,255);
TFTscreen.rect(paddleX, paddleY, 20, 5);
Сохраняем текущую позицию платформы как предыдущую, чтобы мы могли свериться с ней при следующем проходе через цикл.
oldPaddleX = paddleX;
oldPaddleY = paddleY;
В конце блока loop() используем значение из переменной ballSpeed, чтобы определить, как быстро будет обновляться дисплей. Кроме того, разобравшись с этим примером, вы можете добавить еще один потенциометр и менять скорость обновления дисплея уже с его помощью, да еще и в реальном времени.
Для обновления позиции мяча воспользуемся пользовательской функцией moveBall().
if (millis() % ballSpeed < 2) {
moveBall();
}
}
Она работает следующим образом – просто стирает предыдущую позицию мяча, а затем рисует новую. Кроме того, в этой же функции проверяется, не вылетел ли мячик за пределы экрана, и если вылетел, то направление его полета реверсируется. Кроме того, здесь же вызывается вторая пользовательская функция этого скетча – inPaddle() – в которой проверяется, не пересекаются ли позиции мяча и платформы.
void moveBall() {
if (ballX > TFTscreen.width() || ballX < 0) {
ballDirectionX = -ballDirectionX;
}
if (ballY > TFTscreen.height() || ballY < 0) {
ballDirectionY = -ballDirectionY;
}
if (inPaddle(ballX, ballY, paddleX, paddleY, 20, 5)) {
ballDirectionY = -ballDirectionY;
}
ballX += ballDirectionX;
ballY += ballDirectionY;
TFTscreen.fill(0,0,0);
if (oldBallX != ballX || oldBallY != ballY) {
TFTscreen.rect(oldBallX, oldBallY, 5, 5);
}
TFTscreen.fill(255,255,255);
TFTscreen.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-экране Arduino
Этот пример для TFT-экрана Arduino считывает данные
от двух потенциометров, чтобы перемещать по осям X и Y
прямоугольную платформу. Эта платформа может взаимодействовать
с мячиком – ударяясь о нее, он будет отскакивать и лететь дальше.
Этот пример кода не защищен авторским правом.
Создан в декабре 2012 Томом Иго (Tom Igoe),
модифицирован 15 апреля 2013 Скоттом Фитцджеральдом (Scott Fitzgerald).
http://www.arduino.cc/en/Tutorial/TFTPong
*/
#include <TFT.h> // библиотека для TFT-экрана Arduino
#include <SPI.h>
// Определяем контакты для Arduino Uno:
#define cs 10
#define dc 9
#define rst 8
// Определяем контакты для Arduino Leonardo (раскомментируйте, чтобы использовать):
// #define cs 7
// #define dc 0
// #define rst 1
TFT TFTscreen = TFT(cs, dc, rst);
// Переменные для позиции мяча и платформы, а также для направления полета мяча:
int paddleX = 0;
int paddleY = 0;
int oldPaddleX, oldPaddleY;
int ballDirectionX = 1;
int ballDirectionY = 1;
int ballSpeed = 10; // чем ниже это число, тем быстрее скорость мячика
int ballX, ballY, oldBallX, oldBallY;
void setup() {
// Инициализируем дисплей:
TFTscreen.begin();
// Делаем экран черным:
TFTscreen.background(0, 0, 0);
}
void loop() {
// Сохраняем ширину и высоту экрана:
int myWidth = TFTscreen.width();
int myHeight = TFTscreen.height();
// Подстраиваем позицию платформы к позициям потенциометров:
paddleX = map(analogRead(A0), 512, -512, 0, myWidth) - 20 / 2;
paddleY = map(analogRead(A1), 512, -512, 0, myHeight) - 5 / 2;
// Делаем цвет заливки черным и стираем предыдущую позицию платформы,
// если ее новые координаты отличаются от предыдущих:
TFTscreen.fill(0, 0, 0);
if (oldPaddleX != paddleX || oldPaddleY != paddleY) {
TFTscreen.rect(oldPaddleX, oldPaddleY, 20, 5);
}
// Рисуем платформу и сохраняем ее текущие координаты как предыдущие:
TFTscreen.fill(255, 255, 255);
TFTscreen.rect(paddleX, paddleY, 20, 5);
oldPaddleX = paddleX;
oldPaddleY = paddleY;
// Обновляем позицию мяча и рисуем его на экране:
if (millis() % ballSpeed < 2) {
moveBall();
}
}
// Эта функция определяет позицию мяча на экране:
void moveBall() {
// Если мячик улетает за пределы экрана, реверсируем направление его полета:
if (ballX > TFTscreen.width() || ballX < 0) {
ballDirectionX = -ballDirectionX;
}
if (ballY > TFTscreen.height() || ballY < 0) {
ballDirectionY = -ballDirectionY;
}
// Проверяем, не занимают ли мячик и платформа одно и то же место на экране:
if (inPaddle(ballX, ballY, paddleX, paddleY, 20, 5)) {
ballDirectionX = -ballDirectionX;
ballDirectionY = -ballDirectionY;
}
// Обновляем позицию мяча:
ballX += ballDirectionX;
ballY += ballDirectionY;
// Стираем предыдущую позицию мяча:
TFTscreen.fill(0, 0, 0);
if (oldBallX != ballX || oldBallY != ballY) {
TFTscreen.rect(oldBallX, oldBallY, 5, 5);
}
// Рисуем текущую позицию мяча:
TFTscreen.fill(255, 255, 255);
TFTscreen.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;
}
См.также
Внешние ссылки
Arduino продукты | |
---|---|
Начальный уровень | Arduino Uno • Arduino Leonardo • Arduino 101 • Arduino Robot • Arduino Esplora • Arduino Micro • Arduino Nano • Arduino Mini • Arduino Starter Kit • Arduino Basic Kit • MKR2UNO • TFT-дисплей Arduino |
Продвинутые функции | Arduino Mega 2560 • Arduino Zero • Arduino Due • Arduino Mega ADK • Arduino Pro • Arduino Motor Shield • Arduino USB Host Shield • Arduino Proto Shield • MKR Proto Shield • MKR Proto Large Shield • Arduino ISP • Arduino USB 2 Serial Micro • Arduino Mini USB Serial Adapter |
Интернет вещей | Arduino Yun • Arduino Ethernet • Arduino MKR1000 • Arduino WiFi 101 Shield • Arduino GSM Shield V2 • Arduino WiFi Shield • Arduino Wireless SD Shield • Arduino Wireless Proto Shield • Arduino Ethernet Shield V2 • Arduino Yun Shield • Arduino MKR1000 Bundle |
Носимые устройства | Arduino Gemma • Lilypad Arduino Simple • Lilypad Arduino Main Board • Lilypad Arduino USB • LilyPad Arduino SimpleSnap |
3D-печать | Arduino Materia 101 |
Устаревшие устройства | - |
Примеры Arduino | |
---|---|
Стандартные функции | |
Основы |
|
Цифровой сигнал |
|
Аналоговый сигнал |
|
Связь |
|
Управляющие структуры |
|
Датчики |
|
Дисплей |
Примеры, объясняющие основы управления дисплеем:
|
Строки |
|
USB (для Leonardo, Micro и Due плат) |
В этой секции имеют место примеры, которые демонстрируют использование библиотек, уникальных для плат Leonardo, Micro и Due.
|
Клавиатура |
|
Мышь |
|
Разное |