在ESP32开发板上开发贪吃蛇游戏

在ESP32上开发贪吃蛇游戏需要使用LED矩阵作为显示器。

控制杠(Joystick)等外设可以提供给用户更好的游戏体验,但并非必须。

以下是一个基本的贪吃蛇游戏的代码示例,使用了LED矩阵作为显示器,并通过控制杠来控制蛇的移动。

#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

#define JOY_X_PIN 34
#define JOY_Y_PIN 35
#define JOY_BTN_PIN 5

#define MATRIX_PIN 27
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_PIN, NEO_GRB + NEO_KHZ800);

typedef struct {
  int x;
  int y;
} coord;

enum direction {
  DIR_UP,
  DIR_DOWN,
  DIR_LEFT,
  DIR_RIGHT
};

const int SNAKE_MAX_LEN = 64;
coord snake[SNAKE_MAX_LEN];
direction dir = DIR_RIGHT;
int snake_len = 3;
bool game_over = false;
int score = 0;

const int FOOD_SCORE = 10;
const int MOVE_DELAY = 100;
const int MIN_DELAY = 50;

coord food;

void setup() {
  Serial.begin(115200);

  pinMode(JOY_X_PIN, INPUT);
  pinMode(JOY_Y_PIN, INPUT);
  pinMode(JOY_BTN_PIN, INPUT_PULLUP);

  matrix.begin();
  matrix.setBrightness(20);

  randomSeed(analogRead(0));

  // Initialize snake
  snake[0].x = 0;
  snake[0].y = 0;
  for (int i = 1; i < snake_len; i++) {
    snake[i].x = snake[i-1].x + 1;
    snake[i].y = snake[i-1].y;
  }

  // Place food
  place_food();
}

void loop() {
  // Move snake
  move();

  // Check for game over
  check_game_over();

  // Draw game board
  draw();

  // Delay for move delay
  delay(get_delay());
}

void move() {
  coord new_head;
  new_head.x = snake[snake_len-1].x;
  new_head.y = snake[snake_len-1].y;

  int x = analogRead(JOY_X_PIN);
  int y = analogRead(JOY_Y_PIN);
  if (x > 900) {
    dir = DIR_RIGHT;
  } else if (x < 100) {
    dir = DIR_LEFT;
  } else if (y > 900) {
    dir = DIR_DOWN;
  } else if (y < 100) {
    dir = DIR_UP;
  }

  switch (dir) {
    case DIR_UP:
      new_head.y--;
      break;
    case DIR_DOWN:
      new_head.y++;
      break;
    case DIR_LEFT:
      new_head.x--;
      break;
    case DIR_RIGHT:
      new_head.x++;
      break;
  }

  // Move snake body
  for (int i = 0; i < snake_len - 1; i++) {
    snake[i].x = snake[i+1].x;
    snake[i].y = snake[i+1].y;
  }

  // Move snake head
  snake[snake_len-1].x = new_head.x;
  snake[snake_len-1].y = new_head.y;

  // Check for food
  if (snake[snake_len-1].x == food.x && snake[snake_len-1].y == food.y) {
    snake_len++;
    score += FOOD_SCORE;
    place_food();
  }
}

void place_food() {
  food.x = random(0, MATRIX_WIDTH);
  food.y = random(0, MATRIX_HEIGHT);
}

int get_delay() {
  int delay = MOVE_DELAY - score;
  if (delay < MIN_DELAY) {
    delay = MIN_DELAY;
  }
  return delay;
}

void draw() {
  matrix.fillScreen(0);

  // Draw food
  matrix.drawPixel(food.x, food.y, matrix.Color(255, 0, 0));

  // Draw snake
  for (int i = 0; i < snake_len; i++) {
    matrix.drawPixel(snake[i].x, snake[i].y, matrix.Color(255, 255, 255));
  }

  matrix.show();
}

void check_game_over() {
  // Check for hitting edges
  if (snake[snake_len-1].x < 0 || snake[snake_len-1].x >= MATRIX_WIDTH ||
      snake[snake_len-1].y < 0 || snake[snake_len-1].y >= MATRIX_HEIGHT) {
    game_over = true;
    return;
  }

  // Check for hitting self
  for (int i = 0; i < snake_len - 1; i++) {
    if (snake[i].x == snake[snake_len-1].x && snake[i].y == snake[snake_len-1].y) {
      game_over = true;
      return;
    }
  }
}

这个代码示例使用了Adafruit_GFX、Adafruit_NeoMatrix和Adafruit_NeoPixel库,在Arduino IDE中安装这些库即可运行代码。此外,JOY_X_PIN和JOY_Y_PIN分别使用了ESP32开发板的34和35号引脚,需要在开发板上连接相应的控制杠。MATRIX_PIN是用于连接LED矩阵的引脚。

在这个例子中,通过读取控制杠的x和y值来判断蛇应该移动的方向。其中,当x值大于900时,表示向右移动,当x值小于100时,表示向左移动,当y值大于900时,表示向下移动,当y值小于100时,表示向上移动。

在每次移动之后,检查是否吃到了食物。如果蛇的头部在食物的位置上,则将蛇的长度加一,并重新放置食物。每次移动后,都会检查是否撞墙或撞自己,如果是则游戏结束。

该示例中的控制杠可能需要进行一些微调,以适应不同的硬件。

Leave a Comment

豫ICP备19001387号-1