查看: 5975|回复: 40

Arduino教你制作 FC炸弹人游戏

[复制链接]
  • TA的每日心情
    奋斗
    2019-3-22 20:44
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    发表于 2018-9-17 19:30 | 显示全部楼层 |阅读模式
    本帖最后由 createskyblue 于 2018-9-17 20:20 编辑

    0 - 副本.png 1.png
    前排提示,游戏文件、在线模拟在2楼
    1楼为制作教程
    视频: https://www.bilibili.com/video/av31933044/

    第一步 导入素材

    11.png



    第二步 地图生成器


    kittenblock中小学创客名师推荐的图形化编程软件

    void BuildMap() {
      /*
         0  空气
         1  不可摧毁墙
         2  普通墙
         3  TNT
         4  爆炸3
         5  爆炸2
         6  爆炸1
      */
      //生成墙和怪物
      LIFE = 3; //开局3条命
      byte MN = 0; //重置怪物计数器
      PP = 2; //设置玩家方向头朝下

    首先要生成墙壁,先生成边框防止玩家跑出地图,最后生成边框里面墙壁阵列

    5.png

    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;    假若不满足上边的条件则生成空气
          }
        }
      }


    4.png

    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;
    }



    12.png

    上图为生成器生成的初始游戏地图
    第三步 实现玩家移动 绘图部分

    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的显示范围
    游戏中,无论怎样移动移动的都是地图而不是玩家本身,玩家是被固定在屏幕中心位置的,而且地图方块对应的位置不代表实际显示的位置,为了正确显示我们需要减去地图方块与玩家相对坐标 参考下图紫色箭头
    为了直观告诉大家哪里做了处理,下列显示代码会把要坐标处理的部分染为紫色

    6.png

    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;
      }
    }


    7.png

    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可以爆炸,接下来是爆炸动画

    8.png

    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(); 假若通过为真,调用通关函数
          }
        }

    2.png

    第六步 游戏菜单 以及 游戏结束


    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(); //显示第几关
      }
    }


    3.png

    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);
    切换爆炸下一帧,直到爆炸结束
      }


    9.png

    kittenblock中小学创客名师推荐的图形化编程软件

     Draw();
      arduboy.drawSlowXYBitmap(56, 24, Man_table[3] , 8, 8, 0);
    在画面中间显示孤独的主角

    10.png


    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("1281702594@qq.com"));
              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
    0.75R=>1米热敏纸=>8道错题解析=>接近梦想

    1人打赏

  • 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可以直接编译
    https://www.arduino.cn/forum.php?mod=viewthread&tid=80103&highlight=arduboy
    方法三 在线模拟器
    游客,如果您要查看本帖隐藏内容请回复
    0.75R=>1米热敏纸=>8道错题解析=>接近梦想
  • TA的每日心情
    开心
    2018-6-23 09:08
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2018-10-9 14:07 | 显示全部楼层
    太棒了 终于找到了

    该用户从未签到

    发表于 2018-10-29 15:50 | 显示全部楼层

    太棒了 终于找到了
  • TA的每日心情
    慵懒
    2018-12-7 09:11
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2018-11-3 09:41 | 显示全部楼层
    棒,学习到了!!!
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表