亲,“电路城”已合并升级到更全、更大、更强的「新与非网」。点击查看「新与非网」

本网页已闲置超过3分钟,按键盘任意键或点击空白处,即可回到网页

基于Arduino的“太空侵略者”游戏

发布时间:2021-04-28
分享到:

基于Arduino的“太空侵略者”游戏

发布时间:2021-04-28
分享到:

该项目/视频将展示如何在自制的8x8 LED矩阵上制作“太空侵略者”游戏。

组件:

  • Arduino Nano微控制器
  • 8x8 LED矩阵
  • 10kΩ电位器
  • 蜂鸣器
  • 瞬时开关

 原理图:

组装:

矩阵包含64个5毫米LED,这些LED安装在厚度为4毫米的Alumil板上。在矩阵的前面放置了一块厚度为1 mm的白色有机玻璃,用作光扩散器。

电位器用于左右移动武器,并通过按钮发射激光束。游戏伴随着适当的声音,类似于原始声音。它还包含几个级别,每增加一个新级别,速度就会提高。在这种情况下,电源是外部的,电池也可以安装。

将组件安装在合适的PVC盒子中,该盒子的厚度为3和5 mm,并涂有彩色的自粘墙纸。

代码(Arduino):

/ * ============================================ ============= * /
/ *
05-833 HCI中的应用小工具,传感器和活动识别
斯科特·哈德森(Scott Hudson)上课
卡内基·梅隆大学
2012年春季

*《太空客》 *,艾尔文·李(Elwin Lee)
娱乐技术中心
卡内基·梅隆大学

学分:
驱动器矩阵模式http://arduino.cc/playground/Main/DirectDriveLEDMatrix
通过扬声器播放音调http://arduino.cc/en/Tutorial/Tone
* /
/ * ================================================ ======== * /

#include "pitches.h"

/****测试****/
byte tempMatrix[8][8] = {  
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0},
  {0, 0, 0, 0, 0, 0, 0, 0} 
};

/*** 1级 ***/
#define level1_ani { \
  {1, 1, 1, 0, 0, 1, 1, 1}, \
  {1, 1, 0, 0, 0, 1, 1, 1}, \
  {1, 1, 0, 0, 0, 1, 1, 1}, \
  {1, 1, 1, 0, 0, 1, 1, 1}, \
  {1, 1, 1, 0, 0, 1, 1, 1}, \
  {1, 1, 1, 0, 0, 1, 1, 1}, \
  {1, 1, 0, 0, 0, 0, 1, 1}, \
  {1, 1, 0, 0, 0, 0, 1, 1}  \
}
#define level1 { \
  {0, 1, 0, 1, 0, 1, 0, 0}, \
  {0, 0, 1, 0, 1, 0, 1, 0}, \
  {0, 1, 0, 1, 0, 1, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}  \
}

/*** 2级 ***/
#define level2_ani { \
  {1, 1, 1, 0, 0, 1, 1, 1}, \
  {1, 1, 0, 0, 0, 0, 1, 1}, \
  {1, 1, 0, 1, 1, 0, 0, 1}, \
  {1, 1, 1, 1, 1, 0, 0, 1}, \
  {1, 1, 1, 1, 0, 0, 1, 1}, \
  {1, 1, 1, 0, 0, 1, 1, 1}, \
  {1, 1, 0, 0, 0, 0, 0, 1}, \
  {1, 1, 0, 0, 0, 0, 0, 1}  \
}

#define level2 { \
  {0, 1, 0, 1, 0, 1, 0, 1}, \
  {0, 0, 1, 0, 1, 0, 1, 0}, \
  {0, 1, 0, 1, 0, 1, 0, 1}, \
  {0, 0, 1, 0, 1, 0, 1, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}  \
}

/*** 3级 ***/
#define level3_ani { \
  {1, 1, 1, 0, 0, 0, 1, 1}, \
  {1, 1, 0, 0, 0, 0, 0, 1}, \
  {1, 1, 0, 1, 1, 0, 0, 1}, \
  {1, 1, 1, 1, 0, 0, 1, 1}, \
  {1, 1, 1, 1, 0, 0, 0, 1}, \
  {1, 1, 0, 1, 1, 0, 0, 1}, \
  {1, 1, 0, 0, 0, 0, 0, 1}, \
  {1, 1, 1, 0, 0, 0, 1, 1}  \
}
#define level3 { \
  {0, 0, 0, 1, 1, 1, 0, 0}, \
  {0, 0, 1, 1, 1, 1, 1, 0}, \
  {0, 1, 1, 0, 1, 0, 1, 1}, \
  {0, 1, 0, 1, 1, 1, 0, 1}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}  \
}

