Project tutorial
Space Invaders Game on 8x8 Homemade LED Matrix

Space Invaders Game on 8x8 Homemade LED Matrix © GPL3+

The goal is to defeat wave after wave of descending aliens with a horizontally moving laser to earn as many points as possible.

  • 2 views
  • 0 comments
  • 0 respects

Components and supplies

Necessary tools and machines

09507 01
Soldering iron (generic)
4966285
Solder Wire, Lead Free

Apps and online services

About this project

Space Invaders is a 1978 arcade game created by Tomohiro Nishikado. The goal is to defeat wave after wave of descending aliens with a horizontally moving laser to earn as many points as possible.

On the given video I will show you how to make a Space Invaders game on a homemade 8x8 LED matrix.

The device is very simple to build and contains only a few components:

- Arduino Nano microcontroller

- 8x8 LED matrix

- 10 Kiloohms Potentiometer

- Buzzer

- and Momentary switch

The matrix contains 64 pieces, 5 mm LEDs that are mounted on an Alumil plate with a thickness of 4 mm. On the front of the matrix is placed a white plexiglass with a thickness of 1 mm which serves as a light diffuser.The idea for this project as well as the code are taken from the "elvinlee" page, where you can see the original project.

The potentiometer is used to move the weapon left and right, and with the button we fire laser beams. The game is accompanied by appropriate sounds similar to those of the original. Also it contains several levels and with each new level the speed increases. In this case the power supply is external but the battery can also be mounted, so we get an independent game console.

Finally, the assembly is mounted in a suitable box made of PVC plastic with a thickness of 3 and 5 mm, coated with colored self-adhesive wallpaper.

Code

Arduino codeC/C++
Binary file (no preview)/*========================================================*/
/*
05-833 Applied Gadgets, Sensors and Activity Recognition in HCI
Class by Scott Hudson
Carnegie Mellon University
Spring 2012

*SpaceVaders* by Elwin Lee
Entertainment Technology Center
Carnegie Mellon University

Credits:
Drive matrix pattern http://arduino.cc/playground/Main/DirectDriveLEDMatrix
Play tones through speaker http://arduino.cc/en/Tutorial/Tone
*/
/*========================================================*/

#include "pitches.h"

/****TESTING****/
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} 
};

/*** Level 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}  \
}

/*** Level 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}  \
}

/*** Level 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}  \
}

/*** WIN ***/
#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}  \
}


/*** GENERAL ***/
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

// 2-dimensional array of pixels in LED Matrix:
int pixels[8][8];  

int loopDelay = 2;

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

int levelsArrayIndex = 0;

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

//copy of levels array for resetting purposes
byte initial[_lvls][8][8] = { 
  level1_ani, level1, level2_ani, level2, level3_ani, level3, win
};

/*** SOUND ***/
int boom = NOTE_C4;

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

/*** TIMERS ***/
unsigned long aniTime;
unsigned long completeTime;
unsigned long enemyTime;
unsigned long gameOverTime;

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

int bulletDelayCount = 0;
boolean fired = false;


/*** CONTROLS ***/
int btnPin = A5;
int potPin = A6;
int potVal;

boolean btnDown = false;

/*** ENEMY ***/
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;

/*** SHIFTING ***/
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);
  // initialize the I/O pins as outputs:

  // iterate over the pins:
  for (int thisPin = 0; thisPin < 8; thisPin++) {
    // initialize the output pins:
    pinMode(cols[thisPin], OUTPUT); 
    pinMode(rows[thisPin], OUTPUT);  
    // take the col pins (i.e. the cathodes) high to ensure that
    // the LEDS are off: 
    //both HIGH so no connection
    digitalWrite(cols[thisPin], HIGH);
    digitalWrite(rows[thisPin], HIGH);  
  }
  
  //set button and potentio meter as input
  pinMode(btnPin, INPUT);
  pinMode(potPin, INPUT);

  clearLeds();  //clear LED Matrix
//  shiftLevel = true;
  aniTime = millis();  //start level # animation timer
  
}

