Eleanor's Final Project

From CSclasswiki
Jump to: navigation, search

Project Proposal

I am choosing to do the Arduino only option. My project idea is to utilize the 8x8 grid and the joystick to create the game Snake, and for Part 3 to use the 8x8 grid, the joystick, and the button to recreate space invaders.

Part 1: Name Print

The name printing aspect was a fairly straightforward introduction to using the 8x8 LED screen

Helpful Links

Video Tutorial with links to example code: https://www.youtube.com/watch?v=TOuKnOG8atk

Libraries

LedControl: https://randomnerdtutorials.com/guide-for-8x8-dot-matrix-max7219-with-arduino-pong-game/

Schematic

*All schematics using photos from https://www.arduino.cc/en/Tutorial/MultiSerialMega and https://educ8s.tv/arduino-8x8-led-matrix-tutorial/
Pt1scheme.png

Code

#include <LedControl.h>

int DIN = 12;
int CS =  11;
int CLK = 10;

//obtained binary letter values from : https://create.arduino.cc/projecthub/SAnwandter1/programming-8x8-led-matrix-23475a
byte A[] = {  B00000000,B00111100,B01100110,B01100110,B01111110,B01100110,B01100110,B01100110};
byte E[] = {B00000000,B00111100,B00100000,B00111000,B00100000,B00100000,B00111100,B00000000};
byte L[] = {B00000000,B00100000,B00100000,B00100000,B00100000,B00100000,B00111100,B00000000};
byte R[] = {B00000000,B00111000,B00100100,B00100100,B00111000,B00100100,B00100100,B00000000};
byte N[] = {B00000000,B00100010,B00110010,B00101010,B00100110,B00100010,B00000000,B00000000};
byte O[] = {B00000000,B00111100,B01000010,B01000010,B01000010,B01000010,B00111100,B00000000};


LedControl lc=LedControl(DIN,CLK,CS,0);

void setup(){
 lc.shutdown(0,false);       //The MAX72XX is in power-saving mode on startup
 lc.setIntensity(0,15);      // Set the brightness to maximum value
 lc.clearDisplay(0);         // and clear the display
}

void loop(){ 

    printByte(E);
     
    delay(1000);

    printByte(L);
    
    delay(1000);

    printByte(E);    

    delay(1000);
   
    printByte(A);    

    delay(1000);
    printByte(N);    

    delay(1000);
    printByte(O);    

    delay(1000);
    printByte(R);    

    delay(1000);
   
    lc.clearDisplay(0);
    
    delay(1000);
}


void printByte(byte character [])
{
  int i = 0;
  for(i=0;i<8;i++)
  {
    lc.setRow(0,i,character[i]);
  }
}


Part 2: Addition of Sensor - Snake Game

Description of Project

The inspiration for the project was the Snake genre of videogames, an overview of which is given here: https://en.wikipedia.org/wiki/Snake_(video_game_genre)

The basic rules of the game consist of a player-controlled pixel with a tail that grows in length by a single pixel each time the snake consumes an "enemy" pixel. The snake cannot self-intersect or fall off the edge of the map.

The final idea ended up utilizing the IR sensor in the Elegoo kit controlling the snake using the up/down/side arrow keys on a typical Comcast TV remote.

Libraries

LinkedList: https://github.com/ivanseidel/LinkedList IRremote : given by Elegoo kit included libraries IRremoteInt: given by Elegoo kit included libraries

Working Notes / Thought Process

-Tried to use vectors, cant use in arduino. Originally wanted to use some sort of hashmap to make lookup for enemy spawning faster, problem is that we need to make sure the enemy won’t spawn on the snake. -Instead I know the longest the snake could be is 64 units so it won’t be super inefficient to store the presized array. -Will just need to track size to find head and tail. -array wont work because I need to be able to erase from the tail, so the presized nature would make that inconvenient -use a linkedlist instead -couldn’t get array to work inside linked list, will just add row, col instead as separate ints - originally intended to use joystick sensor, but this ended up seeming inconvenient as well and not as true to the function of the joystick which can record a variety of positions between x = 0 --> 1024 and y = 0 --> 1024, allowing for less restricted movement - fun idea that works better with snake would be to use IR remote - IR remote included with Elegoo kit yields inconsistent results (same button shows multiple codes) so I decided to use my TV remote which I figured would be slightly more reliable