/*** 赢 ***/
#define win { \
  {1, 1, 1, 0, 0, 1, 1, 1}, \
  {1, 1, 0, 0, 0, 0, 1, 1}, \
  {1, 0, 1, 0, 0, 1, 0, 1}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {0, 0, 0, 0, 0, 0, 0, 0}, \
  {1, 0, 1, 0, 0, 1, 0, 1}, \
  {1, 0, 0, 1, 1, 0, 0, 1}, \
  {1, 1, 1, 0, 0, 1, 1, 1}  \
}


/*** 一般的 ***/
const int cols[8] = { 12, 11, 10, 9, 8, 7, 6, 5 };    // Array of all the Column pin numbers
const int rows[8] = { 4, 3, 2, A0, A1, A2, A3, A4 };  // Array of all the Row pin numbers

// LED矩阵中的二维像素阵列:
int pixels[8][8];  

int loopDelay = 2;

boolean levelAni = true;  //真
boolean levelStart = false;
boolean levelComplete = false;

int levelsArrayIndex = 0;

const int _lvls = 7;  //2 * 级数
byte levels[_lvls][8][8] = { 
  level1_ani, level1, level2_ani, level2, level3_ani, level3, win
};

//复制级别数组以进行重置
byte initial[_lvls][8][8] = { 
  level1_ani, level1, level2_ani, level2, level3_ani, level3, win
};

/*** 声音***/
int boom = NOTE_C4;

boolean loseSound = true;
int lose[] = { NOTE_F4, NOTE_A4, NOTE_C5 };
int loseNoteDurations[] = { 2, 4, 4};

/*** 计时器 ***/
unsigned long aniTime;
unsigned long completeTime;
unsigned long enemyTime;
unsigned long gameOverTime;

/*** 玩家 ***/
int bulletRow = 5;
int bulletCol;
byte bulletArray[6];

int bulletDelayCount = 0;
boolean fired = false;


/*** 控制 ***/
int btnPin = A5;
int potPin = A6;
int potVal;

boolean btnDown = false;

/*** 敌人 ***/
boolean enemyWon = false;
boolean enemyWaiting = false;
boolean enemyFired = false;
boolean enemyBulletCollision = false;

int enemyAttackSpeed[7] = {0, 150, 0, 100, 0, 25, 0};
int enemyBulletSpeed[7] = {0, 16, 0, 12, 0, 8, 0};
int enemyBulletRow;
int enemyBulletDelayCount = 0;
int enemyBulletArray[8][2] = { {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0} };
int enemyBottomCount = 0;
int randomBullet;

/*** 转换 ***/
boolean shiftLevel = false;
boolean shiftLeft = true;
boolean shiftDown = false;
boolean shiftRight = false;
boolean shiftUp = false;

int shiftCount = 0;
int shiftSpeed[2] = {70, 35};


void setup() {
  Serial.begin(9600);
  // 将I / O引脚初始化为输出:

  //遍历图钉:
  for (int thisPin = 0; thisPin < 8; thisPin++) {
     //初始化输出引脚:
    pinMode(cols[thisPin], OUTPUT); 
    pinMode(rows[thisPin], OUTPUT);  
     //将col引脚(即阴极)拉高,以确保
    // LED熄灭: 
    //两者均为高电平,因此无连接
    digitalWrite(cols[thisPin], HIGH);
    digitalWrite(rows[thisPin], HIGH);  
  }
  
 //将按钮和电位计设置为输入
  pinMode(btnPin, INPUT);
  pinMode(potPin, INPUT);

  clearLeds();  //清除LED矩阵
  aniTime = millis();  //开始级别#动画计时器
  
}

