在esp32上实现flappy bird

此篇文章在2022年2月12日被记录

看到B站很多大佬都在单片机上运行flappy bird小游戏,自己也想试一试,顺便提升自己的编程思路!

开发平台:platform平台(不得不说这是一个好东西)+Arduino框架

硬件:ESP32、ILI9341

编程思路:

  • 新建水管结构体,包含水管参数与水管更新删除函数:
    struct Tube //管子结构体
    {
      int point;
      int last_point;
      int hole;
      int hole_h;
      void Init(int a, int b, int c)
      {
        point = a;
        last_point = point;
        hole = b;
        hole_h = c;
      }
      void refresh() //绘制管子        在这里绘制管子是先用背景色覆盖上一次的,在绘制多余的管子部分
      {
    
        tft.fillRoundRect(0, point, hole - 10, TUBE_SPEED, 4, TUBE_COLOR);
        tft.fillRoundRect(hole + hole_h + 10, point, 240 - hole - hole_h - 10, TUBE_SPEED, 4, TUBE_COLOR); //绘制管子
        tft.fillRoundRect(hole - 10, point - 10, 10, 10, 4, TUBE_COLOR); //绘制管子边缘凸出部分
        tft.fillRoundRect(hole + hole_h, point - 10, 10, 10, 4, TUBE_COLOR);
        tft.fillRoundRect(hole - 10, point + TUBE_WIDTH + 6, 10, 7, 4, TUBE_COLOR); //绘制右边突出部分的圆角
        tft.fillRoundRect(hole + hole_h, point + TUBE_WIDTH + 6, 10, 7, 4, TUBE_COLOR);
      }
      void delet() //删除管子
      {
    
        tft.fillRect(0, last_point + TUBE_WIDTH, hole - 10, TUBE_SPEED, COLOR_BK);
        tft.fillRect(hole + hole_h + 10, last_point + TUBE_WIDTH, 240 - hole - hole_h - 10, TUBE_SPEED, COLOR_BK); //删除管子
        tft.fillRect(hole - 10, last_point + TUBE_WIDTH + 6, 10, 10, COLOR_BK); //删除管子边缘突出部分
        tft.fillRect(hole + hole_h, last_point + TUBE_WIDTH + 6, 10, 10, COLOR_BK);
      }
    };
  • 小鸟结构体,包含小鸟的信息与图片更新删除函数
    struct Bird //小鸟结构体
    {
    
      int g, v, point, last_point;
      void refresh() //更新小鸟数据
      {
        v += g;
        v = constrain(v, -5, 5);
        point += v;
        point = constrain(point, 0, 240);
        if (point == 0)
        {
          v = 0;
        }
    
        if (v > 0) // 小鸟上升和下降的图片不一样的
          tft.drawXBitmap(point, 50, pic1, pic_w, pic_w, bird_color);
        else
          tft.drawXBitmap(point, 50, pic2, pic_w, pic_w, bird_color);
    
        tft.drawNumber(score, point, 20);
        last_point = point;
      }
    
      void delet()
      {
    
        tft.fillRect(last_point, 50, 32, 32, COLOR_BK);
        int black;
        if (score < 10)
          black = 10;
        else if (score >= 10)
          black = 25;
        else
          black = 60;
        tft.fillRect(last_point, 20, black, 20, COLOR_BK); //抹去上一次的图像
      }
    };
  • 绘制管子:
    void protract_tube(void) //绘制管子
    {
      for (int i = 0; i < TUBE_NUM; i++)
      {
        tube[i].refresh();
        tube[i].last_point = tube[i].point;
        tube[i].point -= TUBE_SPEED;
        if (tube[i].point < -40) //管子走到头了
        {
          tube[i].point = 300;
          tube[i].hole = random(30, 100);
          tube[i].hole_h = random(80, 100);
          tft.fillRect(0, 0, 240, 20, COLOR_BK);
          score++;
        }
      }
    }
  • 删除管子:
    void cover_tube(void) //黑色覆盖管子
    {
      for (int i = 0; i < TUBE_NUM; i++)
        tube[i].delet();
    }
  • 定时器回调函数,这个函数中更新小鸟与管子:
    void tim1Interrupt() //定时器回调函数
    {
      if (tim1_tube++ > (TUBE_REFRESH_TIME)) //到时间了,可以进行更新了
      {
        tim1_tube = 0;
        if (!game_over)
        {
          cover_tube();
          protract_tube();
        }
      }
      if (tim1_bird++ > (BIRD_REFRESH_TIME))
      {
        tim1_bird = 0;
        if (!game_over)
        {
          game_over = knock_detect();
          bird.delet();
          bird.refresh();
        }
      }
    }
  • 按键向上运动函数以及重生:
    void handle_key1() //按键中断函数
    {
      if (digitalRead(key1) == 0)
      {
        delay(10);//按键消抖
        if (digitalRead(key1) == 0)
        {
          bird.v = 5;
          if (game_over) //进行下一次游戏,并且给管子小鸟赋初值
          {        
            tft.fillScreen(COLOR_BK);
            score = 0;
            game_over = 0;
            bird.v = 0;
            bird.point = 80;
            tube[0].Init(300, 50, 120);
            tube[1].Init(150, 50, 120);
    
          }
        }
      }
    }
  • 碰撞检测,小鸟死亡变成红色:
    bool knock_detect(void) //碰撞检测
    {
      int bird_top = bird.point + 28;
      int bird_btm = bird.point;
      int bird_left = 50;
      int bird_right = 78;
      for (int i = 0; i < 2; i++)
      {
        if ((tube[i].point <= bird_right) && ((tube[i].point + TUBE_WIDTH) >= bird_right) || (((tube[i].point + TUBE_WIDTH) > bird_left) && (tube[i].point + TUBE_WIDTH) < bird_right))
        {
          if (bird_btm < tube[i].hole || bird_top > (tube[i].hole + tube[i].hole_h))
          {
            bird_color = TFT_RED;
            draw_over_page = 1;
            return 1;
          }
        }
      }
      bird_color = TFT_YELLOW;
      return 0;
    }

剩下的就是一些初始化等等啦~~~

演示视频:

posted @ 2024-12-06 17:05  shumei52  阅读(45)  评论(0)    收藏  举报