Final Project: Repeat After Me

Finally, we reached the end of the semester, and with it came the submission of the final project. I had decided to make a Simon-Says style game, using lights and buzzers to interact with the user and test their recall skills. An interesting thing I’ve found throughout this course that I seem to really enjoy memory-style games, as with my midterm, and now this.

Like with my midterm, I began by creating a prototype to make sure I got the basic features down before I integrated any fancy features or graphics. Looking back on it now, the initial version worked, but it just looked, in simple terms, boring.

 

The initial gameplay didn’t feel like anything I would be excited to play at all.

The initial wiring setup didn’t inspire much confidence either.

But that’s the great part of a prototype. It didn’t need to look good, so long as it functioned well. I was able to nail down the game states with the prototype, then I began working on graphics.

I wanted to go for a retro style with my game, and so I tried to make the backgrounds and the board match a cohesive neon-arcade-esque vibe.

In the end, we arrived at the final submission. I ended up soldering many of the wires inside my box to hide them as much as possible, because attractive things work better (reading reference!).

After carrying out user-testing, I ended up integrating more features within my code, including an instructions screen, and more interactivity between the buttons (a shorter debounce delay, the buttons lighting up, etc).

And here we are. With the final submission! I had  both  a great  and  frustrating  experience  making  it,  but I’m  really  glad  with the  final result.

Schematic of my circuit (though I used arcade buttons)

// establishing variables
const int buttonPins[] = {2, 3, 4, 5}; // Yellow, green, blue, and red
const int ledPins[] = {8, 9, 10, 11}; // Yellow, green, blue, and red
const int buzzerPin = 6; // Buzzer set on pin 6

bool ledBlinking = false; // Checks whether the LEDs are blinking or not
unsigned long lastBlinkTime = 0; // Tracks when the LEDs were last blinked
bool blinkState = false; // Toggles between on and off when the LEDs are blinking

void setup() {
  // Setting up serial communication
  Serial.begin(9600); // Buad rate of 9600
  for (int i = 0; i < 4; i++) {
    // Setting the pin modes for the buttons, LEDs, and buzzer
    pinMode(buttonPins[i], INPUT_PULLUP);
    pinMode(ledPins[i], OUTPUT);
  }
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  // Handle blinking mode
  if (ledBlinking && millis() - lastBlinkTime > 500) { 
    blinkState = !blinkState; // Alternates between the LED being on and off every 500ms
    for (int i = 0; i < 4; i++) {
      if (blinkState) {
        digitalWrite(ledPins[i], HIGH); // Turn the LED on if blinkState is true
        } 
      else {
        digitalWrite(ledPins[i], LOW); // Turn the LED off if blinkState is false
        }
       }
    lastBlinkTime = millis();
  }

  // Check button presses
  for (int i = 0; i < 4; i++) {
    if (digitalRead(buttonPins[i]) == LOW) {
      Serial.println(buttonPins[i]); // Send button pin number to p5
      delay(100); // Debounce delay
    }
  }

  // Handle serial input from p5
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n');
    command.trim();

    if (command.startsWith("ALL")) { // if the p5 command sends "ALL", all LEDs must be on
      int mode = command.substring(3).toInt();
      handleAllLEDs(mode);
    } 
    else if (command == "WRONG") { // if the p5 command sends "WRONG", play the sound
      tone(buzzerPin, 100, 500); // Wrong answer sound
    } 
    else {
      int pin = command.toInt(); // lights up the corresponding LED and plays the sound
      if (pin >= 8 && pin <= 11) {
        playColorFeedback(pin);
      }
    }
  }
}

// Turns on the LED corresponding to the button, and plays the sound
void playColorFeedback(int pin) {
  digitalWrite(pin, HIGH);
  playToneForPin(pin);
  delay(300);
  digitalWrite(pin, LOW);
  noTone(buzzerPin);
}

// Plays a specific tone based on the button pressed
void playToneForPin(int pin) {
  switch (pin) {
    case 8: tone(buzzerPin, 262); break; // Yellow is C4
    case 9: tone(buzzerPin, 330); break; // Green is E4
    case 10: tone(buzzerPin, 392); break; // Blue is G4
    case 11: tone(buzzerPin, 523); break; // Red is C5
  }
}

void handleAllLEDs(int mode) {
  ledBlinking = false;
  for (int i = 0; i < 4; i++) {
    digitalWrite(ledPins[i], LOW); // the LEDs are off
  }

  if (mode == 1) {
    for (int i = 0; i < 4; i++) {
      digitalWrite(ledPins[i], HIGH); // if the mode is 1, it turns on all the LEDs
    }
  } else if (mode == 2) { // if the mode is 2, it blinks the LEDs
    ledBlinking = true;
    lastBlinkTime = millis();
  }
}

My Arduino Code

Link to the full screen version

Thanks for a great semester!

Leave a Reply