void loop() {
  
 / ***全部重置为无电路*** /
  for (int i = 0; i < 8; i++) {
    digitalWrite(rows[i], HIGH); //所有行都高 
    digitalWrite(cols[i], LOW);
  }
  
  
    
  /***行 0***/
  for (int col = 0; col < 8; col++) {
    if (pixels[0][col] == 1) {
      digitalWrite(cols[col], HIGH); 
    } else {
      digitalWrite(cols[col], LOW);
    }
  }
  digitalWrite(rows[0], LOW);
  delay(loopDelay);
  digitalWrite(rows[0], HIGH);

  setPattern(levelsArrayIndex);  //创建关卡
  
  /***行 1***/
  for (int col = 0; col < 8; col++) {
    if (pixels[1][col] == 1) {
      digitalWrite(cols[col], HIGH); 
    } else {
      digitalWrite(cols[col], LOW);
    }
  }
  digitalWrite(rows[1], LOW);
  delay(loopDelay);
  digitalWrite(rows[1], HIGH);
  
  if (levelAni) playLevelAni();  //播放动画

  /***第 2行***/
  for (int col = 0; col < 8; col++) {
    if (pixels[2][col] == 1) {
      digitalWrite(cols[col], HIGH); 
    } else {
      digitalWrite(cols[col], LOW);
    }
  }
  digitalWrite(rows[2], LOW);
  delay(loopDelay);
  digitalWrite(rows[2], HIGH);
  
  if (levelStart) readPot();  //读取电位器值

  /***第三行***/
  for (int col = 0; col < 8; col++) {
    if (pixels[3][col] == 1) {
      digitalWrite(cols[col], HIGH); 
    } else {
      digitalWrite(cols[col], LOW);
    }
  }
  digitalWrite(rows[3], LOW);
  delay(loopDelay);
  digitalWrite(rows[3], HIGH);
  
  if (levelStart) refreshPlayer();  //根据电位器值更新玩家的位置
  if (levelStart) readBtn();      //读取按钮状态
  
  /***第四行***/
  for (int col = 0; col < 8; col++) {
    if (pixels[4][col] == 1) {
      digitalWrite(cols[col], HIGH); 
    } else {
      digitalWrite(cols[col], LOW);
    }
  }
  digitalWrite(rows[4], LOW);
  delay(loopDelay);
  digitalWrite(rows[4], HIGH);
  
  if (levelStart && !enemyWon) readEnemy(); //获取敌人的最高排#号并发射子弹
  
  /***第五行***/
  for (int col = 0; col < 8; col++) {
    if (pixels[5][col] == 1) {
      digitalWrite(cols[col], HIGH); 
    } else {
      digitalWrite(cols[col], LOW);
    }
  }
  digitalWrite(rows[5], LOW);
  delay(loopDelay);
  digitalWrite(rows[5], HIGH);
  
  if (levelStart && !levelComplete) checkLevelState();  //检查关卡的所有像素都消失了
  if (levelComplete) levelFinished();                //胜利等级

  
  /***第六行***/
  for (int col = 0; col < 8; col++) {
    if (pixels[6][col] == 1) {
      digitalWrite(cols[col], HIGH); 
    } else {
      digitalWrite(cols[col], LOW);
    }
  }
  digitalWrite(rows[6], LOW);
  delay(loopDelay);
  digitalWrite(rows[6], HIGH);
  
  if (levelStart && shiftLevel)  shiftRow();  //在关卡中移动像素
  
  /***Row 7***/
  for (int col = 0; col < 8; col++) {
    if (pixels[7][col] == 1) {
      digitalWrite(cols[col], HIGH); 
    } else {
      digitalWrite(cols[col], LOW);
    }
  }
  digitalWrite(rows[7], LOW);
  delay(loopDelay);
  digitalWrite(rows[7], HIGH);
  
  if (enemyWon) gameOver();  //被敌人击中则失败
  updatePixels();  //更新LED矩阵的所有像素

}

void clearLeds() {
  // 清除显示数组
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      pixels[i][j] = 0;
    }
  }
}

/*** 在LED矩阵上填充水平***/
void setPattern(int pattern) {
  
  if (levelsArrayIndex < 7) {  //如果不是最后一级
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < 8; j++) {
        if ( levels[levelsArrayIndex][i][j] == 1 ) {  //仅将“ 1”复制到临时矩阵
          tempMatrix[i][j] = levels[levelsArrayIndex][i][j];  
        }
      }
    }
  } else {
    restart();  //如果已经结束游戏就重新开始
  }
  
}