Helpful Links and Why They Are Helpful

Pong Game: https://randomnerdtutorials.com/guide-for-8x8-dot-matrix-max7219-with-arduino-pong-game/ - this link was helpful as it showed how a single LED could be manipulated, also showed that game simulation was possible using the Arduino and 8x8 matrix

IRremote Project: https://create.arduino.cc/projecthub/ingo-lohs/first-test-super-starterkit-from-elegoo-infrared-ab4272 - this link was helpful for digging into the function and usage of the IR remote sensor included with the Elegoo kit

How to Reset Arduino in Software: https://www.instructables.com/id/two-ways-to-reset-arduino-in-software/ - this link was helpful as I wanted to be able to have the game reset itself if the player lost. It didn't really matter if it was a software or hardware fix, but the software approach was easy enough and obviously included no additional hardware

Schematic

Part2schematic.png

Code

/*
 Created by Eleanor Donaher
*/

#include "LedControl.h"
#include <LinkedList.h>
#include "binary.h"
#include  <IRremote.h>
#include <IRremoteInt.h>

/*
 DIN connects to pin 12
 CLK connects to pin 11
 CS connects to pin 10 
*/
//setup led
LedControl lc=LedControl(12,11,10,1);
int receiver = 7; //setup IR Reciever
IRrecv irrecv(receiver);
decode_results results; //instance of decode results
//enemy x and y
int enemy_x = 1;
int enemy_y = 2;
LinkedList<int> snake_position = LinkedList<int>();
 //boolean to report collision (initially set to true so enemy will randomly spawn)

boolean collision = false;
boolean headCollision = false; 
//direction snake is going, initially right
// (up = 0, down = 1, left = 2, right = 3)
int snake_dir = 3;
//findrow = x/10
//findcol = x%10
int gameDelay = 400;


void setup() {
  Serial.begin(9600);
  //start reciever
  irrecv.enableIRIn();
  lc.shutdown(0,false);
  // Set brightness to a medium value
  lc.setIntensity(0,8);
  // Clear the display
  lc.clearDisplay(0); 

  //set snake's initial position

  //head
  snake_position.add(31);
  //tail
  snake_position.add(30);
  //render initial snake

  lc.setLed(0,3,1,1);
  lc.setLed(0, 3, 0, 1);
  //render initial enemy
  lc.setLed(0,1,2, 1);
  
}
void(* resetFunc) (void) = 0;//declare reset function at address 0


