在單片機上寫遊戲 esp32 flappy bird

【自制】單片機也能玩遊戲。up在esp32上寫了個flappy bird(box)

csdn:https://blog.csdn.net/zhong1213/article/details/105781758

個人博客:https://hanbaoaaa.xyz/index.php/archives/65/k.html

視頻地址:https://www.bilibili.com/video/BV1r7411U7ra/

代碼位於github:https://github.com/ActivePeter/esp32_flappy_bird

硬件平臺 ttgo-t-display (esp32)

軟件平臺platform io in vscode

(一)驅動部分

顯示屏

#include <TFT_eSPI.h>

按鍵

#include <Button2.h>

對顯示屏部分做出了一定的修改

加入了顯示信息緩衝區unsigned short buffer[32400]={0};

加入了往顯示屏緩衝區繪製長方體的函數

void drawRectToBuffer(int x,int y,int w,int h,u_short color){
  int i,j;
  if(x<0){
    w=w+x;
    x=0;
  }
  if(y<0){
    h=h+y;
    y=0;
  }
  if(x+w>ScreenW){//修正超出範圍
    w=ScreenW-x;
  }
  if(y+h>ScreenH){//修正超出範圍
    h=ScreenH-y;
  }
  for(i=0;i<h;i++){
    for(j=0;j<w;j++){
      buffer[(j+x)*ScreenH+(i+y)]=color;

    }
  }

}

初始化顯示屏

void initTFT(){
  tft.init();
  tft.setRotation(1);
  tft.fillScreen(TFT_BLACK);
  tft.setTextSize(2);
  tft.setTextColor(TFT_WHITE);
  tft.setCursor(0, 0);
  tft.setTextDatum(MC_DATUM);
  tft.setTextSize(1);
  

  if (TFT_BL > 0)
  {                          // TFT_BL has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
    pinMode(TFT_BL, OUTPUT); // Set backlight pin to output mode
    digitalWrite(TFT_BL, 1);
                             // Turn backlight on. TFT_BACKLIGHT_ON has been set in the TFT_eSPI library in the User Setup file TTGO_T_Display.h
  }
}

(二)邏輯實現部分

兩個結構體

typedef struct{
  float x;
  u_char height;

} Pillar;
typedef struct{
  float y;
  float speed;

} Bird;

用來描述小鳥和障礙物。


整體結構

  1. 循環開頭,清空顯示屏緩衝區
  2. 更新數據
  3. 然後將新的數據對應的圖形繪製到緩衝區。
  4. 將緩衝區內容刷新到顯示屏

最主要的邏輯部分就在於更新數據

 if(!dead){
    drawRectToBuffer(birdX,(int)bird.y,birdW,birdW,0xFFE0);
    updatePillars();
    updateBird();
    judgeColid();

  }else{
    drawRectToBuffer(birdX,(int)bird.y,birdW,birdW,0xF800)
  }
(1)更新障礙物,每次增加的x值的大小決定了速度。

然後做一個判斷。有沒有超出屏幕範圍。如果超出了。就把他放到最前面。

void updatePillars(){
  pillars[0].x+=0.6f;
  pillars[1].x+=0.6f;
  pillars[2].x+=0.6f;
  if(pillars[0].x>=ScreenW){
    pillars[0].x=pillars[2].x-PillarSpace-PillarW;
    pillars[0].height=rand()%160+20;
  }
  if(pillars[1].x>=ScreenW){
    pillars[1].x=pillars[0].x-PillarSpace-PillarW;
    pillars[1].height=rand()%160+20;
  }
  if(pillars[2].x>=ScreenW){
    pillars[2].x=pillars[1].x-PillarSpace-PillarW;
    pillars[2].height=rand()%160+20;
  }
}
(2)更新小鳥

1.每次速度都增加一定值(模擬重力)

2.再給速度減掉一個(t*速度^2)(模擬阻力)

3.將速度加到小鳥的y座標上

void updateBird(){
  bird.speed+=0.15f;
  bird.speed-=0.015f*(bird.speed*abs(bird.speed));
  bird.y+=bird.speed;
}
(3)判斷碰撞

判斷x方向上,小鳥方塊是否和障礙物有交集

如果有交集就給curpillar賦值。

然後在判斷有交集的情況下y方向上有沒有碰撞就行了。


同時記錄lastpillar

如果上一次pillar值記錄爲1或2或3

這一次記錄爲0

對應的就是鳥從上一個障礙物中飛出,

此時對應的score++

void judgeColid(){
  u_char curPillar=0;

  if(pillars[0].x+PillarW>=birdX&&pillars[0].x<=birdX||pillars[0].x+PillarW>=birdX+birdW&&pillars[0].x<=birdX+birdW){
    curPillar=1;
  }else if(pillars[1].x+PillarW>=birdX&&pillars[1].x<=birdX||pillars[1].x+PillarW>=birdX+birdW&&pillars[1].x<=birdX+birdW){
    curPillar=2;
  }else if(pillars[2].x+PillarW>=birdX&&pillars[2].x<=birdX||pillars[2].x+PillarW>=birdX+birdW&&pillars[2].x<=birdX+birdW){
    curPillar=3;
  }
  if(lastPillar&&(!curPillar)){
    score++;
  }
  lastPillar=curPillar;
  if(curPillar){
    if(bird.y<=ScreenH - pillars[curPillar-1].height -KongxiHeight){
      dead=true;
    }else if(bird.y+birdW>=ScreenH - pillars[curPillar-1].height){
      dead=true;
    }
  }else{
    if(bird.y<0||bird.y+birdW>=ScreenH){
      dead=true;
    }
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章