#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_MPU6050.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define MPU6050_ADDR 0x68
Adafruit_MPU6050 mpu;
float ax, ay, az;
float gx, gy, gz;
const int BLOCK_SIZE = 8;
const int GAME_WIDTH = 128;
const int GAME_HEIGHT = 32;
const int MAX_SNAKE_LENGTH = 20;
int snakeX[MAX_SNAKE_LENGTH] = {GAME_WIDTH / 2, GAME_WIDTH / 2, GAME_WIDTH / 2};
int snakeY[MAX_SNAKE_LENGTH] = {GAME_HEIGHT / 2 + BLOCK_SIZE, GAME_HEIGHT / 2, GAME_HEIGHT / 2 - BLOCK_SIZE};
const int INITIAL_SNAKE_LENGTH = 3;
int snakeLength = INITIAL_SNAKE_LENGTH;
int snakeDir = 0; // 0: right, 1: down, 2: left, 3: up
int foodX = BLOCK_SIZE * (random(1, GAME_WIDTH / BLOCK_SIZE - 1));
int foodY = BLOCK_SIZE * (random(1, GAME_HEIGHT / BLOCK_SIZE - 1));
bool gameOver = false;
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.display();
Serial.begin(9600); // 初始化串口通信,波特率为 9600
Wire.begin();
mpu.begin(MPU6050_ADDR);
}
void loop() {
// 读取MPU6050的加速度和角速度信息
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
ax = a.acceleration.x;
ay = a.acceleration.y;
az = a.acceleration.z;
gx = g.gyro.x;
gy = g.gyro.y;
gz = g.gyro.z;
// 输出数据到串口监视器
Serial.print("ax = ");
Serial.print(ax);
Serial.print(", ay = ");
Serial.print(ay);
Serial.print(", az = ");
Serial.print(az);
Serial.print(", gx = ");
Serial.print(gx);
Serial.print(", gy = ");
Serial.print(gy);
Serial.print(", gz = ");
Serial.println(gz);
// 根据加速度信息,更新蛇的移动方向
if (ax < -5) {
snakeDir = 2; // 向左
} else if (ax > 5) {
snakeDir = 0; // 向右
} else if (ay < -5) {
snakeDir = 3; // 向上
} else if (ay > 5) {
snakeDir = 1; // 向下
}
// 执行蛇的移动操作
moveSnake();
// 检测游戏是否结束,是否吃到食物
checkGameStatus();
// 绘制游戏界面
drawGameScreen();
}
void moveSnake() {
// 移动蛇头
int headX = snakeX[0];
int headY = snakeY[0];
if (snakeDir == 0) { // 向右
headX += BLOCK_SIZE;
} else if (snakeDir == 1) { // 向下
headY += BLOCK_SIZE;
} else if (snakeDir == 2) { // 向左
headX -= BLOCK_SIZE;
} else if (snakeDir == 3) { // 向上
headY -= BLOCK_SIZE;
}
// 检测蛇是否吃到了食物
bool eatFood = false;
if (headX == foodX && headY == foodY) {
eatFood = true;
foodX = BLOCK_SIZE * (random(1, GAME_WIDTH / BLOCK_SIZE - 1));
foodY = BLOCK_SIZE * (random(1, GAME_HEIGHT / BLOCK_SIZE - 1));
}
// 更新蛇的身体状态
for (int i = snakeLength - 1; i > 0; i--) {
snakeX[i] = snakeX[i-1];
snakeY[i] = snakeY[i-1];
}
snakeX[0] = headX;
snakeY[0] = headY;
// 如果蛇吃到了食物,则增加蛇的长度
if (eatFood) {
snakeX[snakeLength] = snakeX[snakeLength - 1];
snakeY[snakeLength] = snakeY[snakeLength - 1];
snakeLength++;
}
}
void checkGameStatus() {
// 检测蛇是否碰到边界或自身
if (snakeX[0] < 0 || snakeX[0] >= GAME_WIDTH
|| snakeY[0] < 0 || snakeY[0] >= GAME_HEIGHT) {
gameOver = true;
}
for (int i = 1; i < snakeLength; i++) {
if (snakeX[i] == snakeX[0] && snakeY[i] == snakeY[0]) {
gameOver = true;
}
}
}
void drawGameScreen() {
// 清空屏幕
display.clearDisplay();
// 绘制蛇和食物
display.fillCircle(snakeX[0], snakeY[0], BLOCK_SIZE / 2, SSD1306_WHITE);
for (int i = 1; i < snakeLength; i++) {
display.fillRect(snakeX[i] - BLOCK_SIZE / 2, snakeY[i] - BLOCK_SIZE / 2,
BLOCK_SIZE, BLOCK_SIZE, SSD1306_WHITE);
}
display.fillCircle(foodX, foodY, BLOCK_SIZE / 2, SSD1306_WHITE);
// 绘制游戏结束提示
if (gameOver) {
display.setCursor(8, 24);
display.println("Game Over!");
display.display();
delay(2000);
// 重置游戏状态
snakeDir = 0;
snakeLength = INITIAL_SNAKE_LENGTH;
snakeX[0] = GAME_WIDTH / 2;
snakeY[0] = GAME_HEIGHT / 2 + BLOCK_SIZE;
snakeX[1] = GAME_WIDTH / 2;
snakeY[1] = GAME_HEIGHT / 2;
snakeX[2] = GAME_WIDTH / 2;
snakeY[2] = GAME_HEIGHT / 2 - BLOCK_SIZE;
foodX = BLOCK_SIZE * (random(1, GAME_WIDTH / BLOCK_SIZE - 1));
foodY = BLOCK_SIZE * (random(1, GAME_HEIGHT / BLOCK_SIZE - 1));
gameOver = false;
}
// 显示屏幕内容
display.display();
}