/***阅读句柄***/
void readPot() {
  potVal = analogRead(potPin);      //读取电位器值
  potVal = map(potVal, 0, 1024, 0, 6);  //将1023映射到6个LED矩阵值;
                                          //仅0〜6列用于显示播放器
                                          //将max_in和max_out提高1,以实现均匀的值分配http://arduino.cc/forum/index.php?topic=72153.0  
}
/*** 刷新播放器 ***/
void refreshPlayer() {

  byte _playerRows[2][8] = {   //用于储存玩家位置的临时数组
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0}
  };
  
  //绘制玩家像素
  _playerRows[0][potVal+1] = 1;
  _playerRows[1][potVal] = 1;
  _playerRows[1][potVal+1] = 1;
  _playerRows[1][potVal+2] = 1;

  for (int i = 6; i < 8; i++) {     //第6-7行(玩家所在的位置)
    for (int j = 7; j >= 0; j--) {  //更新玩家位置
       if(_playerRows[i-6][j] == 1) {  //仅将“一个”复制到临时矩阵
         tempMatrix[i][j] = _playerRows[i-6][j];
       }
    }
  } 
}


/***阅读按钮***/
void readBtn() {
  
  int btnPress = digitalRead(btnPin);  //读取按钮状态
  if (btnPress == 1 && !fired && !btnDown){      //如果按下按钮
    bulletCol = potVal+1;      //矩阵上的项目符号列值
    btnDown = true;
    fired = true;
  } 
  if (btnDown) {
    if (btnPress == 0) {
      btnDown = false;
    }  
  }
  if (fired) {   
    shoot(bulletCol);    //播放拍摄动画
  } 
}

/*** 拍摄 ***/
void shoot(int _bulletCol) {
  
  if (bulletDelayCount == 2) {    //充当延迟并确定子弹的速度
    bulletRow--;
    
    if (bulletRow < 0) {  //如果子弹到达顶部(行0)
      bulletRow = 5;    //重置子弹行位置
      fired = false;    //子弹射击完成
    } else {
      if (tempMatrix[bulletRow][_bulletCol] == 0) {  //检查下一个像素位置是否为空
        tempMatrix[bulletRow][_bulletCol] = 1;  //新的项目符号像素位置并打开
      } else {
        collisionBullet(bulletRow, _bulletCol);  //子弹与像素碰撞
      }
     }
  } else {
    tempMatrix[bulletRow][_bulletCol] = 1;  //绘制子弹像素
  }
  bulletDelayCount = (bulletDelayCount+1) % 3;  //子弹的速度计算器
  
}
/*** 子弹碰撞 ***/
void collisionBullet(int _row, int _col) {
  int boomNoteDuration = 1000/4;      //声音持续时间
  tone(13, boom, boomNoteDuration);      //播放时播放声音
//  noTone(13);
  levels[levelsArrayIndex][_row][_col] = 0;    //删除从原始级别矩阵拍摄的1个像素
  tempMatrix[_row][_col] = 0;   //更新像素矩阵的温度矩阵
  
  bulletRow = 5;    //将原始项目符号行的位置设置回5
  fired = false;    //子弹射击完成
}


