#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
// --- TFT pins ---
#define TFT_CS 5
#define TFT_DC 2
#define TFT_RST 4
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// --- Joystick pins ---
#define JOY_X 34 // horizontal axis
#define JOY_Y 35 // vertical axis
#define JOY_BTN 16 // button
// --- Cursor & Target ---
int cursorX = 120;
int cursorY = 160;
int targetX, targetY, targetR = 20;
int score = 0;
void newTarget() {
targetX = random(40, tft.width() - 40);
targetY = random(80, tft.height() - 40);
}
void drawScene() {
tft.fillScreen(ILI9341_BLACK);
// Score
tft.setTextColor(ILI9341_WHITE);
tft.setCursor(10, 10);
tft.print("Score: ");
tft.print(score);
// Target
tft.fillCircle(targetX, targetY, targetR, ILI9341_RED);
}
void setup() {
Serial.begin(115200);
tft.begin();
tft.setRotation(0); // portrait mode
pinMode(JOY_BTN, INPUT_PULLUP);
randomSeed(analogRead(0));
newTarget();
drawScene();
}
void loop() {
int rawX = analogRead(JOY_X);
int rawY = analogRead(JOY_Y);
// Deadzone around center
int deadzone = 300;
// Erase old cursor
tft.fillCircle(cursorX, cursorY, 5, ILI9341_BLACK);
// --- Mouse-like movement ---
// Horizontal axis (fixed inversion)
if (rawX < 2048 - deadzone) cursorX += 3; // move left
if (rawX > 2048 + deadzone) cursorX -= 3; // move right
// Vertical axis (already corrected)
if (rawY < 2048 - deadzone) cursorY += 3; // move up
if (rawY > 2048 + deadzone) cursorY -= 3; // move down
// Clamp to screen bounds
cursorX = constrain(cursorX, 0, tft.width()-1);
cursorY = constrain(cursorY, 0, tft.height()-1);
// Draw cursor
tft.fillCircle(cursorX, cursorY, 5, ILI9341_WHITE);
// Button press = click
if (digitalRead(JOY_BTN) == LOW) {
int dx = cursorX - targetX;
int dy = cursorY - targetY;
if (dx*dx + dy*dy <= targetR*targetR) {
score++;
newTarget();
drawScene();
}
delay(200); // debounce
}
delay(30);
}