void loop() {
  
  /***reset all to no circuit***/
  for (int i = 0; i < 8; i++) {
    digitalWrite(rows[i], HIGH);  //all rows to high
    digitalWrite(cols[i], LOW);
  }
  
  
    
  /***Row 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);  //create levels
  
  /***Row 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();  //play animation

  /***Row 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();  //read potentiometer value

  /***Row 3***/
  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();  //update player's position based on potentiometer value
  if (levelStart) readBtn();      //read button state
  
  /***Row 4***/
  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();  //get highest row # of enemy and fire bullet
  
  /***Row 5***/
  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();  //check all pixels of the level are gone
  if (levelComplete) levelFinished();                //win level

  
  /***Row 6***/
  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();  //shift pixels in the level
  
  /***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();  //lose if hit by enemy
  updatePixels();  //update all pixels of the LED Matrix 

}

void clearLeds() {
  // Clear display array
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      pixels[i][j] = 0;
    }
  }
}

/*** Populate Level on LED Matrix***/
void setPattern(int pattern) {
  
  if (levelsArrayIndex < 7) {  //if not last level
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < 8; j++) {
        if ( levels[levelsArrayIndex][i][j] == 1 ) {  //copy only "ones" to temporary matrix
          tempMatrix[i][j] = levels[levelsArrayIndex][i][j];  
        }
      }
    }
  } else {
    restart();  //restart if end of the game has been reached
  }
  
}


/***READ POTMETER***/
void readPot() {
  potVal = analogRead(potPin);      //read potentiometer value
  potVal = map(potVal, 0, 1024, 0, 6);  //map 1023 to 6 values for LED Matrix; 
                                          //only column 0~6 are used to display player
                                          //raise max_in and max_out by one for even value distribution http://arduino.cc/forum/index.php?topic=72153.0  
}
/*** Refresh PLAYER ***/
void refreshPlayer() {

  byte _playerRows[2][8] = {   //temp array to store player's position
    {0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0}
  };
  
  //draw player pixels
  _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++) {     //rows 6-7 (where the player is)
    for (int j = 7; j >= 0; j--) {  //update player positions
       if(_playerRows[i-6][j] == 1) {  //copy only "ones" to temporary matrix
         tempMatrix[i][j] = _playerRows[i-6][j];
       }
    }
  } 
}


/***READ BUTTON***/
void readBtn() {
  
  int btnPress = digitalRead(btnPin);  //read button state
  if (btnPress == 1 && !fired && !btnDown){      //if button is pressed
    bulletCol = potVal+1;      //bullet column value on matrix
    btnDown = true;
    fired = true;
  } 
  if (btnDown) {
    if (btnPress == 0) {
      btnDown = false;
    }  
  }
  if (fired) {   
    shoot(bulletCol);    //play shoot animation
  } 
}

/*** SHOOT ***/
void shoot(int _bulletCol) {
  
  if (bulletDelayCount == 2) {    //act as a delay & determines bullet's speed
    bulletRow--;
    
    if (bulletRow < 0) {  //if bullet reaches top (row 0)
      bulletRow = 5;    //reset bullet row position
      fired = false;    //bullet fire done
    } else {
      if (tempMatrix[bulletRow][_bulletCol] == 0) {  //check if next pixel position is empty or not
        tempMatrix[bulletRow][_bulletCol] = 1;  //new bullet pixel position and turn on
      } else {
        collisionBullet(bulletRow, _bulletCol);  //bullet collides with pixel
      }
     }
  } else {
    tempMatrix[bulletRow][_bulletCol] = 1;  //draw bullet pixel
  }
  bulletDelayCount = (bulletDelayCount+1) % 3;  //bullet's speed counter
  
}
/*** BULLET COLLISION ***/
void collisionBullet(int _row, int _col) {
  int boomNoteDuration = 1000/4;      //sound duration
  tone(13, boom, boomNoteDuration);      //play sound when hit
//  noTone(13);
  levels[levelsArrayIndex][_row][_col] = 0;    //remove 1 pixel that got shot from original level matrix
  tempMatrix[_row][_col] = 0;  //update temp matrix for pixel display
  
  bulletRow = 5;    //set original bullet row position back to 5
  fired = false;    //bullet fire done
}


