Hardware components | ||||||
| × | 1 | ||||
| × | 64 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
| ||||||
Hand tools and fabrication machines | ||||||
| ||||||
|
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.
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
};
Comments