//track if spawn failed
boolean failedSpawn = false;
void loop(){
  
  //reset collisions to false
  if(!failedSpawn){
    collision = false;
}
  
  headCollision = false;
  //record previous head
  int prev_head_position = snake_position.get(0);
  int prev_head_x = prev_head_position/10;
  int prev_head_y = prev_head_position%10;

  //check for reciever input
  if (irrecv.decode(&results)){
    //down
    if(results.value==1511671869){
      if(snake_dir!=0){
        snake_dir=1;
      }
    }
    if(results.value==741245183){
      if(snake_dir!=1){
        snake_dir=0;
      }
    }
    if(results.value==2507695210){
      if(snake_dir!=3){
        snake_dir=2;
      }
    }
    if(results.value==3692585004){
      if(snake_dir!=2){
        snake_dir=3;
      }
    }
    irrecv.resume(); //recieve next value
  }
//update snake position
  int new_snake_head;
  if(snake_dir == 0){
    new_snake_head = prev_head_position-10; 
  }
  if(snake_dir == 1){
    new_snake_head = prev_head_position+10;
  }
  if(snake_dir == 2){
    new_snake_head = prev_head_position-1;
  }
  if(snake_dir == 3){
    new_snake_head = prev_head_position+1;
  }
 //add new head to snake
  snake_position.unshift(new_snake_head);
  //light new LED
  int new_snake_x = new_snake_head/10;
  int new_snake_y = new_snake_head%10;
  lc.setLed(0, new_snake_x, new_snake_y, 1);

 //check for collision
  if(new_snake_x == enemy_x && new_snake_y == enemy_y){
    //collision detected
    collision = true;
    headCollision = true;
  }

 //if there was not a head collision, unlight tail LED and remove it from list
  if(!headCollision){
    int snake_tail = snake_position.pop();
    int tail_x = snake_tail/10;
    int tail_y = snake_tail%10;
    lc.setLed(0, tail_x, tail_y, 0);
 }

 //if snake falls off board, game over
  if(new_snake_x > 7 || new_snake_x <0 || new_snake_y > 7 || new_snake_y < 0){
    //you lose sucker!!!
     // sad face
    byte sf[8]= {B00111100,B01000010,B10100101,B10000001,B10011001,B10100101,B01000010,B00111100};

    //you lose sucker!!!
    // Display sad face
    lc.setRow(0,0,sf[0]);
    lc.setRow(0,1,sf[1]);
    lc.setRow(0,2,sf[2]);
    lc.setRow(0,3,sf[3]);
    lc.setRow(0,4,sf[4]);
    lc.setRow(0,5,sf[5]);
    lc.setRow(0,6,sf[6]);
    lc.setRow(0,7,sf[7]);
    delay(1000);
    resetFunc(); //call reset
  }

  //if snake self-intersects, game over
  for(int i = 1; i<snake_position.size(); i++){
    int snake_xy = snake_position.get(i); 
    if(new_snake_head == snake_xy){
      //also game over sucker!!!  
        // sad face
      byte sf[8]= {B00111100,B01000010,B10100101,B10000001,B10011001,B10100101,B01000010,B00111100};
  
      //you lose sucker!!!
      // Display sad face
      lc.setRow(0,0,sf[0]);
      lc.setRow(0,1,sf[1]);
      lc.setRow(0,2,sf[2]);
      lc.setRow(0,3,sf[3]);
      lc.setRow(0,4,sf[4]);
      lc.setRow(0,5,sf[5]);
      lc.setRow(0,6,sf[6]);
      lc.setRow(0,7,sf[7]);
      delay(1000);
      resetFunc(); //call reset 
    }
  }//end self int check



  //if collision, respawn enemy
  if(collision == 1){   
    failedSpawn = false;
    //lc.setLed(0, enemy_x, enemy_y, 0);
    enemy_x = random(8);
    enemy_y = random(8);
    collision = false;
    for(int i =0; i<snake_position.size(); i++){
      int snake_xy = snake_position.get(i);
      int snake_x = snake_xy/10;
      int snake_y = snake_xy%10;
      //if the enemy is on top of the snake
      if(enemy_x==snake_x && enemy_y==snake_y){
        failedSpawn = true;
        collision=true;
      }//
    }//endpositionCheckfor
  //update enemy rendering
  lc.setLed(0, enemy_x, enemy_y, 1);
  }//end collisionIf
  //
  delay(gameDelay);
}
  • NOTE: To use game with a different remote, follow tutorial at link on IRremote usage to find that remote's individual codes, then substitute for given codes

Part 3: Space Invaders

Project Proposal

Space Invaders is a well known arcade game from 1978, information on it can be found at this Wikipedia page: https://en.wikipedia.org/wiki/Space_Invaders the basic tenants of the game include rows of descending enemies who shoot at a player at the bottom of the screen. The player can move left and right to evade the enemies shots, with barriers to duck behind. The player attempts to shoot all the enemies without getting shot themselves and before the enemies can reach the bottom of the screen. This implementation involves yet again using the IRremote signal to move the player left and right, and the pushbutton to fire.

Helpful Links

Same as part 2

Libraries

Same as part 2

Working Notes

