#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED width, in pixels
#define SCREEN_HEIGHT 64 // OLED height, in pixels
// declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin number
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int downButtonPin = 25; // 25, The pin to which the grey button is connected
const int upButtonPin = 33; // 33, The pin to which the green button is connected
const int enterButtonPin = 32; // 32, The pin to which the blue button is connected
const int exitButtonPin = 34; // 34, The pin to which the yellow button is connected
const int switchPin1 = 27; // The pin to which the first switch is connected
const int switchPin2 = 14; // The pin to which the second switch is connected
const int switchPin3 = 12; // The pin to which the third switch is connected
const int switchPin4 = 13; // The pin to which the last switch is connected
// Sarah's addition
const int IRpin = 16; // The pin to which the IR transmitter is connected, looks like it's connected to pint 18 and not 16, but want to check and make sure
// End of addition
// number of games and array to hold their names
const int numGames = 7;
const char* gameNames[numGames] = {"Binary Conversion", "Encryption", "WiFi Strength",
"Ping Pong", "Block Game", "IR Morse Code", "Accelerometer 8-Ball"}; // game names on the board
//int gamesCount = sizeof(games) / sizeof(games[0]); // Number of games
int gameSelect = 0; // game initially selected
// function prototypes
void displayMenu(int selectedGame);
void buttonPress(int &selectedGame);
bool playGameAgain();
// game function prototypes
void playBinaryConversion();
void playEncryption();
void playWiFiStrength();
void playPingPong();
void playMazeBall();
void playIRMorseCode();
void playAccelerometer8Ball();
// current selected game index
int selectedGame = 0;
void setup() {
Serial.begin(115200);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)){
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
delay(2000);
pinMode(downButtonPin, INPUT_PULLUP);
pinMode(upButtonPin, INPUT_PULLUP);
pinMode(enterButtonPin, INPUT_PULLUP);
pinMode(exitButtonPin, INPUT_PULLUP);
pinMode(switchPin1, INPUT_PULLUP);
pinMode(switchPin2, INPUT_PULLUP);
pinMode(switchPin3, INPUT_PULLUP);
pinMode(switchPin4, INPUT_PULLUP);
// Sarah's addition
pinMode(IRpin, OUTPUT);
// End of addition
}
// scroll capability through games and determining which game the user selects
void loop() {
// put your main code here, to run repeatedly:
delay(10); // this speeds up the simulation
displayMenu(selectedGame);
buttonPress(selectedGame);
}
void displayMenu(int selectedGame) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
// display current game selected
display.setCursor(0, 0);
display.println("Selected Game: ");
display.setCursor(0, 10);
display.println(gameNames[selectedGame]);
// show a prompt
display.setCursor(0, 40);
display.println("Press ENTER to play");
display.setCursor(0, 50);
display.println("Press DOWN to scroll down in the games");
display.println("Press UP to scroll up in the games");
display.display();
}
void buttonPress(int &selectedGame) {
if(digitalRead(downButtonPin) == LOW) {
selectedGame = (selectedGame+1)%numGames; // move to the next game
delay(100); // debounce
}
if(digitalRead(upButtonPin) == LOW) {
selectedGame = (selectedGame-1+numGames)%numGames; // move to the next game
delay(100); // debounce
}
if(digitalRead(enterButtonPin) == LOW) {
switch(selectedGame) {
case 0: playBinaryConversion(); break;
case 1: playEncryption(); break;
case 2: playWiFiStrength(); break;
case 3: playPingPong(); break;
case 4: playMazeBall(); break;
case 5: playIRMorseCode(); break;
case 6: playAccelerometer8Ball(); break;
}
delay(100);
}
if(digitalRead(exitButtonPin) == LOW) {
delay(100);
}
}
void playGameAgain() {
display.clearDisplay();
display.setCursor(0, 0);
display.println("Play again? Press ENTER");
display.setCursor(0, 10);
display.println("Press EXIT to go back");
display.display();
while(true) {
if(digitalRead(enterButtonPin) == LOW) {
// Restart the current game
delay(100); // debounce
return true; // indicate that the game should be restarted
} else if(digitalRead(exitButtonPin) == LOW) {
// Go back to the main menu
delay(100); // debounce
return false; // indicate to exit to main menu
}
}
}
/// function definitions for the games
// Alex's addition
void playBinaryConversion() {
bool gameActive = true; // Flag to keep the game active
while(gameActive) {
// Initialize or reset game state here
// For instance, setting scores to 0, resetting game variables, etc.
// Main game loop
while(true) {
// Game logic here
// This includes updating the display, reading inputs, game mechanics, etc.
// Break out of this loop when the game ends (e.g., when a win or lose condition is met)
// For demonstration, let's assume the game ends after a condition is met
if(/* game end condition */) {
break; // Exit the game loop, moving on to the play again or exit logic
}
}
// After game loop ends, ask if the player wants to play again
bool playAgain = playGameAgain();
if(!playAgain) {
gameActive = false; // Set flag to false to exit the while loop and return to main menu
}
// If playAgain is true, the while loop continues, effectively restarting the game
}
// Optionally, return to the main menu or perform cleanup outside the loop
}
// Holden's addition
void playEncryption() {
bool gameActive = true; // Flag to keep the game active
while(gameActive) {
// Initialize or reset game state here
// For instance, setting scores to 0, resetting game variables, etc.
// Main game loop
while(true) {
// Game logic here
// This includes updating the display, reading inputs, game mechanics, etc.
// Break out of this loop when the game ends (e.g., when a win or lose condition is met)
// For demonstration, let's assume the game ends after a condition is met
if(/* game end condition */) {
break; // Exit the game loop, moving on to the play again or exit logic
}
}
// After game loop ends, ask if the player wants to play again
bool playAgain = playGameAgain();
if(!playAgain) {
gameActive = false; // Set flag to false to exit the while loop and return to main menu
}
// If playAgain is true, the while loop continues, effectively restarting the game
}
// Optionally, return to the main menu or perform cleanup outside the loop
}
// Holden's addition
void playWiFiStrength() {
bool gameActive = true; // Flag to keep the game active
while(gameActive) {
// Initialize or reset game state here
// For instance, setting scores to 0, resetting game variables, etc.
// Main game loop
while(true) {
// Game logic here
// This includes updating the display, reading inputs, game mechanics, etc.
// Break out of this loop when the game ends (e.g., when a win or lose condition is met)
// For demonstration, let's assume the game ends after a condition is met
if(/* game end condition */) {
break; // Exit the game loop, moving on to the play again or exit logic
}
}
// After game loop ends, ask if the player wants to play again
bool playAgain = playGameAgain();
if(!playAgain) {
gameActive = false; // Set flag to false to exit the while loop and return to main menu
}
// If playAgain is true, the while loop continues, effectively restarting the game
}
// Optionally, return to the main menu or perform cleanup outside the loop
}
// My addition????
void playPingPong() {
bool gameActive = true; // flag to keep the game active
while(gameActive) {
const int paddleHeight = 10; // height of the paddle
int paddleY = SCREEN_HEIGHT/2; // start in the middle of the screen
int ballX = 0, ballY = SCREEN_HEIGHT/2; // start ball in the middle, left side
int ballDirX = 1, ballDirY = 1; // ball direction; 1 for right/down, -1 for left/up
const int ballSpeed = 2; // speed of ball movement
display.clearDisplay();
while(true) {
// move paddle
if(digitalRead(upButtonPin) == LOW) {
paddleY = max(0, paddleY-3); // move paddle up
delay(50); // debounce delay
} else if(digitalRead(downButtonPin) == LOW) {
paddleY = min(SCREEN_HEIGHT-paddleHeight, paddleY+3); // move paddle down
delay(50); // debounce delay
}
// move ball
ballX += ballDirX*ballSpeed;
ballY += ballDirY*ballSpeed;
// check for collisions
if(ballY <= 0 || ballY >= SCREEN_HEIGHT) {
ballDirY *= -1 // bounce off top/bottom
}
if(ballX <= 0) {
ballDirX *= 1; // bounce off left side
} else if(ballX >= SCREEN_WIDTH-1) {
// check if the ball hits the paddle
if(ballY >= paddleY && ballY <= paddleY+paddleHeight) {
ballDirX *= -1; // bounce off paddle
} else {
// missed the paddle, game over
display.setTextSize(2);
display.setCursor(10, 20);
diplay.println("Game Over");
display.display();
delay(2000);
break; // exit inner while loop
}
}
// draw paddle and ball
display.clearDisplay(); // clear display for next draw cycle
display.fillRect(SCREEN_WIDTH,-3, paddleY, 3, paddleHeight, WHITE); // draw paddle
display.fillCircle(ballX, ballY, 2, WHITE); // draw ball
display.display();
delay(10); // game speed delay
}
// ask if the player wants to play again
bool playAgain = playGameAgain();
if(!playAgain) {
gameActive = false; // set flag to false to exit the while loop and return to main menu
} else {
// reset game state for new game
paddleY = SCREEN_HEIGHT/2;
ballX = 0, ballY = SCREEN_HEIGHT/2;
ballDirX = 1, ballDirY = 1;
}
}
}
// Sarah's addition
void playMazeBall() {
bool gameActive = true; // Flag to keep the game active
while (gameActive) {
// Initialize or reset game state here
// For instance, setting scores to 0, resetting game variables, etc.
// Main game loop
while (true) {
// Game logic here
// This includes updating the display, reading inputs, game mechanics, etc.
// Break out of this loop when the game ends (e.g., when a win or lose condition is met)
// For demonstration, let's assume the game ends after a condition is met
if (/* game end condition */) {
break; // Exit the game loop, moving on to the play again or exit logic
}
}
// After game loop ends, ask if the player wants to play again
bool playAgain = playGameAgain();
if (!playAgain) {
gameActive = false; // Set flag to false to exit the while loop and return to main menu
}
// If playAgain is true, the while loop continues, effectively restarting the game
}
// Optionally, return to the main menu or perform cleanup outside the loop
}
// Sarah's addition
void playIRMorseCode() {
// IR morse code - Should flash "Go Chargers"
// Morse code background
// - a dot "." lasts 1 sec
// - a dash "-" lasts 3 sec
// - space between dots and dashes of the same letter last 1 sec
// - spcae between different letters lasts 3 sec
// - space between different words lasts 7 sec or the equivalent of 7 silent dots
// --. --- ....... -.-. .... .- .-. --. . .-. ...
// G O Space C H A R G E R S
// G -> --. -> 3on, 1off, 3on, 1off, 1on, 3off
digitalWrite(IRpin, HIGH); // High = on, this means the voltage is high
delay(3000); // dash
digitalWrite(IRpin, LOW); // Low = off, this means the voltage is low
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(1000); //pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(3000); // go to next letter
// O -> --- -> 3on, 1off, 3on, 1off, 3on, 3off
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(1000); //pause
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(7000); // go to next word
// C -> -.-. -> 3on, 1off, 1on, 1off, 3on, 1off, 1on, 3off
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(1000); //pause
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(1000); //pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(3000); // go to next letter
// H -> .... -> 1on, 1off, 1on, 1off, 1on, 1off, 1on, 3off
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(1000); //pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(1000); //pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(3000); // go to next letter
// A -> .- -> 1on, 1off, 3on, 3off
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(3000); // go to next letter
// R -> .-. -> 1on, 1off, 3on, 1off, 1on, 3off
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(3000); // go to next letter
// G -> --. -> 3on, 1off, 3on, 1off, 1on, 3off
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(1000); //pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(3000); // go to next letter
// E -> . -> 1on, 3off
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(3000); // go to next letter
// R -> .-. -> 1on, 1off, 3on, 1off, 1on, 3off
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(3000); // dash
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(3000); // go to next letter
// S -> ... -> 1on, 1off, 1on, 1off, 1on, 3off
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(1000); // pause
digitalWrite(IRpin, HIGH);
delay(1000); // dot
digitalWrite(IRpin, LOW);
delay(3000); // go to next letter
}
// Alex's addition
void playAccelerometer8Ball() {
bool gameActive = true; // Flag to keep the game active
while (gameActive) {
// Initialize or reset game state here
// For instance, setting scores to 0, resetting game variables, etc.
// Main game loop
while (true) {
// Game logic here
// This includes updating the display, reading inputs, game mechanics, etc.
// Break out of this loop when the game ends (e.g., when a win or lose condition is met)
// For demonstration, let's assume the game ends after a condition is met
if (/* game end condition */) {
break; // Exit the game loop, moving on to the play again or exit logic
}
}
// After game loop ends, ask if the player wants to play again
bool playAgain = playGameAgain();
if (!playAgain) {
gameActive = false; // Set flag to false to exit the while loop and return to main menu
}
// If playAgain is true, the while loop continues, effectively restarting the game
}
// Optionally, return to the main menu or perform cleanup outside the loop
}