#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include "yandexRover.h"
#include <SPI.h>
#define TFT_DC 21
#define TFT_CS 22
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// --- Размер спрайта ---
const int SPR_W = 50;
const int SPR_H = 50;
const int JOY_X = 33; // VRx (ADC)
const int JOY_Y = 32; // VRy (ADC)
const int LOW_TH = 1200; // «влево/вверх»
const int HIGH_TH = 2800; // «вправо/вниз»
const int STEP = 4; // шаг в пикселях
int16_t x, y; // текущая позиция
int16_t px, py; // предыдущая позиция
int16_t maxX, maxY;
uint16_t BG = ILI9341_BLACK;
static inline void drawSpriteAt(int16_t x0, int16_t y0, const uint16_t* data565) {
tft.drawRGBBitmap(x0, y0, data565, SPR_W, SPR_H);
}
static inline void eraseRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
if (w > 0 && h > 0) tft.fillRect(x, y, w, h, color);
}
// Хелпер: рисуем новый, стираем только «лишние» куски старого
void blitNoFlicker(int16_t newCx, int16_t newCy, int16_t oldCx, int16_t oldCy,
const uint16_t* spr, uint16_t bg) {
int16_t nw = SPR_W, nh = SPR_H;
int16_t nx = newCx - SPR_W/2, ny = newCy - SPR_H/2;
int16_t ow = SPR_W, oh = SPR_H;
int16_t ox = oldCx - SPR_W/2, oy = oldCy - SPR_H/2;
// 1) сначала рисуем новый спрайт
drawSpriteAt(nx, ny, spr);
// 2) считаем пересечение старого и нового
int16_t ix = max(nx, ox);
int16_t iy = max(ny, oy);
int16_t ix2 = min(nx + nw, ox + ow);
int16_t iy2 = min(ny + nh, oy + oh);
int16_t iw = ix2 - ix;
int16_t ih = iy2 - iy;
// 3) стираем ТОЛЬКО ту часть старого прямоугольника, которая не перекрыта новым
// верхняя полоска
eraseRect(ox, oy, ow, max(0, iy - oy), bg);
// нижняя полоска
eraseRect(ox, iy2, ow, max(0, (oy + oh) - iy2), bg);
// левая полоска
eraseRect(ox, iy, max(0, ix - ox), max(0, ih), bg);
// правая полоска
eraseRect(ix2, iy, max(0, (ox + ow) - ix2), max(0, ih), bg);
}
const uint16_t* sprite565 = (const uint16_t*)yandexRover_map;
void setup() {
Serial.begin(115200);
Serial.println("Start");
tft.begin();
SPI.begin();
SPI.setFrequency(40000000); // быстрее заливка
tft.setRotation(1);
tft.fillScreen(BG);
maxX = tft.width() - 1;
maxY = tft.height() - 1;
x = px = maxX / 2 - STEP;
y = py = maxY / 2 - STEP;
blitNoFlicker(x, y, x, y, sprite565, BG);
}
int max(int value1, int value2) {
if (value1>value2) return value1;
return value2;
}
int min(int value1, int value2) {
if (value1<value2) return value1;
return value2;
}
void loop() {
int horz = analogRead(JOY_X); // вправо растёт
int vert = analogRead(JOY_Y); // вниз растёт
// сохранить прошлую позицию
px = x; py = y;
if (vert > HIGH_TH) y = max(y - STEP, STEP/2);
if (vert < LOW_TH) y = min(y + STEP, maxY - STEP/2);
if (horz > HIGH_TH) x = max(x - STEP, STEP/2);
if (horz < LOW_TH) x = min(x + STEP, maxX - STEP/2);
// перерисовать без следа
if (x != px || y != py) {
blitNoFlicker(x, y, px, py, sprite565, BG);
}
delay(100);
}