-The same as the snake game, linkedlists will be super important for this application, as it involves a lot of tracking, updating, removing, and dynamically resizing lists for enemy pixels, enemy and player shots, and the barriers - barriers can withstand 3 shots before being destroyed, can be destroyed by player as well - first big problem encountered was with the pushbutton. At first, I was doing the timing the same as the snake game, implementing a 1s delay at the end of the loop to make the game playable. This wasn't working for the firing because it would only check once per loop if the button was pressed at the exact moment it was checked, not if it had been pressed during the loop -overcame this by doing the delay more dynamically, entire loop runs as a for loop updating every 2ms to check if the button has been fired. I was then able to dynamically time the shooting for enemies and players by having the updateShot called at variable intervals - expensive to check all necessary lists in nested for loops each iteration, but I figure it can't be super expensive because at most each shooting list will have maybe 3 entries at a time, so I figured it wasn't terribly inefficient. - main issue in game was with timing everything correctly and having enemies fire with correct timing.

Schematics

Part3schematic.png

Code

/*
 Created by Eleanor Donaher
*/

#include "LedControl.h"
#include <LinkedList.h>
#include "binary.h"
#include  <IRremote.h>
#include <IRremoteInt.h>

/*
 DIN connects to pin 12
 CLK connects to pin 11
 CS connects to pin 10 
*/
//setup led
LedControl lc=LedControl(12,11,10,1);
int receiver = 7; //setup IR Reciever
IRrecv irrecv(receiver);
decode_results results; //instance of decode results
//enemy List 
LinkedList<int> enemyList = LinkedList<int>();
LinkedList<int> playerShotList = LinkedList<int>();
LinkedList<int> enemyShotList = LinkedList<int>();
//how to manipulate enemy movement (so is it going left or right)
int enemyDir;
int delayTimer;
//barrier position List
LinkedList<int> barrierPositions = LinkedList<int>();
LinkedList<int> barrierStrengths = LinkedList<int>();
//function to resetgame
void(* resetFunc) (void) = 0;//declare reset function at address 0
int delayPlayerShots = 0;
int delayEnemyShots = 0;
//player position
int playerPosition;
//findrow = x/10
//findcol = x%10

void setup() {
  Serial.begin(9600);
  //start reciever
  irrecv.enableIRIn();
  lc.shutdown(0,false);
  // Set brightness to a medium value
  lc.setIntensity(0,8);
  // Clear the display
  lc.clearDisplay(0); 


//initialize button
  pinMode( 53, INPUT_PULLUP );

 //create barriers
 barrierPositions.add(62);
 barrierPositions.add(64);
 barrierPositions.add(66);
 barrierStrengths.add(3);
 barrierStrengths.add(3);
 barrierStrengths.add(3);
//create enemies

  enemyList.add(01);
  enemyList.add(11);
  enemyList.add(02);
  enemyList.add(12);
  enemyList.add(03);
  enemyList.add(13);
  enemyList.add(04);
  enemyList.add(14);
  enemyList.add(05);
  enemyList.add(15);

//add enemies to board
  for(int i = 0; i<enemyList.size(); i++){
    int enemy = enemyList.get(i);
    //dont place enemies that are not displayed yet
    if(enemy>=0){
    lc.setLed(0,enemy/10,enemy%10,1);
    }
  }
//start enemies going right
  enemyDir=1;
//add barriers to board
  lc.setLed(0,6,2,1);
  lc.setLed(0,6,4,1);
  lc.setLed(0,6,6,1);

//set initial playerPosition and add to board
  playerPosition = 75;
  lc.setLed(0,7,5,1); 

}


//void(* resetFunc) (void) = 0;//declare reset function at address 0
//if we have handled edge case
boolean handled = false;

