arduino uno+LCD12864(ST7735S)+蓝牙模块实现贪吃蛇

1.前言:

1.1本实验实现的贪吃蛇能穿越边界,结束游戏的唯一条件是贪吃蛇到达指定长度

1.2本实验所用LCD可能不是LCD12864,LCD12864所用库为u8glib,笔者在词库中并没有找到型号为ST77355的初始化函数,而是在ucglib中找到,其方法为
Ucglib_ST7735_18x128x160_SWSPI ucg(/*sclk=*/13, /*data=*/11, /*cd=*/9, /*cs=*/10, /*reset=*/8);

1.3代码由学长LCD1602修改而来
2.接线方式

蓝牙模块 RXD TXD GND VCC
Arduino uno pin7 pin6 5v GND
ST7735S模块 BLK CS DC RST SDA SCL VDD VCC
Arduino uno 3.3v pin10 pin9 pin8 pin11 pin13 未接 GND

3.话不多说上代码
点击查看代码

#include <SoftwareSerial.h>
#include <SPI.h>
#include "Ucglib.h"
#define maxlength 4 //蛇最大长度
Ucglib_ST7735_18x128x160_SWSPI ucg(/*sclk=*/13, /*data=*/11, /*cd=*/9, /*cs=*/10, /*reset=*/8);
SoftwareSerial BT(6, 7);
char val;//蓝牙接收字符
int snake_length = 1;//蛇目前长度
int snake_x[maxlength], snake_y[maxlength];
int direction = 6;//方向判断和闪屏控制
int x = 10;
int y = 10;//记录变化的位置
int food_x;
int food_y;//食物
int gameOver = 0;//结束条件
void setup(void) {
  //delay(1000);
  ucg.begin(UCG_FONT_MODE_TRANSPARENT);
  //ucg.begin(UCG_FONT_MODE_SOLID);
  ucg.clearScreen();
  BT.begin(9600);
  snake_x[0] = 10;
  snake_y[0] = 10;
  food_x = 10 + 10 * random(0, 9);
  food_y = 10 + 10 * random(0, 9);
}

void loop(void) {
  if (direction == 6) {//欢迎界面
    ucg.setFont(ucg_font_ncenR12_tr);//字体设置
    ucg.setPrintPos(40, 80);//设定显示坐标
    ucg.print("welcome");
  } else
    ucg.drawFrame(10, 10, 100, 100);//游戏区域,有没有无所谓
  if (BT.available()) {
    val = BT.read();
    if (val == 'w' && direction != 2) direction = 0;
    if (val == 's' && direction != 0) direction = 2;
    if (val == 'a' && direction != 1) direction = 3;
    if (val == 'd' && direction != 3) direction = 1;
  }
  if (direction == 0) y -= 10;  //w
  if (direction == 1) x += 10;  //d
  if (direction == 2) y += 10;  //s
  if (direction == 3) x -= 10;  //a

  if (x < 10) x = 100;
  if (x > 100) x = 10;
  if (y < 10) y = 100;
  if (y > 100) y = 10;//到达边界后穿过边界

  if (x == food_x && y == food_y) {//行动后吃到食物
    snake_length++;
    while (1) {
      int flag = 1;//跳出循环标志
      food_x = 10 + 10 * random(0, 9);
      food_y = 10 + 10 * random(0, 9);//重新生成一个食物

      for (int i = snake_length - 1; i >= 0; i--) {//遍历蛇身看食物是否生成在身上
        if ((food_x == snake_x[i]) && (food_y == snake_y[i]) || ((food_x == x) && (food_y == y))) {
          flag = 0;
          break;
        }
      }
      if (snake_length == maxlength) {//游戏结束条件
        gameOver = 1;
        direction=5;//结束后显示gameover时的闪屏控制
        break;
      }
      if (flag) break;
    }
  }

  if (direction != 6) {
    for (int i = snake_length - 1; i > 0; i--) {
      snake_x[i] = snake_x[i - 1];
      snake_y[i] = snake_y[i - 1];
    }
    snake_x[0] = x;
    snake_y[0] = y;
    if (gameOver) {
      if(direction==5){
        ucg.clearScreen();
        direction=1;
      }
      else{
        ucg.setFont(ucg_font_ncenR12_tr);
        ucg.setPrintPos(40, 80);
        ucg.print("gameover");
      }
      
    }
    if (!gameOver) {
      ucg.clearScreen();
      for (int i = 0; i < snake_length; i++) {
        ucg.drawFrame(snake_x[i], snake_y[i], 10, 10);
      }
      ucg.drawFrame(food_x, food_y, 10, 10);
    }
  }
}

4.来人上图

再上

还上

使用手机app蓝牙串口调试,发送wasd,对应上左下右

5.回顾(复习看)

头文件:<SoftwareSerial.h>、 <Ucglib.h> 、<stdio.h>

5.1LCD相关函数

LCD初始化
Ucglib_ST7735_18x128x160_SWSPI ucg(/*sclk=*/13, /*data=*/11, /*cd=*/9, /*cs=*/10, /*reset=*/8);

显示矩形,其左上角坐标为(snake_x[i], snake_y[i]),长度和宽度为10
ucg.drawFrame(snake_x[i], snake_y[i], 10, 10);

显示像素点,其坐标坐标为(x,y)
ucg.drawPixel(x,y)

清屏
ucg.clearScreen();

初始化,两者区别不知道
ucg.begin(UCG_FONT_MODE_TRANSPARENT); //ucg.begin(UCG_FONT_MODE_SOLID);

字体、显示坐标、显示函数
ucg.setFont(ucg_font_ncenR12_tr); ucg.setPrintPos(40, 80); ucg.print("welcome");

5.2蓝牙相关函数
SoftwareSerial BT(6, 7);

读app发来的信息
if (BT.available()) char val = BT.read();

6.说明

如有同道中人,请删去注释