/*** READ ENEMY ***/
void readEnemy() {
  
  if (!enemyWaiting && !enemyFired && !enemyBulletCollision){  //if enemy isn't doing anything
    enemyTime = millis();  //start timer
    enemyWaiting = true;
  }
  
  if (enemyWaiting) {
    if (millis() - enemyTime > enemyAttackSpeed[levelsArrayIndex]) {  //attack speed for each level according to array 
      
      int _row = 3;   //temp row value
      boolean dobreak = false;    //for double break;
      
      //loop to get the enemy's pixels of highest row (closest to the player) 
      for (int i = 3; !dobreak && i >= 0; i--) {  //backwards loop to get highest row
        for (int j = 0; j < 8; j++) {
            if(levels[levelsArrayIndex][i][j] == 1) {  //if a "one" is found in the row
              _row = i;          //save row index
              enemyBulletRow = _row + 1;  //value to put enemy bullet 1 row below enemy
              dobreak = true;    //double break;
              break;
            }
         }  
      }
      
      enemyBottomCount = 0; //counter for number of "one" pixels in highest row (closest to the player) 
      for (int c = 0; c < 8; c++) {  //loop through highest row
        if(levels[levelsArrayIndex][_row][c] == 1) {   //check if column contains "one" 
          enemyBulletArray[enemyBottomCount][0] = _row;  
          enemyBulletArray[enemyBottomCount][1] = c;
          enemyBottomCount++;  
        }
      }
       
      enemyWaiting = false;
      enemyFired = true;  //fire enemy bullet
      randomBullet = random(enemyBottomCount);  //randomly select one of the column pixels
    }
  }
  
  if (enemyFired) {
    if (enemyBulletDelayCount == (enemyBulletSpeed[levelsArrayIndex]-1)) {  //enemy bullet speed (higher value = slower)
      enemyBulletArray[randomBullet][0]++;  //row + 1
      if  (enemyBulletArray[randomBullet][0] > 7) {  //if bullet reaches bottom
        enemyBulletDelayCount = 0;  //reset and remove bullet
        enemyFired = false;
      } else {
        if (tempMatrix[enemyBulletArray[randomBullet][0]] [enemyBulletArray[randomBullet][1]] == 0) {  //if next row is empty
          tempMatrix[enemyBulletArray[randomBullet][0]] [enemyBulletArray[randomBullet][1]] = 1;  //bullet claims row
        } else {  //bullet hit something!!
          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;
  }
}




/*** SHIFTING LEVEL ***/
void shiftRow() {  //testing purposes
  int _speed;
  if (levelsArrayIndex == 3) {
      _speed = shiftSpeed[0];
  } else if (levelsArrayIndex == 5) {
      _speed = shiftSpeed[1];
  }
  byte _levelTemp[5][8] = {   //temp matrix array to store level pixel positions
        {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++) {    //store in temp array
    for (int j = 0; j < 8; j++) {
        _levelTemp[i][j] = levels[levelsArrayIndex][i][j];
    }
  }
  
  if (shiftCount == (_speed-1)) {  //delay before shifting (roughly 100*18ms)
    if (shiftLeft == true) {  //shift left
      //loops through top 5x8 of the matrix
      for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 8; j++) {
          if (j == 7) {     //prevents shifting column index 8 which doesn't exist
            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) {  //shift down
      for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 8; j++) {
          if ( i == 0 ) {    //prevents shifting row index -1 which doesn't exist
            levels[levelsArrayIndex][i][j] = 0;
          } else {
            levels[levelsArrayIndex][i][j] = _levelTemp[i-1][j];  //shift down
          }
        }
      }
      shiftDown = false;
      shiftRight = true;
     } else if (shiftRight == true) {  //shift right
        for (int i = 0; i < 5; i++) {
          for (int j = 7; j >= 0; j--) {
            if (j == 0) {     //prevents shifting column index -1 which doesn't exist
              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) {  //shift up
        for (int i = 0; i < 5; i++) {
          for (int j = 0; j < 8; j++) {
            if ( i == 4 ) {  //prevents shifting row index 5
              levels[levelsArrayIndex][i][j] = 0;
            } else {
              levels[levelsArrayIndex][i][j] = _levelTemp[i+1][j];  //shift down
            }
          }
        }
        shiftUp = false;
        shiftLeft = true;
      }
    }
    shiftCount = (shiftCount+1) % _speed;  //shifting delay
  
}




/*** PLAY LEVEL NUMBER ANIMATION ***/
void playLevelAni() {
  
  
  if (millis() - aniTime < 3000) {  //time before transition from level number to actual level    
//    if (levelsArrayIndex < 6 && millis() - aniTime > 3750) {  //3000
//      delay(500);
//    } 
  } else {
    levelAni = false;  //end animation
    levelStart = true;

    
    levelsArrayIndex++;
    if (levelsArrayIndex == 3 || levelsArrayIndex == 5) {  //if level 2 or 3, initiate shifting
      shiftLeft = true;
      shiftDown = false;
      shiftRight = false;
      shiftUp = false;
      shiftLevel = true;
    } else {
      shiftLevel = false;
    }
    clearLeds();
    
  }
}

void checkLevelState() {  //check if all level pixels (enemies) are dead
  int _countLevelPixels = 0;
  for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 8; j++) {
      if(levels[levelsArrayIndex][i][j] == 1){
        _countLevelPixels++;  //count the number of "one" pixels
      }
    }  
  }
  if((_countLevelPixels) == 0){  //if nothing left, congratz! you beat the level!
//    digitalWrite(13, HIGH);
//    Serial.println("COMPLETE!");
    completeTime = millis();
    levelComplete = true;
  }  
}

void levelFinished() { 
  
  if (millis() - completeTime > 2000) {  //time before transitioning to next level
  
    //reset all booleans
    enemyWaiting = false;
    enemyFired = false;
    enemyBulletCollision = false;

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


/*** UPDATE PIXEL MATRIX ***/
void updatePixels() {
  //Use temporary 8x8 matrix to update actual matrix to prevent any bugs
  //Tends to get buggy when apply values straight to pixels[] matrix 
  //Instead, storing all matrix values in a temp and apply values to pixels[] at once is more stable
  
  //copy all temp matrix values to actual display matrix
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      pixels[i][j] = tempMatrix[i][j]; 
    }
  }
  
  //reset all values for temp matrix
  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++) {
  
      // to calculate the note duration, take one second 
      // divided by the note type.
      int noteDuration = 250/loseNoteDurations[thisNote];
      tone(13, lose[thisNote],noteDuration);
  
      // to distinguish the notes, set a minimum time between them.
      // the note's duration + 30% seems to work well:
      int pauseBetweenNotes = noteDuration * 1.30;
      delay(pauseBetweenNotes);
      // stop the tone playing:
      noTone(13);
    }
  }
  
  if (millis() - gameOverTime < 3000) {  //time before restarting
    delay(250);
  } else {
    restart();  
  }
  

}

void restart() {
  //reset all booleans
  enemyWon = false;
  enemyWaiting = false;
  enemyFired = false;
  enemyBulletCollision = false;
  
  levelAni = true;
  levelStart = false;  
  levelComplete = false;
  levelsArrayIndex = 0;
  
  loseSound = true;
  
  //reset all levels
  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();  //run level 1 animation 
};
pitches.hC/C++
No preview (download only).

Schematics

Schematic diagram
Schematic wusop3hjek

Comments

Similar projects you might like

DIY 37 LED Roulette Game

Project tutorial by Mirko Pavleski

  • 2,699 views
  • 3 comments
  • 5 respects

Arduino Pong Game on 24x16 Matrix with MAX7219

Project tutorial by Mirko Pavleski

  • 6,353 views
  • 6 comments
  • 22 respects

LED Roulette Game

Project tutorial by Arduino “having11” Guy

  • 18,505 views
  • 8 comments
  • 25 respects

Arduino Word Clock on 8x8 RGB LED Matrix

Project tutorial by Mirko Pavleski

  • 9,405 views
  • 4 comments
  • 30 respects

8x8 Dot Matrix

Project tutorial by RoboCircuits

  • 8,092 views
  • 2 comments
  • 9 respects
Add projectSign up / Login