void handlePlayerMovement(){
   //check for reciever input
  if (irrecv.decode(&results)){
    //moveLEFT
    if(results.value==2507695210){
      //if we are not all the way to the left
      if(playerPosition%10!=0){
      //unlight previous position
        lc.setLed(0, playerPosition/10, playerPosition%10,0);
        //update new position
        playerPosition = playerPosition-1;
        lc.setLed(0, playerPosition/10, playerPosition%10,1);
      }
    }
    //moveRIGHT
    if(results.value==3692585004){
      //if we are not already all the way to the right
      if(playerPosition%10!=7){
        //unlight previous position
        lc.setLed(0, playerPosition/10, playerPosition%10,0);
        //update new position
              //update new position
        playerPosition = playerPosition+1;
        lc.setLed(0, playerPosition/10, playerPosition%10,1);
      }
    }
    irrecv.resume(); //recieve next value
  }
}//endHandlePlayerMovement
void editBarrier(int barrierPosition){
  //subtract 1 from barrier strength, if it is destroyed, unlight the LED and remove it from the map
  int i = 0;
  for(i; i<barrierPositions.size(); i++){
    if(barrierPosition==barrierPositions.get(i)){
      break;
    }
  }
  int barrierStrength = barrierStrengths.get(i);
  barrierStrength = barrierStrength-1;
  if(barrierStrength>0){
    barrierStrengths.set(i,barrierStrength);
  }
  //otherwise unlight LED barrier is dead
  else{
    int barrier = barrierPositions.get(i);
    lc.setLed(0, barrier/10, barrier%10, 0);
    barrierStrengths.remove(i);
    barrierPositions.remove(i);
  }

}
LinkedList<int> enemyToRemove = LinkedList<int>();
LinkedList<int> playerToRemove = LinkedList<int>();
void newEnemyShots(){ 
  //decides if enemy will fire new shot, happens a bit less than once per second
  int willEnemyShoot = random(0,300);
  if(willEnemyShoot==1){
    int chooseShotIndex = random(0,enemyList.size());
    enemyShotList.add(enemyList.get(chooseShotIndex)); // add new shot to list of enemy shots currently on the board
  }
  //check if any enemy shots overlap with player shots
  //if we need to remove it, add it to this lis
}//endHandleShooting

void registerPlayerShot(){
  //add to player shot list
  //unless player shoots into barrier
  boolean hitBarrier = false;
  for(int i=0; i<barrierPositions.size(); i++){
    if(playerPosition == barrierPositions.get(i)){
      hitBarrier = true;
      //edit barrier and send position of barrier to edit
      editBarrier(playerPosition);
    }
  }
  if(!hitBarrier){
    playerShotList.add(playerPosition);        
  }

}


   //check if playerShot hit enemy1, playershot goes off board1, enemyshot goes off board1, enemyshot hits barrier, enemyshot hits player, 
void checkOverlaps(){
  //check playershot hits enemy
  boolean enemyHit = false;
  int playerShotIndexToRemove = 0;
  int enemyIndexToRemove = 0;
  for(int i=0; i<playerShotList.size(); i++){
    int playerShot = playerShotList.get(i);
    for(int j = 0; j<enemyList.size(); j++){
      int enemy = enemyList.get(j);
      //if playershot hits enemy

      if(playerShot==enemy){
        //set them both to be removed
        enemyHit=true;
        enemyIndexToRemove = j;
        playerShotIndexToRemove = i;
        break;
      }
    }//endinnerfor
    //remove enemy&playershot
    if(enemyHit){
      int enemytoRemove = enemyList.get(enemyIndexToRemove);
      int playershottoremove = playerShotList.get(playerShotIndexToRemove);
      lc.setLed(0, playershottoremove/10, playershottoremove%10, 0);
      //lc.setLed(0, enemyIndexToRemove/10, enemyIndexToRemove%10, 0);
      enemyList.remove(enemyIndexToRemove);
      playerShotList.remove(playerShotIndexToRemove);
    }
  }//endPlayerShotListFor

  //check playershot off board
  int playershotindextoremove = 0;
  boolean shotoffboard = false;
  for(int i=0; i<playerShotList.size(); i++){
    if(playerShotList.get(i)<0){
      playershotindextoremove = i;
      shotoffboard = true;
      break;
    }
  }
  if(shotoffboard){
    int shot = playerShotList.get(playershotindextoremove);
    lc.setLed(0, shot/10, shot%10, 0);
  }
  
 //check enemyshot off board
  int enemyshotindextoremove = 0;
  shotoffboard = false;
  for(int i=0; i<enemyShotList.size(); i++){
    if(enemyShotList.get(i)<0){
      enemyshotindextoremove = i;
      shotoffboard = true;
      break;
    }
  }
  if(shotoffboard){
    int shot = enemyShotList.get(enemyshotindextoremove);
    lc.setLed(0, shot/10, shot%10, 0);
  }
  //removePlayerShot(hit enemy or off board)

  boolean hitBarrier = false;
  int shotToRemove = 0;
  for(int i = 0; i<enemyShotList.size(); i++){
    for(int j = 0; j<barrierPositions.size(); j++){
      if(barrierPositions.get(j)==enemyShotList.get(i)){
        //deal with barrier
        editBarrier(barrierPositions.get(j));
        shotToRemove = i;
        hitBarrier=true;
        break;
      }
    }
  }//endouterfor
  if(hitBarrier){
    //remove that shot
    enemyShotList.remove(shotToRemove);
  }
  //check if playershot hits enemyshot
  int enemyShotToRemove = 0;
  int playerShotToRemove = 0;
  boolean conflict = false;
  for(int i = 0; i<enemyShotList.size(); i++){
    for(int j = 0; j<playerShotList.size(); j++){
      if(enemyShotList.get(i)==playerShotList.get(j)){
        conflict = true;
        enemyShotToRemove = i;
        playerShotToRemove = j;
        break;
      }
    }
  }//end outerFor

  //remove player and enemy shots if conflict
  if(conflict){
    int unlight = enemyShotList.get(enemyShotToRemove);
    lc.setLed(0, unlight/10, unlight%10, 0);//unlight hit led
    enemyShotList.remove(enemyShotToRemove);
    playerShotList.remove(playerShotToRemove);
  }

  //check enemyHitsPlayer
  for(int i=0; i<enemyShotList.size(); i++){
    if(enemyShotList.get(i)==playerPosition){
      //player loses!!!
            //enemies win
       byte sf[8]= {B00111100,B01000010,B10100101,B10000001,B10011001,B10100101,B01000010,B00111100};

      //you lose sucker!!!
      // Display sad face
      lc.setRow(0,0,sf[0]);
      lc.setRow(0,1,sf[1]);
      lc.setRow(0,2,sf[2]);
      lc.setRow(0,3,sf[3]);
      lc.setRow(0,4,sf[4]);
      lc.setRow(0,5,sf[5]);
      lc.setRow(0,6,sf[6]);
      lc.setRow(0,7,sf[7]);
      delay(1000);
      resetFunc(); //call reset
    }
  }
}//endmethod

  //check if enemies hit bottom, or if there are no enemies left
