Project Overview
For this project we had one simple instruction: do it better. The 'it' means one of our previous projects by the way. This was shocking news for me, since I thought I had already done every project perfectly. Apparently Mr. Williams didn't think so. Because of this, I had to accomplish the herculean task of improving one of my amazing works, the electricity and robotics project.
We decided to improve on the lightshow by making it interactive. What is more interactive than a video game? A person. So we decided to make an artificially intelligent cybernetic organism, Jordan Halpern. We then used this cyborg to make a cool display for our real project, the Amazing Game of Snake.
What is snake? You should look it up on Wikipedia, they have more information than I can possibly provide. But a basic definition is a video game where the player maneuvers a line which grows in length, with the line itself being the primary obstacle. The objective of our game is to acquire as many objectives as possible to make the snake as long as possible. We used Kai's Arduino Mega to control fifty red LEDs arranged in a 5x10 matrix to serve as the screen. We then made a not-wireless controller with four buttons to maneuver the snake around this matrix.
For this project we had one simple instruction: do it better. The 'it' means one of our previous projects by the way. This was shocking news for me, since I thought I had already done every project perfectly. Apparently Mr. Williams didn't think so. Because of this, I had to accomplish the herculean task of improving one of my amazing works, the electricity and robotics project.
We decided to improve on the lightshow by making it interactive. What is more interactive than a video game? A person. So we decided to make an artificially intelligent cybernetic organism, Jordan Halpern. We then used this cyborg to make a cool display for our real project, the Amazing Game of Snake.
What is snake? You should look it up on Wikipedia, they have more information than I can possibly provide. But a basic definition is a video game where the player maneuvers a line which grows in length, with the line itself being the primary obstacle. The objective of our game is to acquire as many objectives as possible to make the snake as long as possible. We used Kai's Arduino Mega to control fifty red LEDs arranged in a 5x10 matrix to serve as the screen. We then made a not-wireless controller with four buttons to maneuver the snake around this matrix.
Gameplay
This is a video of an older build, so it terminates prematurely due to a bug.
This is a video of an older build, so it terminates prematurely due to a bug.
Concepts
Many of the concepts we used in this project were used in the last one, so you can check out my robotics page to learn about electricity, Arduinos, and other basic concepts. I will be covering more advanced topics here.
Arduino Mega 2560: An advanced arduino model with four times as much remote access memory as a base level arduino. The Mega has 54 digital pins and 16 analog pins.
For loop: A loop construct found in many procedural languages which repeatedly executes some instructions while a condition is true.
While loop: The loop construct, found in nearly all procedural languages, that executes one or more instructions (the "loop body") repeatedly so long as some condition evaluates to true.
Modulus: a quantity by which two given quantities can be divided to yield the same remainders.
Array: A data structure in computers which can store many different values of one type.
Serial monitor: A display in the Arduino IDE that can show variable values from the program on the Arduino board.
Zener diode: a type of diode that permits current in the forward direction like a normal diode, but also in the reverse direction if the voltage is larger than the breakdown voltage known as "Zener knee voltage" or "Zener voltage".
Analog pins: pins on the Arduino that can send or received1024 different voltage levels between 0-5 volts.
Many of the concepts we used in this project were used in the last one, so you can check out my robotics page to learn about electricity, Arduinos, and other basic concepts. I will be covering more advanced topics here.
Arduino Mega 2560: An advanced arduino model with four times as much remote access memory as a base level arduino. The Mega has 54 digital pins and 16 analog pins.
For loop: A loop construct found in many procedural languages which repeatedly executes some instructions while a condition is true.
While loop: The loop construct, found in nearly all procedural languages, that executes one or more instructions (the "loop body") repeatedly so long as some condition evaluates to true.
Modulus: a quantity by which two given quantities can be divided to yield the same remainders.
Array: A data structure in computers which can store many different values of one type.
Serial monitor: A display in the Arduino IDE that can show variable values from the program on the Arduino board.
Zener diode: a type of diode that permits current in the forward direction like a normal diode, but also in the reverse direction if the voltage is larger than the breakdown voltage known as "Zener knee voltage" or "Zener voltage".
Analog pins: pins on the Arduino that can send or received1024 different voltage levels between 0-5 volts.
Reflection:
This project went very smoothly. Kai was brilliant with the hardware and was able to wire up the entire LED matrix in less than two days. I didn't have many problems with the code, although it was more difficult than the last project. I learned more about setting up circuits involving Arduino boards, like using multiple GND, 5V, and 3.3V pins at once, as well as learning how to stabilize analog input by using Zener diodes. A peak of this project was playing the game. It is actually pretty fun, and it is extra cool for me because I programmed it. Another peak was when I figured out what was causing the input bug, which leads me to my first pit: the input bug. This bug was very annoying and set us back an entire day. It was the result of a 5V pin being used where a GND pin should have been, and it sucked. The other pit was making the matrix itself. Pinning all of the LEDs in was very tedious, and I recommend outsourcing it if you every need to do this menial task.
This was a great year in STEM, and this was an awesome project to finish with. Hopefully next year will be cool too.
This project went very smoothly. Kai was brilliant with the hardware and was able to wire up the entire LED matrix in less than two days. I didn't have many problems with the code, although it was more difficult than the last project. I learned more about setting up circuits involving Arduino boards, like using multiple GND, 5V, and 3.3V pins at once, as well as learning how to stabilize analog input by using Zener diodes. A peak of this project was playing the game. It is actually pretty fun, and it is extra cool for me because I programmed it. Another peak was when I figured out what was causing the input bug, which leads me to my first pit: the input bug. This bug was very annoying and set us back an entire day. It was the result of a 5V pin being used where a GND pin should have been, and it sucked. The other pit was making the matrix itself. Pinning all of the LEDs in was very tedious, and I recommend outsourcing it if you every need to do this menial task.
This was a great year in STEM, and this was an awesome project to finish with. Hopefully next year will be cool too.
Source Code
const int pins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59};
const int right = 64;
const int left = 62;
const int up = 65;
const int down = 63;
const int minX = 0;
const int maxX = 9;
const int minY = 0;
const int maxY = 4;
const int delay_length = 250;
int updateCounter = 0;
int snake[10][5];
int snakeHeadX;
int snakeHeadY;
int objectiveX;
int objectiveY;
int snake_direction;
boolean gameover = false;
boolean newObjective = true;
int snake_size = 3;
void setup()
{
for (int i = 0; i < 50; i++){
pinMode(pins[i], OUTPUT);
}
pinMode(right, INPUT);
pinMode(left, INPUT);
pinMode(up, INPUT);
pinMode(down, INPUT);
spawn_snake();
}
void loop()
{
updateCounter++;
if(newObjective)
{
while(true)
{
delay(2);
objectiveX = millis()%10;
objectiveY = millis()%5;
if (snake[objectiveX][objectiveY] == 0)
{
newObjective = false;
break;
}
}
}
if (analogRead(left) < 50 && snake_direction != 3) // right
{
snake_direction = 1;
}
else if (analogRead(right) < 50 && snake_direction != 1) // left
{
snake_direction = 3;
}
else if (analogRead(down) < 50 && snake_direction != 4) // up
{
snake_direction = 2;
}
else if (analogRead(up) < 50 && snake_direction != 2) // down
{
snake_direction = 4;
}
if(updateCounter == 100)
{
if(snake_direction == 1){
snakeHeadX += 1;
}else if (snake_direction == 3){
snakeHeadX -= 1;
}else if (snake_direction == 2){
snakeHeadY -= 1;
}else if (snake_direction == 4){
snakeHeadY += 1;
}
if (snake[snakeHeadX][snakeHeadY] > 1)
{
gameover = true;
}
snake[snakeHeadX][snakeHeadY] = snake_size+1;
for (int i = 0; i < 10; i++){
for (int j = 0; j < 5; j++){
if(snake[i][j] > 0){
snake[i][j]--;
}
}
}
updateCounter = 0;
}
if (snakeHeadX > maxX || snakeHeadX < minX || snakeHeadY > maxY || snakeHeadY < minY)
{
gameover = true;
}
if(snakeHeadX == objectiveX && snakeHeadY == objectiveY)
{
int twoX;
int twoY;
int threeX;
int threeY;
newObjective = true;
snake_size ++;
for (int i = 0; i < 10; i++){
for (int j = 0; j < 5; j++){
if(snake[i][j] > 0){
snake[i][j]++;
}
if(snake[i][j] == 2)
{
twoX = i;
twoY = j;
}
else if (snake[i][j] == 3)
{
threeX = i;
threeY = j;
}
}
}
snake[2 * twoX - threeX][2 * twoY - threeY] = 1;
}
for (int i = 0; i < 10; i++){
for (int j = 0; j < 5; j++){
if(snake[i][j] > 0){
digitalWrite(pins[5*i + j], HIGH);
}
else {
digitalWrite(pins[5*i + j], LOW);
}
}
}
if(updateCounter < 25){
digitalWrite(pins[objectiveX*5 +objectiveY], HIGH);
}else if(updateCounter > 25 && updateCounter < 50){
digitalWrite(pins[objectiveX*5 +objectiveY], LOW);
}else if(updateCounter > 50 && updateCounter < 75){
digitalWrite(pins[objectiveX*5 +objectiveY], HIGH);
}else if(updateCounter > 75 && updateCounter < 100){
digitalWrite(pins[objectiveX*5 +objectiveY], LOW);
}
while(gameover){
if (analogRead(left) < 3 || analogRead(right) < 3 || analogRead(up) < 3 || analogRead(down) < 3)
{
spawn_snake();
gameover = false;
newObjective = true;
}
for (int i = 0; i < 10; i++){
for (int j = 0; j < 5; j++){
digitalWrite(pins[5*i + j], LOW);
snake[i][j] = 0;
}
}
}
delay(delay_length/100);
}
void spawn_snake()
{
snake_size = 3;
snake_direction = 1;
snakeHeadX = 5;
snakeHeadY = 2;
snake[snakeHeadX-0][snakeHeadY+0] = 3;
snake[snakeHeadX-1][snakeHeadY+0] = 2;
snake[snakeHeadX-2][snakeHeadY+0] = 1;
}
const int pins[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59};
const int right = 64;
const int left = 62;
const int up = 65;
const int down = 63;
const int minX = 0;
const int maxX = 9;
const int minY = 0;
const int maxY = 4;
const int delay_length = 250;
int updateCounter = 0;
int snake[10][5];
int snakeHeadX;
int snakeHeadY;
int objectiveX;
int objectiveY;
int snake_direction;
boolean gameover = false;
boolean newObjective = true;
int snake_size = 3;
void setup()
{
for (int i = 0; i < 50; i++){
pinMode(pins[i], OUTPUT);
}
pinMode(right, INPUT);
pinMode(left, INPUT);
pinMode(up, INPUT);
pinMode(down, INPUT);
spawn_snake();
}
void loop()
{
updateCounter++;
if(newObjective)
{
while(true)
{
delay(2);
objectiveX = millis()%10;
objectiveY = millis()%5;
if (snake[objectiveX][objectiveY] == 0)
{
newObjective = false;
break;
}
}
}
if (analogRead(left) < 50 && snake_direction != 3) // right
{
snake_direction = 1;
}
else if (analogRead(right) < 50 && snake_direction != 1) // left
{
snake_direction = 3;
}
else if (analogRead(down) < 50 && snake_direction != 4) // up
{
snake_direction = 2;
}
else if (analogRead(up) < 50 && snake_direction != 2) // down
{
snake_direction = 4;
}
if(updateCounter == 100)
{
if(snake_direction == 1){
snakeHeadX += 1;
}else if (snake_direction == 3){
snakeHeadX -= 1;
}else if (snake_direction == 2){
snakeHeadY -= 1;
}else if (snake_direction == 4){
snakeHeadY += 1;
}
if (snake[snakeHeadX][snakeHeadY] > 1)
{
gameover = true;
}
snake[snakeHeadX][snakeHeadY] = snake_size+1;
for (int i = 0; i < 10; i++){
for (int j = 0; j < 5; j++){
if(snake[i][j] > 0){
snake[i][j]--;
}
}
}
updateCounter = 0;
}
if (snakeHeadX > maxX || snakeHeadX < minX || snakeHeadY > maxY || snakeHeadY < minY)
{
gameover = true;
}
if(snakeHeadX == objectiveX && snakeHeadY == objectiveY)
{
int twoX;
int twoY;
int threeX;
int threeY;
newObjective = true;
snake_size ++;
for (int i = 0; i < 10; i++){
for (int j = 0; j < 5; j++){
if(snake[i][j] > 0){
snake[i][j]++;
}
if(snake[i][j] == 2)
{
twoX = i;
twoY = j;
}
else if (snake[i][j] == 3)
{
threeX = i;
threeY = j;
}
}
}
snake[2 * twoX - threeX][2 * twoY - threeY] = 1;
}
for (int i = 0; i < 10; i++){
for (int j = 0; j < 5; j++){
if(snake[i][j] > 0){
digitalWrite(pins[5*i + j], HIGH);
}
else {
digitalWrite(pins[5*i + j], LOW);
}
}
}
if(updateCounter < 25){
digitalWrite(pins[objectiveX*5 +objectiveY], HIGH);
}else if(updateCounter > 25 && updateCounter < 50){
digitalWrite(pins[objectiveX*5 +objectiveY], LOW);
}else if(updateCounter > 50 && updateCounter < 75){
digitalWrite(pins[objectiveX*5 +objectiveY], HIGH);
}else if(updateCounter > 75 && updateCounter < 100){
digitalWrite(pins[objectiveX*5 +objectiveY], LOW);
}
while(gameover){
if (analogRead(left) < 3 || analogRead(right) < 3 || analogRead(up) < 3 || analogRead(down) < 3)
{
spawn_snake();
gameover = false;
newObjective = true;
}
for (int i = 0; i < 10; i++){
for (int j = 0; j < 5; j++){
digitalWrite(pins[5*i + j], LOW);
snake[i][j] = 0;
}
}
}
delay(delay_length/100);
}
void spawn_snake()
{
snake_size = 3;
snake_direction = 1;
snakeHeadX = 5;
snakeHeadY = 2;
snake[snakeHeadX-0][snakeHeadY+0] = 3;
snake[snakeHeadX-1][snakeHeadY+0] = 2;
snake[snakeHeadX-2][snakeHeadY+0] = 1;
}