#include <TFT_eSPI.h>
#include <SPI.h>
#include <EEPROM.h>
TFT_eSPI tft = TFT_eSPI();
const int buttonPin = 5; // 按钮连接到GPIO5
int score = 0;
int misses = 0;
int blueCircleIndex = -1;
int highScore = 0;
bool buttonWasPressed = false;
const int angles[] = {0, 60, 120, 180, 240, 300};
int direction = 1; // 初始方向:顺时针
unsigned long speedInterval = 100; // 初始速度间隔
unsigned long preTime = 0;
int angle = 0;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
Serial.begin(115200);
tft.init();
tft.fillScreen(TFT_BLACK);
// 读取EEPROM中的历史最高分
EEPROM.begin(512);
if (EEPROM.read(0) != 1) { // 如果标志位不为1,说明未初始化
highScore = 0;
EEPROM.write(0, 1); // 设置标志位为1
EEPROM.write(1, highScore & 0xFF);
EEPROM.write(2, (highScore >> 8) & 0xFF);
EEPROM.commit();
} else {
highScore = EEPROM.read(1) + (EEPROM.read(2) << 8);
}
drawBackground();
startGame();
}
void loop() {
unsigned long currentTime = millis();
// 更新黄点位置和速度
if (currentTime - preTime >= speedInterval) {
restoreBackgroundCircle(120 + 65 * cos(angle * PI / 180), 120 + 65 * sin(angle * PI / 180), 11);
angle += 5 * direction;
if (angle >= 360) {
angle -= 360;
} else if (angle < 0) {
angle += 360;
}
tft.fillCircle(120 + 65 * cos(angle * PI / 180), 120 + 65 * sin(angle * PI / 180), 10, TFT_YELLOW);
preTime = currentTime;
}
int yellowX = 120 + 65 * cos(angle * PI / 180);
int yellowY = 120 + 65 * sin(angle * PI / 180);
int blueX = 120 + 65 * cos(angles[blueCircleIndex] * PI / 180);
int blueY = 120 + 65 * sin(angles[blueCircleIndex] * PI / 180);
// 先判断黄色圆圈和蓝色圆圈是否重叠
bool circlesOverlap = (abs(yellowX - blueX) < 10 && abs(yellowY - blueY) < 10);
// 检查按钮按下情况
if (digitalRead(buttonPin) == LOW && !buttonWasPressed) {
if (circlesOverlap) {
score++;
Serial.print("Score: ");
Serial.println(score);
// 改变方向
direction = -direction;
// 增加速度
if (score == 5 || score == 10 || score == 15 || score == 20) {
speedInterval -= 20; // 速度加快
}
// 清除当前蓝色圆位置
restoreBackgroundCircle(blueX, blueY, 12);
// 随机生成新的蓝色圆位置,确保不重复
int newBlueCircleIndex;
do {
newBlueCircleIndex = random(0, 6);
} while (newBlueCircleIndex == blueCircleIndex);
blueCircleIndex = newBlueCircleIndex;
drawBlueCircle();
// 更新得分显示
displayScore();
// 更新和显示最高分
if (score > highScore) {
highScore = score;
EEPROM.write(1, highScore & 0xFF);
EEPROM.write(2, (highScore >> 8) & 0xFF);
EEPROM.commit();
displayHighScore();
}
} else {
misses++;
Serial.print("Misses: ");
Serial.println(misses);
// 更新MISS值显示
displayMisses();
if (misses >= 3) {
// 显示GAME OVER
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_RED);
tft.setTextSize(3);
tft.setCursor(20, 90);
tft.print("GAME OVER");
tft.setCursor(20, 150);
tft.setTextSize(2);
tft.print("Press to Restart");
while (true) {
// 检查重新开始按钮按下情况
if (digitalRead(buttonPin) == LOW && !buttonWasPressed) {
buttonWasPressed = true;
resetGame();
break;
} else if (digitalRead(buttonPin) == HIGH) {
buttonWasPressed = false;
}
}
}
}
buttonWasPressed = true; // 按钮状态设置为已按下
} else if (digitalRead(buttonPin) == HIGH && circlesOverlap == false) {
buttonWasPressed = false; // 按钮释放,重置按钮状态
restoreBackgroundCircle(blueX, blueY, 12);
drawBlueCircle();
}
delay(50); // 消抖动
}
void drawBackground() {
tft.fillCircle(120, 120, 70, TFT_WHITE);
tft.fillCircle(120, 120, 60, TFT_BLACK);
// 预留得分显示区域
tft.fillRect(0, 240 - 30, 240, 30, TFT_BLACK);
}
void restoreBackgroundCircle(int x, int y, int r) {
for (int i = -r; i <= r; i++) {
for (int j = -r; j <= r; j++) {
if (i * i + j * j <= r * r) {
int dist = (x + i - 120) * (x + i - 120) + (y + j - 120) * (y + j - 120);
if (dist >= 60 * 60 && dist <= 70 * 70) {
tft.drawPixel(x + i, y + j, TFT_WHITE);
} else {
tft.drawPixel(x + i, y + j, TFT_BLACK);
}
}
}
}
}
void drawBlueCircle() {
int blueX = 120 + 65 * cos(angles[blueCircleIndex] * PI / 180);
int blueY = 120 + 65 * sin(angles[blueCircleIndex] * PI / 180);
// 绘制外圆
tft.drawCircle(blueX, blueY, 12, TFT_BLUE);
// 绘制内圆
tft.drawCircle(blueX, blueY, 10, TFT_BLACK);
}
void displayScore() {
tft.fillRect(0, 240 - 30, 120, 30, TFT_BLACK); // 清除之前的得分显示
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
tft.setCursor(10, 240 - 24);
tft.print("Score: ");
tft.print(score);
}
void displayMisses() {
tft.fillRect(120, 240 - 30, 120, 30, TFT_BLACK); // 清除之前的MISS值显示
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
tft.setCursor(130, 240 - 24);
tft.print("Misses: ");
tft.print(misses);
}
void displayHighScore() {
tft.fillRect(0, 0, 240, 30, TFT_BLACK); // 清除之前的最高分显示
tft.setTextColor(TFT_WHITE);
tft.setTextSize(2);
tft.setCursor(10, 6);
tft.print("High Score: ");
tft.print(highScore);
}
void startGame() {
score = 0;
misses = 0;
angle = 0;
direction = 1;
speedInterval = 100;
randomSeed(analogRead(0));
blueCircleIndex = random(0, 6);
drawBlueCircle();
displayScore();
displayMisses();
displayHighScore();
}
void resetGame() {
tft.fillScreen(TFT_BLACK);
drawBackground();
startGame();
}