void checkEndgame(){
  for(int i = 0; i<enemyList.size(); i++){
    if(enemyList.get(i)/10 == 7){
      //enemies win
       byte sf[8]= {B00111100,B01000010,B10100101,B10000001,B10011001,B10100101,B01000010,B00111100};

      //you lose sucker!!!
      // Display sad face
      lc.setRow(0,0,sf[0]);
      lc.setRow(0,1,sf[1]);
      lc.setRow(0,2,sf[2]);
      lc.setRow(0,3,sf[3]);
      lc.setRow(0,4,sf[4]);
      lc.setRow(0,5,sf[5]);
      lc.setRow(0,6,sf[6]);
      lc.setRow(0,7,sf[7]);
      delay(1000);
      lc.clearDisplay(0);
      resetFunc(); //call reset
    }
  }//endfor

  if(enemyList.size()==0){
    //player wins!
    byte hf[8]= {B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100};
    // Display happy face
    lc.setRow(0,0,hf[0]);
    lc.setRow(0,1,hf[1]);
    lc.setRow(0,2,hf[2]);
    lc.setRow(0,3,hf[3]);
    lc.setRow(0,4,hf[4]);
    lc.setRow(0,5,hf[5]);
    lc.setRow(0,6,hf[6]);
    lc.setRow(0,7,hf[7]);
    delay(1000);
    resetFunc(); //call reset
  }
}//endCheckEndGame


  
void loop(){
  
//move enemies
  //if enemies are all the way to the left, move down and go right
  //if all the way to the right, move down and go left
  //if moving left but not at end, keep moving left
  //if moving right but not at end, keep moving right
  //each loop reset edge to false
  boolean edge = false;
  if((enemyList.get(0)%10 == 0) || (enemyList.get(enemyList.size()-1)%10)==7){
    //if we haven't already handled the case
    if(handled!=true){
      edge=true;
    }
  }
    //we are all the way to the right or left move down and change sign of enemyDir
    if(edge==true){
      for(int i=0; i<enemyList.size(); i++){
        //unlight old LED
        int oldEnemy = enemyList.get(i);
        lc.setLed(0, oldEnemy/10, oldEnemy%10, 0);
        //move down a row
        int newEnemy = oldEnemy+10;
        //set new value to enemy
        enemyList.set(i, newEnemy);
    }//endEnemyFor
    //change direction
    enemyDir = enemyDir*-1;
    handled = true;
  }//endIf

  if(edge!=true){
    //continue in the same direction (update values based on enemyDir)
    for(int i=0; i<enemyList.size(); i++){
      //unlight old LED
      int oldEnemy = enemyList.get(i);
      lc.setLed(0, oldEnemy/10, oldEnemy%10, 0);
      //move depending on enemyDir (left or right)
      int newEnemy = oldEnemy+enemyDir;
      //Serial.println(newEnemy);
      //set new value to enemy
      enemyList.set(i, newEnemy);
    }//endEnemyFor
    //reset handled
    handled = false;
  }
  //light new enemies
  for(int i=0; i<enemyList.size(); i++){
    int enemy = enemyList.get(i);
    lc.setLed(0, enemy/10, enemy%10, 1);
  }
//shooting aspect
  delayTimer = 0; //delay counter  
  int recoil = 0;//number of loops before player can fire again
  for(delayTimer; delayTimer<500; delayTimer++){
        //get button value
    handlePlayerMovement();
    delay(2);
    int val = digitalRead(53);
    Serial.println(val);
    if(val==0){
      if(recoil==0){
        registerPlayerShot();
        recoil = recoil+1; //add to recoil
      }
    }
    if(recoil!=0){
      recoil = recoil+1;
      if(recoil==100){
        recoil=0;
      }
    }

      //update shot positions
  if(delayPlayerShots==0){
    for(int i = 0; i<playerShotList.size(); i++){
      int shot = playerShotList.get(i);
      //if the shot is not on top of the player, unlight that led
      if(shot!=playerPosition){
        lc.setLed(0, shot/10, shot%10, 0);
      }
      //go up
      shot = shot-10;
      playerShotList.set(i, shot); //update shot position
      lc.setLed(0, shot/10, shot%10, 1); //light new LED
    }//endPlayerShotUpdateFor
    delayPlayerShots = delayPlayerShots+1;
  }
  if(delayEnemyShots==0){
      //update shot positions
    for(int i = 0; i<enemyShotList.size(); i++){
      int shot = enemyShotList.get(i);
      //if the shot is not on top of the player, unlight that led
      boolean onEnemy = false;
      for(int i=0; i<enemyList.size(); i++){
        if(shot==enemyList.get(i)){
          onEnemy=true;
        }
      }
      for(int i=0; i<barrierPositions.size(); i++){
        if(shot==barrierPositions.get(i)){
          onEnemy = true;
        }
      }
      if(!onEnemy){
        lc.setLed(0, shot/10, shot%10, 0);
      }
      //go down
      shot = shot+10;
      enemyShotList.set(i, shot); //update shot position
      lc.setLed(0, shot/10, shot%10, 1); //light new LED
    }//endenemyShotUpdateFor
    delayEnemyShots = delayEnemyShots+1;
  }

  if(delayEnemyShots!=0){
    delayEnemyShots = delayEnemyShots+1;
    if(delayEnemyShots==40){
      delayEnemyShots=0;
    }
  }


  if(delayPlayerShots!=0){
    delayPlayerShots = delayPlayerShots+1;
    if(delayPlayerShots==20){
      delayPlayerShots=0;
    }
  }

  //create new enemy shots
  newEnemyShots();
  //check if playerShot hit enemy, playershot goes off board, enemyshot goes off board, enemyshot hits player, enemyshot hits barrier
  checkOverlaps();
  //check if enemies hit bottom, or if there are no enemies left
  checkEndgame();
  }//end shooting/gameplay loop

//player shot/enemy shot and result of shot
  //delay game in here and query for shot within delay
}//endloop
  • same note applies to play game with a different remote

GamePlayVideo

5kWbKtxLcDM includes gameplay of Snake and SpaceInvaders