/*** 阅读敌人 ***/
void readEnemy() {
  
  if (!enemyWaiting && !enemyFired && !enemyBulletCollision){  //如果敌人没有做任何事情 anything
    enemyTime = millis();  //启动计时器
    enemyWaiting = true;
  }
  
  if (enemyWaiting) {
    if (millis() - enemyTime > enemyAttackSpeed[levelsArrayIndex]) {  //根据数组对每个等级的攻击速度
      
      int _row = 3;   //临时行值
      boolean dobreak = false;    //用于两次休息;
      
       //循环获取敌人的最高行像素(距离玩家最近) 
      for (int i = 3; !dobreak && i >= 0; i--) {  //向后循环以获取最高行
        for (int j = 0; j < 8; j++) {
            if(levels[levelsArrayIndex][i][j] == 1) { //如果在行中找到“ 1”
              _row = i;           //保存行索引
              enemyBulletRow = _row + 1;  //将敌人子弹放在敌人下方1行的值
              dobreak = true;    //双破;
              break;
            }
         }  
      }
      
      enemyBottomCount = 0; ///计算最高行(距离播放器最近)中“一”像素的数量
      for (int c = 0; c < 8; c++) {  //循环遍历最高行
        if(levels[levelsArrayIndex][_row][c] == 1) {    //检查列是否包含“一个”
          enemyBulletArray[enemyBottomCount][0] = _row;  
          enemyBulletArray[enemyBottomCount][1] = c;
          enemyBottomCount++;  
        }
      }
       
      enemyWaiting = false;
      enemyFired = true;  //发射敌人子弹
      randomBullet = random(enemyBottomCount);  //随机选择列像素之一
    }
  }
  
  if (enemyFired) {
    if (enemyBulletDelayCount == (enemyBulletSpeed[levelsArrayIndex]-1)) {  //敌人子弹速度(较高的值=慢)
      enemyBulletArray[randomBullet][0]++;  //行+ 1
      if  (enemyBulletArray[randomBullet][0] > 7) {  //如果子弹到达底部
        enemyBulletDelayCount = 0;  ///重置并删除项目符号
        enemyFired = false;
      } else {
        if (tempMatrix[enemyBulletArray[randomBullet][0]] [enemyBulletArray[randomBullet][1]] == 0) {  //如果下一行为空
          tempMatrix[enemyBulletArray[randomBullet][0]] [enemyBulletArray[randomBullet][1]] = 1;  //子弹声明
        } else {  //子弹击中东西
          if (!levelComplete) {
            enemyBulletDelayCount = 0;  
            enemyFired = false;
            enemyBulletCollision = true;
          }
        }
      }
    } else {
      tempMatrix[enemyBulletArray[randomBullet][0]][enemyBulletArray[randomBullet][1]] = 1;
    }
    enemyBulletDelayCount = (enemyBulletDelayCount+1) % enemyBulletSpeed[levelsArrayIndex];  //enemy bullet speed
  }
  
  if (enemyBulletCollision) {
    if (enemyBulletArray[randomBullet][0] == 6 || enemyBulletArray[randomBullet][0] == 7) {  //check if enemy's bullet hit player
//      digitalWrite(13, HIGH);
      Serial.println("HIT!");
      enemyWon = true;
      gameOverTime = millis();
    }
    enemyBulletCollision = false;
  }
}


/*** 转换级别***/
void shiftRow() {  //测试目的
  int _speed;
  if (levelsArrayIndex == 3) {
      _speed = shiftSpeed[0];
  } else if (levelsArrayIndex == 5) {
      _speed = shiftSpeed[1];
  }
  byte _levelTemp[5][8] = {   //临时矩阵数组,用于储存级别像素位置
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0}
  };
  for (int i = 0; i < 5; i++) {    //储存在临时数组中
    for (int j = 0; j < 8; j++) {
        _levelTemp[i][j] = levels[levelsArrayIndex][i][j];
    }
  }
  
  if (shiftCount == (_speed-1)) {  //移位前延迟(大约100 * 18ms)
    if (shiftLeft == true) {  //左移
     //循环遍历矩阵的顶部5x8
      for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 8; j++) {
          if (j == 7) {     //防止移动不存在的列索引8
            levels[levelsArrayIndex][i][7] = _levelTemp[i][0];
          } else {
            levels[levelsArrayIndex][i][j] = _levelTemp[i][j+1];
          }
        }
      }
      shiftCount = 0;
      shiftLeft = false;
      shiftDown = true;
    } else if (shiftDown == true) {  //下移
      for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 8; j++) {
          if ( i == 0 ) {    //防止不存在的行索引-1的移位
            levels[levelsArrayIndex][i][j] = 0;
          } else {
            levels[levelsArrayIndex][i][j] = _levelTemp[i-1][j];  //降档
          }
        }
      }
      shiftDown = false;
      shiftRight = true;
     } else if (shiftRight == true) {  //右移
        for (int i = 0; i < 5; i++) {
          for (int j = 7; j >= 0; j--) {
            if (j == 0) {      //防止移动不存在的列索引-1
              levels[levelsArrayIndex][i][0] = _levelTemp[i][7];
            } else {
              levels[levelsArrayIndex][i][j] = _levelTemp[i][j-1];
            }
          }
        }
        shiftCount = 0;
        shiftRight = false;
        shiftUp = true;
      
      } else if (shiftUp == true) {  //向上移动
        for (int i = 0; i < 5; i++) {
          for (int j = 0; j < 8; j++) {
            if ( i == 4 ) {  //防止移位行索引5
              levels[levelsArrayIndex][i][j] = 0;
            } else {
              levels[levelsArrayIndex][i][j] = _levelTemp[i+1][j];  //降档
            }
          }
        }
        shiftUp = false;
        shiftLeft = true;
      }
    }
    shiftCount = (shiftCount+1) % _speed;  //换挡延迟
  
}


