查看: 8137|回復: 44
打印 上一主題 下一主題

Arduino教你制作 FC炸彈人游戲

[復制鏈接]
  • TA的每日心情
    奮斗
    2019-3-22 20:44
  • 簽到天數: 6 天

    [LV.2]偶爾看看I

    跳轉到指定樓層
    樓主
    發表于 2018-9-17 19:30 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
    本帖最后由 createskyblue 于 2018-9-17 20:20 編輯


    前排提示,游戲文件、在線模擬在2樓
    1樓為制作教程
    視頻: https://www.bilibili.com/video/av31933044/

    第一步 導入素材





    第二步 地圖生成器


    kittenblock中小學創客名師推薦的圖形化編程軟件

    void BuildMap() {
      /*
         0  空氣
         1  不可摧毀墻
         2  普通墻
         3  TNT
         4  爆炸3
         5  爆炸2
         6  爆炸1
      */
      //生成墻和怪物
      LIFE = 3; //開局3條命
      byte MN = 0; //重置怪物計數器
      PP = 2; //設置玩家方向頭朝下

    首先要生成墻壁,先生成邊框防止玩家跑出地圖,最后生成邊框里面墻壁陣列



    kittenblock中小學創客名師推薦的圖形化編程軟件

    for (byte y = 0; y < 15; y++) {
        for (byte x = 0; x < 31; x++) {
          if (y == 0 || y == 14) {
            MAP[x][y] = 1;        生成y軸墻壁外圍 下圖橙色區域
          } else if (x == 0 || x == 30) {
            MAP[x][y] = 1;        生成x軸墻壁外圍 下圖藍色區域
          } else {
            if (x % 2 == 0 && y % 2 == 0) {
              MAP[x][y] = 1;      判斷當前x,y坐標是否為偶數,如果是則生成內部墻壁
            } else if (random(0, 4) == 0) {
              MAP[x][y] = 2;      1/4概率生成可以破壞的墻
            } else if (random(0, 28) == 0) {   1/28 的概率生成怪物
              //生成怪物
              if (MN < LEVEL) {        確保怪物數量少于當前關卡數
                monster[MN][0] = x;    記錄當前編號怪物的x,y坐標
                monster[MN][1] = y;
                MLRUD[MN] = 2; //設置怪物方向為頭朝下 0上 1右 2下 3左
                MN++;            下一個怪物編號
              }
            } else MAP[x][y] = 0;    假若不滿足上邊的條件則生成空氣
          }
        }
      }



    kittenblock中小學創客名師推薦的圖形化編程軟件

    //設置玩家出生點
      for (byte py = 0; py < 3; py++) {
        for (byte px = 0; px < 3; px++) {
          //清空出生點附近的普通墻和怪物,確保出生點安全
          MAP[15 - 1 + px][7 - 1 + py] = 0;
        }
      }
    
    清除玩家出生點附近3*3區域內所有方塊,確保有較大的空間讓玩家開一條路出去
    
      PX = 15;  設置玩家在地圖上的出生點
      PY = 7;
    }





    上圖為生成器生成的初始游戲地圖
    第三步 實現玩家移動 繪圖部分

    kittenblock中小學創客名師推薦的圖形化編程軟件

    void loop() {
    if (LIFE == 0) FAIL();  //如果生命為0 游戲結束
      key();     //掃描按鍵
      Draw();    //繪圖
      logic();   //邏輯處理
    }
    
    /*=========================================================
      按鍵掃描
      =========================================================*/
    void key() {
      /*
          0  1  2  3  4  5
          ↑ ↓← →  A  B
      */
      KeyBack = 255;
      if (arduboy.pressed(UP_BUTTON)) KeyBack = 0;
      if (arduboy.pressed(DOWN_BUTTON)) KeyBack = 1;
      if (arduboy.pressed(LEFT_BUTTON)) KeyBack = 2;
      if (arduboy.pressed(RIGHT_BUTTON)) KeyBack = 3;
      if (arduboy.pressed(A_BUTTON)) KeyBack = 4;
      if (arduboy.pressed(B_BUTTON)) KeyBack = 5;
    }
    
    /*===================================================================
                                 繪圖
    ===================================================================*/
    void Draw() {
      DrawMap(); //渲染地圖
      DrawEntity(); //渲染實體
      arduboy.display(); //發送畫面到屏幕
    arduboy.fillRect(0, 56, 128, 8, 0);
      for (byte ni = 0; ni < LIFE; ni++) {
        arduboy.drawSlowXYBitmap(ni * 9, 56, LOVE, 8, 8, 1); //生命條
      }
      arduboy.display(); //發送畫面到屏幕
    }
    /*=================================================================
                                 渲染地圖
     ==================================================================*/
    void DrawMap() {
      arduboy.fillRect(0, 0, 128, 64, 1);
      for (char y = PY - 4; y < PY + 5; y++) {
        for (char x = PX - 8; x < PX + 10; x++) {
          if (x >= 0 && y >= 0 && x <= 30 && y <= 14) {


    用兩個嵌套的for語句來掃描玩家視線內的方塊,然后用switch語句顯示出對應方塊的位圖
    下圖灰色區域為玩家所能看到的區域 黑框內為128x64OLED的顯示范圍
    游戲中,無論怎樣移動移動的都是地圖而不是玩家本身,玩家是被固定在屏幕中心位置的,而且地圖方塊對應的位置不代表實際顯示的位置,為了正確顯示我們需要減去地圖方塊與玩家相對坐標 參考下圖紫色箭頭
    為了直觀告訴大家哪里做了處理,下列顯示代碼會把要坐標處理的部分染為紫色

    kittenblock中小學創客名師推薦的圖形化編程軟件

     switch (MAP[x][y]) {
              case 1:
                arduboy.drawSlowXYBitmap(x * 8 - (PX - 15) * 8 - 64 + CSX, y * 8 - (PY - 7) * 8 - 32 + CSY, WALL_1, 8, 8, 0);
                break;
              case 2:
                arduboy.drawSlowXYBitmap(x * 8 - (PX - 15) * 8 - 64 + CSX, y * 8 - (PY - 7) * 8 - 32 + CSY, WALL_2, 8, 8, 0);
                break;
              case 3:
                arduboy.drawSlowXYBitmap(x * 8 - (PX - 15) * 8 - 64 + CSX, y * 8 - (PY - 7) * 8 - 32 + CSY, TNT_table[TNTS], 8, 8, 0);
                break;
              case 4:
                arduboy.drawSlowXYBitmap(x * 8 - (PX - 15) * 8 - 64 + CSX, y * 8 - (PY - 7) * 8 - 32 + CSY, BOOM_1, 8, 8, 0);
                break;
              case 5:
                arduboy.drawSlowXYBitmap(x * 8 - (PX - 15) * 8 - 64 + CSX, y * 8 - (PY - 7) * 8 - 32 + CSY, BOOM_2, 8, 8, 0);
                break;
              case 6:
                arduboy.drawSlowXYBitmap(x * 8 - (PX - 15) * 8 - 64 + CSX, y * 8 - (PY - 7) * 8 - 32 + CSY, BOOM_3, 8, 8, 0);
                break;
            }
          }
        }
      }
      TNTS++;
      if (TNTS >= 2) TNTS = 0;
    }
    /*====================================================================
                                 渲染實體
      ====================================================================*/
    void DrawEntity() {
      if (LIFE > 0) {
        //渲染怪物
        for (byte n = 0; n < 10; n++) {
          if (MLRUD[n] != 255) arduboy.drawSlowXYBitmap(monster[n][0] * 8 - (PX - 15) * 8 - 64 + CSX, monster[n][1] * 8  - (PY - 7) * 8 - 32 + CSY, M_table[byte(MLRUD[n])], 8, 8, 0);
        }

    Man_table 存儲的是炸彈人動作列表:{ 炸彈人_朝上_1, 炸彈人_朝上_2, 炸彈人_朝上_3, 炸彈人_朝右_1, 炸彈人_朝右_2, 炸彈人_朝右_3, 炸彈人_朝下_1, 炸彈人_朝下_2, 炸彈人_朝下_3, 炸彈人_朝左_1, 炸彈人_朝左_2, 炸彈人_朝左_3}
    炸彈人有4個方向的貼圖,每個方向擁有3個動作,加起來一共12幅圖
    變量PP指的是炸彈人的方向,決定選擇哪一組貼圖
    變量PS為炸彈人當前動作幀,當每一幀動作顯示后自加或者復位 實現炸彈人移動動畫
    因此得出Man_table[PP * 3 + PS]這條式子
    當炸彈人受到傷害后將會被扣血,扣血后會進入一段時間的無敵狀態避免短時間重復受到傷害
    而無敵模式中只會顯示炸彈人某個方向的第一幀 忽略掉2、3幀,因此在無敵模式中炸彈人會有閃爍的效果

    kittenblock中小學創客名師推薦的圖形化編程軟件

    //渲染玩家
        if (millis() >= PIT + Invincible_Time) {
          arduboy.drawSlowXYBitmap(56, 24, Man_table[PP * 3 + PS] , 8, 8, 0); //玩家圖像為方向*3+動畫幀
        } else if (PS == 0) arduboy.drawSlowXYBitmap(56, 24, Man_table[PP * 3 + PS] , 8, 8, 0); //無敵模式的時候閃爍效果
        if (PMove == true || millis() < PIT + Invincible_Time) { //只有在玩家移動的時候或者無敵模式 才會有移動動畫
          PS++;
          if (PS > 2) PS = 0;
        } else PS = 0;
      }
    }



    kittenblock中小學創客名師推薦的圖形化編程軟件

    /*=========================================================
      邏輯
      =========================================================*/
    void logic() {
        /*
          控制移動 以及移動相關動畫
        */
        switch (KeyBack) {
          case 0:
            PP = 0;
            SBDP(PP, PX, PY);
            if (PY > 1 && BMove == true) {
              PMove = true;
              for (CSY = 1; CSY <= 7; CSY += 3) Draw();
              PY--;
            }
            break;
          case 1:
            PP = 2;
            SBDP(PP, PX, PY);
            if (PY < 13 && BMove == true) {
              PMove = true;
              for (CSY = -1; CSY >= -7; CSY -= 3) Draw();
              PY++;
            }
            break;
          case 2:
            PP = 3;
            SBDP(PP, PX, PY);
            if (PX > 1 && BMove == true) {
              PMove = true;
              for (CSX = 1; CSX <= 7; CSX += 3) Draw();
              PX--;
            }
            break;
          case 3:
            PP = 1;
            SBDP(PP, PX, PY);
            if (PX < 29 && BMove == true) {
              PMove = true;
              for (CSX = -1; CSX >= -7; CSX -= 3) Draw();
              PX++;
            }
            break;
        }
        if (PMove == true) {
          CSX = 0;
          CSY = 0;
          PMove = false;
        }
    }

    接下來研究炸彈人平滑移動,而不是直接瞬移到下一方塊
    方法是按下方向鍵后先讓背景平滑移動,當移動整整一格方塊后背景復位并且玩家坐標移動到對應位置。給人一種平滑走動的感覺!
    上面移動代碼中反復出現了以下類似的結構,我們取向右移動的代碼來研究:


    1   PP = 1;
    設置炸彈人朝向右邊
       2 SBDP(PP, PX, PY);
    調用SBDP障礙物判斷函數,判斷在炸彈人位置對應方向前是否有障礙物,如果沒有障礙物判斷函數會把變量BMove設置為true
       3 if (PX < 29 && BMove == true) {
       判斷障礙物判斷函數返回值 前方是否沒障礙物,并且前面是否小于x軸地圖最大范圍
       4 PMove = true;
       允許移動
    5 for (CSX = -1; CSX >= -7; CSX -= 3) Draw();
       讓背景往左邊方向平滑移動 每次移動3個像素 如果想要更加平滑可以把-3改為-1
       并且調用繪圖函數背景顯示部分,這里拿墻壁顯示片段舉例
    arduboy.drawSlowXYBitmap(x * 8 - (PX - 15) * 8 - 64 + CSX, y * 8 - (PY - 7) * 8 - 32 + CSY, WALL_1, 8, 8, 0);
       6 PX++;
       讓炸彈人坐標真正往前一步,不過不用馬上調用繪圖函數刷新
       }
       6步 背景復位   if (PMove == true) {
                 CSX = 0;
                   CSY = 0;
                   PMove = false;
                }
    這一步也沒有立即調用繪圖函數來刷新,盡管背景位置復位了,不過玩家位置已經向前,所以在下一次刷新的時候畫面不會變化


    /*===================================================================
                                  障礙物判斷===================================================================*/
    void SBDP(byte SBP, byte sx, byte sy) {
    1  BMove = true;
           char SX, SY;
    初始化變量
    2步 判斷返回值
    調用障礙物判斷函數的時候還要傳遞3個數據 分別是 方向 和玩家位置x和y
    用一個SWITCH語句判斷要檢測的坐標

    (X,Y-1)
    (X-1,Y)
    玩家位置
    (X,Y)
    (X+1,Y)
    (X,Y+1)


    kittenblock中小學創客名師推薦的圖形化編程軟件

    switch (SBP) {
        case 3:
          SX = -1;
          SY = 0;
          break;
        case 1:
          SX = +1;
          SY = 0;
          break;
        case 0:
          SX = 0;
          SY = -1;
          break;
        case 2:
          SX = 0;
          SY = +1;
          break;
      }

    3步 獲取列表長度
    獲取障礙物列表最大的長度 默認障礙物列表有以下ID(1,2,3) 分別為堅固墻壁 可以摧毀的墻壁以及TNT

    kittenblock中小學創客名師推薦的圖形化編程軟件

    byte length = sizeof(SBDPL) / sizeof(SBDPL[0]);
    4步 檢測是否為障礙物
    獲用for逐個檢測目標位置ID是否為障礙物,如果是則設定變量BMOVE為false

    kittenblock中小學創客名師推薦的圖形化編程軟件

    for (byte i = 0; i < length; i++) {  
        if (MAP[sx + SX][sy + SY] == SBDPL) BMove = false;
      }
    }

    第四步 TNT放置 爆炸效果 爆炸傷害

    在上邊第二步中檢測按鍵返回值控制移動的switch語句中加多以下內容
    case 4:
            //TNT
    1步 檢查要放TNT的位置是否已經有TNT 并且這一刻全地圖內是否少于10TNT
            if (TNTN < 10 && MAP[PX][PY] != 3) {
              //注意0為沒有TNT 范圍1-10
    2步 可以放置TNT 讓全地圖TNT數量+1
              TNTN++;

    3步  在TNT列表中設置好當前編號的TNT位置
              TntList[TNTN - 1][0] = PX;
              TntList[TNTN - 1][1] = PY;

    4步  在地圖對應位置寫入TNTID
              MAP[PX][PY] = 3;

    5步 記錄下放置TNT的時間 用于計算什么時候起爆
              TntTime[TNTN - 1] = millis();
            }
            break;
    現在TNT已經放置了,可是還需要讓它到時間后起爆,在邏輯語句中加入以下部分
    /*
           計算TNT爆炸
      */

    1步 判斷地圖內是否存在TNT,有的話繼續
        if (TNTN != 0) {
          //存在炸彈
    2步 檢查TNT列表第一個也就是最接近起爆時間的TNT是否到時間
          if (millis() >= TntTime[0] + BOOMTime) {

    3步 如果到了起爆時間那么在地圖TNT所在的位置上把ID-3 準備爆炸的TNT 替換為ID-4爆炸第一階段

            MAP[TntList[0][0]][TntList[0][1]] = 4; //引爆
            //摧毀附近的非堅固實體或者方塊

    4步 檢查起爆的TNT十字范圍內是否有可以摧毀的東西,有的話把ID替換為ID-4 爆炸的第一階段

    (X,Y-1)
    (X-1,Y)
    TNT位置
    (X,Y)
    (X+1,Y)
    (X,Y+1)

    先用for檢查X軸是否有可以摧毀的方塊,這里可以修改代碼擴大摧毀范圍

    kittenblock中小學創客名師推薦的圖形化編程軟件

     for (byte BOOMx = 0; BOOMx < 3; BOOMx++) {
    if (MAP[TntList[0][0] - 1 + BOOMx][TntList[0][1]] != 1 && MAP[TntList[0][0] - 1 + BOOMx][TntList[0][1]] != 3) { MAP[TntList[0][0] - 1 + BOOMx][TntList[0][1]] = 4; } }
    最后for檢查y軸是否有可以摧毀的方塊

    kittenblock中小學創客名師推薦的圖形化編程軟件

    for (byte BOOMy = 0; BOOMy < 3; BOOMy++) {
              if (MAP[TntList[0][0]][TntList[0][1] - 1 + BOOMy] != 1 && MAP[TntList[0][0] - 1 + BOOMy][TntList[0][1]] != 3) {
                MAP[TntList[0][0]][TntList[0][1] - 1 + BOOMy] = 4;
              }
            }
    5步 在TNT列表注銷以及爆炸的TNT

    kittenblock中小學創客名師推薦的圖形化編程軟件

     //讓TNT列表向前移位
            TNTN--; //減少一枚TNT
            for (byte TNTi = 0; TNTi < TNTN; TNTi++) {
    讓列表后邊的TNT坐標和TNT放置時間移動到前面一位
    TntList[TNT編號][0] 對應編號TNT的X軸
    TntList[TNT編號][1] 對應編號TNT的Y軸
    TntTime[編號]         對應編號TNT的放置時間
    
              TntList[TNTi][0] = TntList[TNTi + 1][0];
              TntList[TNTi][1] = TntList[TNTi + 1][1];
              TntTime[TNTi] = TntTime[TNTi + 1];
            }
          }
    }
    現在TNT可以爆炸,接下來是爆炸動畫


    kittenblock中小學創客名師推薦的圖形化編程軟件

    第1步 兩個嵌套的for遍歷地圖
     for (byte y = 0; y < 15; y++) {
    for (byte x = 0; x < 31; x++) {
    
    
    第2步 如果是4替換為5 5替換為6 6替換為0(空氣)
          if (MAP[x][y] == 4) MAP[x][y] = 5; else if (MAP[x][y] == 5) MAP[x][y] = 6; else if (MAP[x][y] == 6) MAP[x][y] = 0; //讓爆炸切換下一幀
        }
      }
    
    有動畫還不夠,TNT存在的意義是破壞和傷害
    
    第1步 檢查怪物列表
    用for遍歷怪物列表,每個地圖怪物上限為10 很輕松就可以遍歷一次
    for (byte i = 0; i < 10; i++) {
          if (MAP[monster[0]][monster[1]] >= 4 && MLRUD != 255) { 
    假若當前列表編號的怪物不是死亡狀態并且腳下為ID-4 ~ ID-6 不同階段的爆炸則繼續執行
            
    
    第2步 讓怪物死亡
    MLRUD = 255; 
          }
    
    第3步 檢查玩家是否在無敵狀態
          if (millis() >= PIT + Invincible_Time) { //玩家不在無敵狀態
    
    
    第4步 若不是在無敵狀態下檢查腳下是否為為ID-4 ~ ID-6 不同階段的爆炸
            if (PX == monster[0] && PY == monster[1] || MAP[PX][PY] >= 4) { //怪物傷害 或者 TNT傷害
    
    第5步 扣生命 以及設置無敵狀態開始的時間
              LIFE--;
              PIT = millis();
            }
          }

    第五步 怪物AI
    要怪物有可用,為了被玩家攻擊和攻擊玩家給玩家帶來難度,所以我們要會動的怪物而不是呆住不動的木頭腦袋
    在邏輯語句插入以下內容

    kittenblock中小學創客名師推薦的圖形化編程軟件

     /*
         怪物AI
      */
    第1步 假設游戲通關 怪物被消滅
    bool PWIN = true;
    
    第2步 是否到了刷新時間 若是繼續執行
    if (millis() >= MMTime + MMTimeOut) {
    
    重置刷新時間
          MMTime = millis();
    
    第3步 遍歷怪物列表
          for (byte n = 0; n < 10; n++) {
    
    假若對應列表編號的怪物不是死亡狀態
            if (MLRUD[n] != 255) {
    很遺憾,游戲還沒有結束 設置游戲勝利狀態為假
              PWIN = false;
    
    第4步  通過SBDP障礙物判斷函數判斷怪物坐標的對應方向是否有障礙物
              SBDP(MLRUD[n], monster[n][0], monster[n][1]); 
    
    第5步 沒有障礙物 進行移動
    在對應方向的坐標走一步
              if (BMove == true) {
                //移動合法
                switch (MLRUD[n]) {
                  case 0:
                    monster[n][1]--;
                    break;
                  case 1:
                    monster[n][0]++;
                    break;
                  case 2:
                    monster[n][1]++;
                    break;
                  case 3:
                    monster[n][0]--;
                    break;
                }
    假若有障礙物,那么怪物方向隨機更改(通過無數次嘗試發現越簡單的越好用,窮舉法在這種情況下很好用)
              } else MLRUD[n] = random(0, 4);
            } else if (PWIN == true) WIN(); 假若通過為真,調用通關函數
          }
        }


    第六步 游戲菜單 以及 游戲結束


    kittenblock中小學創客名師推薦的圖形化編程軟件

    /*=========================================================
                         通關
      =========================================================*/
    void WIN() {
    
    第1步 假若關卡為10 則通關畫面
      if (LEVEL == 10) {
    第2步 清屏并顯示文字
        arduboy.clear();
        arduboy.setCursor(16, 0);
        arduboy.println(F("CONGRATULATIONS"));
        arduboy.println(F(" BOMBER MAN BECOMES"));
        arduboy.println(F("       RUNNER"));
        arduboy.println(F("SEE YOU AGAIN IN LODE"));
    arduboy.println(F("       RUNNER"));
    
    
    第3步 顯示一個面向右面的炸彈人
    arduboy.drawSlowXYBitmap(56, 48, Man_table[3] , 8, 8, 1);
    
    
    第4步 在最下方磚塊顯示的區域畫一個實心長方體,用于畫布底層
    arduboy.fillRect(0, 56, 128, 8, 1);
    通過for顯示16個轉頭
        for (byte x = 0; x < 128; x += 8) {
          arduboy.drawSlowXYBitmap(x, 56, WALL_2, 8, 8, 0);
    }
    
    第5步 在屏幕上顯示
        arduboy.display();
        while (1) {}
      } else {
    假若關卡小于10
        LEVEL++;   //關卡+1
        BuildMap();  //構建地圖
        ShowLevel(); //顯示第幾關
      }
    }




    kittenblock中小學創客名師推薦的圖形化編程軟件

    /*=========================================================
                         顯示關卡
      =========================================================*/
    void ShowLevel() {
      arduboy.clear();
      arduboy.setCursor(52, 16);
      arduboy.println(F("LEVEL"));
      arduboy.setCursor(64, 32);
      arduboy.println(LEVEL);
      arduboy.display();
      delay(1000);
    }
    /*=========================================================
                         玩家死亡
      =========================================================*/
    void FAIL() {
      for (byte y = 0; y < 15; y++) {
        for (byte x = 0; x < 31; x++) {
          MAP[x][y] = 4;
    把整個地圖設置為爆炸
        }
      }
    
      while (MAP[0][0] >= 3) {
        Draw();
        logic();
    delay(500);
    切換爆炸下一幀,直到爆炸結束
      }




    kittenblock中小學創客名師推薦的圖形化編程軟件

     Draw();
      arduboy.drawSlowXYBitmap(56, 24, Man_table[3] , 8, 8, 0);
    在畫面中間顯示孤獨的主角




    kittenblock中小學創客名師推薦的圖形化編程軟件

    arduboy.display();
      delay(5000);
      resetFunc(); //重啟游戲
    }
    /*=========================================================
                         主菜單
      =========================================================*/
    void MENU() {
      bool POA = false;
      while (POA == true || KeyBack != 4) {
        key();
        switch (KeyBack) {
          case 0:
            POA = false;
            break;
          case 1:
            POA = true;
            break;
          case 4:
            if (POA == true) {
              KeyBack = 255;
              arduboy.clear();
              arduboy.setCursor(0, 0);
              arduboy.println(F(" >About"));
              arduboy.println(F(""));
              arduboy.println(F("LHW programming"));
              arduboy.println(F("LHW Art"));
              arduboy.println(F("E-mail"));
              arduboy.println(F("[email protected]"));
              arduboy.println(F(""));
              arduboy.println(F("Any key back..."));
              arduboy.display();
              delay(200);
              while (KeyBack == 255) key();
              delay(200);
            }
            break;
        }
        arduboy.clear();
        arduboy.drawSlowXYBitmap(39, 1, START_TITLE , 87, 39, 1);  //大標題
        arduboy.drawSlowXYBitmap(0, 23, TITLE_TNT , 37, 41, 1);    //TNT圖標
        arduboy.drawSlowXYBitmap(65, 58, LHW , 39, 5, 1);          //作者信息
        arduboy.setCursor(70, 39);
        arduboy.println(F("PLAY"));
        arduboy.setCursor(70, 47);
        arduboy.println(F("ABOUT"));
        if (POA == false) arduboy.setCursor(62, 39); else arduboy.setCursor(62, 47);
        arduboy.println(F("*"));
        arduboy.display();
      }
    }




    0.png (2.11 KB, 下載次數: 36)

    0.png
  • TA的每日心情
    奮斗
    2019-3-22 20:44
  • 簽到天數: 6 天

    [LV.2]偶爾看看I

    沙發
     樓主| 發表于 2018-9-17 19:41 | 只看該作者
    本帖最后由 createskyblue 于 2018-10-3 21:31 編輯

    更新:2018/9/21 怪物傷害玩家代碼中,忘記判斷怪物是否死亡,導致死亡并且隱藏的怪物傷害玩家,無緣無故扣血 GITHUB將會發布推送更新


    如何正確運行游戲
    游戲文件:
    游客,如果您要查看本帖隱藏內容請回復

    傳統的u8g系列的庫包括u8g2 刷新有點慢,所以使用arduboy UNO移植庫,刷新率比較快
    但是會導致運行游戲沒有這么容易 參考方法一和二
    即使沒有硬件,有手機或電腦也可以使用在線模擬器運行游戲,沒關系的 看方法三
    方法一 直接上傳hex
    *Arduboy上傳Ardubox.hex
    *UNO上傳UNO.hex
    1.先連接硬件
    上鍵               ===>17 A3
    下鍵               ===>2
    左鍵               ===>15 A1
    右鍵               ===>3
    A鍵                ===>4
    B鍵                ===>16 A2
    OLED_SCL     ===>19 A5
    OLED_SDA    ===>18 A4

    按鍵一端接地 一端接到UNO上

    2.下載Arduloader
    3.打開Arduloader
    游戲hex文件在上面的游戲下載附件的壓縮包里
    該畫面為成功上傳,現在oled上應該有畫面

    方法二 編譯安裝    可以參考下面   假若有Arduboy可以直接編譯
    http://www.ogzcha.live/forum.php?mod=viewthread&tid=80103&highlight=arduboy
    方法三 在線模擬器
    游客,如果您要查看本帖隱藏內容請回復
  • TA的每日心情
    開心
    2018-6-23 09:08
  • 簽到天數: 1 天

    [LV.1]初來乍到

    6#
    發表于 2018-10-9 14:07 | 只看該作者
    太棒了 終于找到了

    該用戶從未簽到

    7#
    發表于 2018-10-29 15:50 | 只看該作者

    太棒了 終于找到了
  • TA的每日心情
    慵懶
    2018-12-7 09:11
  • 簽到天數: 5 天

    [LV.2]偶爾看看I

    9#
    發表于 2018-11-3 09:41 | 只看該作者
    棒,學習到了!!!
    您需要登錄后才可以回帖 登錄 | 立即注冊  

    本版積分規則

    熱門推薦

    為拍月亮而生的便攜望遠鏡系統。
    為拍月亮而生的便攜望遠鏡
    參賽項目: 便攜望遠鏡系統 參賽組員: 1人 布丁:嵌入式軟件、上位機軟件、電路、結
    基于機器視覺的智能分揀機械臂
    基于機器視覺的智能分揀機
    本作品是一個基于機器視覺的智能機械臂操作平臺,其采用atmega32單片機作為主控制系統
    小白求助
    小白求助
    也許我這個問題也許看起來有些幼稚。。。 還在入門的路上打滾,在看《愛上Arduino》這
    SpiderRobot 蜘蛛
    SpiderRobot 蜘蛛
    關于SpiderRobot 項目實行方案 之前有人推薦我做這個項目,于是乎就有了這個 h
    沒有合適的模塊,想到自己焊接芯片
    沒有合適的模塊,想到自己
    有些模塊沒有加工過的模塊銷售,想著自己要是能把芯片焊在一起也是一樣的。只是這個尺
    Copyright   ©2015-2016  Arduino中文社區  Powered by©Discuz!   
    快速回復 返回頂部 返回列表
    北京快乐8论坛