Arduino提高篇26—貪喫蛇遊戲

在這裏插入圖片描述

之前文章Processing筆記05—貪喫蛇小遊戲分享過如何使用Processing來實現貪喫蛇遊戲,很多小夥伴問可不可以來個Arduino版本的,那麼本篇就通過Arduino,配合搖桿按鍵和OLED顯示屏來實現貪喫蛇遊戲。

1. 實驗材料

  • Uno R3開發板
  • 配套USB數據線
  • 麪包板及配套連接線
  • 雙軸按鍵搖桿模塊
  • OLED顯示屏

2. 實驗步驟

1. 根據原理圖搭建電路圖。

OLED屏的VCC、GND分別連接開發板的3.3V、GND,OLED屏的SDA和SCL分別連接開發板的A4和A5。雙軸按鍵搖桿模塊的VCC、GND分別連接開發板的5V、GND,模塊的X軸輸出、Y軸輸出分別連接開發板的模擬引腳A0、A1。

實驗原理圖如下圖所示:

實驗原理圖

實物連接圖如下圖所示:

實物連接圖

2. 由於代碼部分較長,這裏截取部分展示。完整代碼可在文末獲取。

...
void snake_move(void)
{
  switch (snake_dir) {
    case RIGHT:
      snake_head_x += 4;
      break;
    case UP:
      snake_head_y -= 4;
      break;
    case LEFT:
      snake_head_x -= 4;
      break;
    case DOWN:
      snake_head_y += 4;
      break;
  }

  if ((snake_head_x == food_x) && (snake_head_y == food_y))
  {
    food_eaten = true; //可重新生成食物
    snake_len++;
    score++;
    level = score / 5 + 1;
    snake_speed -= level;
  }

  for (i = snake_len - 1; i > 0; i--)
  {
    x[i] = x[i - 1];
    y[i] = y[i - 1];
  }
  x[0] = snake_head_x;
  y[0] = snake_head_y;

  check_snake_die();
}
...

3. 連接開發板,設置好對應端口號和開發板類型,進行程序下載。

程序下載

3. 程序分析

1. 蛇身的繪製

貪喫蛇中最主要的部分就是繪製蛇身,實驗中使用數組來保存蛇身每個方塊的座標值,使用drawBitmap()函數來繪製一個4X4的矩形表示蛇身方塊。

void draw_snake(int x, int y)
{
  oled.drawBitmap(x, y, block, 4, 4, 1);
}

每當蛇頭位置發生變化,從蛇尾往前遍歷整個座標數組,將每個方塊位置往前移動,蛇頭座標爲新位置的座標,然後重新繪製整個蛇身。

2. 食物的產生

在這裏使用了隨機函數產生規定區域內的食物座標。首先在setup()中初始化隨機種子:

randomSeed(analogRead(3));//初始化隨機種子

然後就可以使用random()生成座標數據,這裏除了需要指定區域外,還需要考慮排除掉生成在蛇身中的食物。

void draw_food(void)
{
  int food_out = 0; //判斷食物是否在蛇體內

  if (food_eaten)
  {
    while (food_out == 0)
    {
      food_out = 1;

      food_x = (uint8_t)(random(4, 100) / 4) * 4;
      food_y = (uint8_t)(random(4, 60) / 4) * 4;

      for (int i = snake_len - 1; i > 0; i--) //遍歷整個蛇身方塊,若食物在蛇身內則重新生成
      {
        if (food_x == x[i] && food_y == y[i])
        {
          food_out = 0;
        }
      }
    }
  }

  food_eaten = false;
}

3. 方向控制

本篇使用的是搖桿模塊,通過採集到的模擬量來識別出上下左右的不同操作,然後對應改變蛇頭的座標,當重新對蛇身進行繪製的時候,整個蛇就進行了一次移動。

4. 判斷遊戲結束

當蛇頭座標超過顯示區域,即蛇撞牆,或蛇頭位置座標與蛇身其他方塊座標相同,即自己吃了自己,都會導致遊戲結束。

void check_snake_die(void)
{
  //撞牆
  if (snake_head_x < 4 || snake_head_x > 96 || snake_head_y < 1 || snake_head_y > 56)
  {
    game_over = true;
  }

  //自己喫自己
  if (snake_len > 4)
  {
    for (int i = 1; i < snake_len; i++)
    {
      if (snake_head_x == x[i] && snake_head_y == y[i])
      {
        game_over = true;
      }
    }
  }
}

5. 問題及改進

由於按鍵的判斷和屏幕的刷新都放在了loop()中,遊戲的速度通過改變delay()函數即改變延時時間來實現,所以當遊戲速度過慢時,按鍵操作就變得不靈敏。可以試着使用定時器來刷新屏幕,通過改變定時時間來改變遊戲速度。

另外在撞牆的條件判斷中,邊界值需要實際調試,沒有移動到邊界或者移動超出邊界都不應結束遊戲。

大結局

陸陸續續分享了很多Arduino的教程,包括基礎版33篇和提高版26篇,在這個過程中也幫助到了一些小夥伴,其實筆者玩Arduino都是業餘興趣,教程中的很多東西也是通過網絡不斷學習彙總的。

由於教程配套了實物套件,不得不與套件中的器件進行配套,其實這並不是件容易的事情,需要從一開始就要考慮後面的好幾篇內容,完全不能隨心所欲的分享。終於,Arduino系列教程到此就結束了,後面分享Arduino會多一些創客DIY之類的。

興趣是最好的老師,希望小夥伴們除了應對課程設計之類的,也能喜歡上Arduino。願你所有的堅持,都來自心中的那份熱愛。


關注公衆號「TonyCode」,後臺回覆“提高”,獲取文中代碼。

個人博客

回覆「1024」獲取1000G學習資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章