/***播放级别数字动画***/
void playLevelAni() {
  
  
  if (millis() - aniTime < 3000) { //从级别号转换到实际级别之前的时间    
//    if (levelsArrayIndex < 6 && millis() - aniTime > 3750) {  //3000
//      delay(500);
//    } 
  } else {
    levelAni = false;  //结束动画
    levelStart = true;

    
    levelsArrayIndex++;
    if (levelsArrayIndex == 3 || levelsArrayIndex == 5) {//如果级别2或3,则开始移位
      shiftLeft = true;
      shiftDown = false;
      shiftRight = false;
      shiftUp = false;
      shiftLevel = true;
    } else {
      shiftLevel = false;
    }
    clearLeds();
    
  }
}

void checkLevelState() { //检查所有关卡像素(敌人)是否都消失了
  int _countLevelPixels = 0;
  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 8; j++) {
      if(levels[levelsArrayIndex][i][j] == 1){
        _countLevelPixels++;   //计算“一个”像素的数量
      }
    }  
  }
  if((_countLevelPixels) == 0){   //如果什么都没有,恭喜!你打水平!
// digitalWrite(13,HIGH);
//    digitalWrite(13, HIGH);
//    Serial.println("COMPLETE!");
    completeTime = millis();
    levelComplete = true;
  }  
}

void levelFinished() { 
  
  if (millis() - completeTime > 2000) {  //过渡到下一级别之前的时间
  
    //重置布尔值
    enemyWaiting = false;
    enemyFired = false;
    enemyBulletCollision = false;

    levelStart = false;  
    levelComplete = false;
    levelAni = true;
    aniTime = millis();
    levelsArrayIndex++;
  }
}


/*** 更新像素矩阵 ***/
void updatePixels() {
  / //使用临时的8x8矩阵更新实际矩阵以防止任何错误
  //当将值直接应用于pixel []矩阵时,往往会出现错误 
  //相反,将所有矩阵值都临时存储并立即将值应用于pixels []更稳定
  
  //将所有临时矩阵值复制到实际显示矩阵
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      pixels[i][j] = tempMatrix[i][j]; 
    }
  }
  
  //重置临时矩阵的所有值
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      tempMatrix[i][j] = 0;
    }
  }
}

void gameOver() {
  
  if( loseSound) {
    loseSound = false;
     for (int thisNote = 0; thisNote < 3; thisNote++) {
  
      //要计算音符持续时间,请花费一秒钟 
      //除以音符类型。
      int noteDuration = 250/loseNoteDurations[thisNote];
      tone(13, lose[thisNote],noteDuration);
  
      //为了区分音符,请在它们之间设置最短时间。
      //笔记的持续时间+ 30%似乎效果良好:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
      //停止音调播放:
      noTone(13);
    }
  }
  
  if (millis() - gameOverTime < 3000) {  / //重新启动之前的时间
    延迟(250 );
    delay(250);
  } else {
    restart();  
  }
  

}

void restart() {
  //重置所以布尔值
  enemyWon = false;
  enemyWaiting = false;
  enemyFired = false;
  enemyBulletCollision = false;
  
  levelAni = true;
  levelStart = false;  
  levelComplete = false;
  levelsArrayIndex = 0;
  
  loseSound = true;
  
  //重置所以级别
  for (int level = 0; level<_lvls; level++) {
     for (int x = 0; x<8; x++) {
       for (int y = 0; y<8; y++) {
         levels[level][x][y] = initial[level][x][y];
       }
     }
   }

  aniTime = millis();  //运行一级动画
};

加入微信技术交流群

技术交流,职业进阶

关注与非网服务号

获取电子工程师福利

加入电路城 QQ 交流群

与技术大牛交朋友

讨论