ITTT HKU - the Legend of Zelda Themed Quiz With SFX

Introduction: ITTT HKU - the Legend of Zelda Themed Quiz With SFX

This is a project I made for the subject If This Then That at HKU.

It's a The Legend of Zelda themed quiz setup for 3 teams and a judge. The judge gives a question and the quickest to push the button can answer. Their left LED starts blinking indicating they can answer. Once the answer has been given the judge can then push the right or wrong button. If the answer is right the LED stays lit and if it's wrong the LED stays off. Each team has three LED's meaning three points. At 3 points, you win.

The winner then pushes their button again, which activates a sound effect and the opening of the chest. Then the judge can click the reset button to start over. The reset button can at any time be pressed, so if the judge judged wrong you can start over.

If you're wondering why it's Zelda themed; I was looking at sound effects for the opening of chests and found the famous one from Zelda, which made me think of making the whole thing this theme as I do like the franchise a lot. That's also why I chose the colors yellow, red and green. When I looked up the logo, it featured those colors.

Supplies:

Circuit

- Arduino Uno

- Jumpwires

- Breadbord

- 9x LED's (3 Yellow, 3 Green and 3 Red)

- 6x buttons (3 for judge, 1 for each team)

- 1x buzzer

- 1x servo

- 6x 10k Ohm Resistors (for buttons)

- 9x 330 Ohm Resistors (for LEDs)

Case

- Small chest

- Material to make the case (I used Medium-Density Fibreboards)

- Paperclip

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Wiring the Circuit

Wire the circuit as shown in the image above.

For clarity, I seperated the circuit into two breadbords. The upper breadbord contains the team's LEDs and buttons while the bottom one contains the buttons for the judge. This can of course be put onto one breadbord, but in the actual box it will be seperated from each other too.

Step 2: Typing the Code

The code is quite lengthy, so I put it in different tabs in the IDE. When you make a tab without any dots in the name, the program will put the code beneath the script in the main tab. I took advantage of that to make my code more manageable. I'll put down the code per tab down here. You can find the pitches.h as a file in the attachments. You'll notice the code for each team are actually the same, except for the int currentTeam which is different for each team. With this knowledge you can increase or decrease the number of teams. Just copy paste the code and make sure the int currentTeam changes to a different number, when it's their turn.

///// MAIN tab /////

#include

#include "pitches.h" //add note library

//notes in the melody

int melody1[] = {NOTE_G2, NOTE_A2, NOTE_B2, NOTE_CS3, NOTE_G2, NOTE_A2, NOTE_B2, NOTE_CS3,

NOTE_GS2, NOTE_AS2, NOTE_C3, NOTE_D3, NOTE_GS2, NOTE_AS2, NOTE_C3, NOTE_D3,

NOTE_A2, NOTE_B2, NOTE_CS3, NOTE_DS3, NOTE_A2, NOTE_B2, NOTE_CS3, NOTE_DS3,

NOTE_AS2, NOTE_C3, NOTE_D3, NOTE_E3, NOTE_AS2, NOTE_C3, NOTE_D3, NOTE_E3,

NOTE_B2, NOTE_CS3, NOTE_DS3, NOTE_F3,

NOTE_C3, NOTE_D3, NOTE_E3, NOTE_FS3,

NOTE_CS3, NOTE_DS3, NOTE_F3, NOTE_G3,

NOTE_D3, NOTE_E3, NOTE_FS3, NOTE_GS3

};

int melody2[] = {NOTE_A3, NOTE_AS3, NOTE_B3, NOTE_C4};

int melodyRight[] = {NOTE_CS4, NOTE_A3, NOTE_CS4, NOTE_A3};

int melodyWrong[] = {NOTE_AS2, NOTE_AS2, NOTE_AS2};

//note durations. 4=quarter note / 8=eighth note

int noteDuration1[] = {4, 4, 4, 4, 4, 4, 4, 4,

4, 4, 4, 4, 4, 4, 4, 4,

4, 4, 4, 4, 4, 4, 4, 4,

5, 5, 5, 5, 5, 5, 5, 5,

5, 5, 5, 5, 6, 6, 6, 6,

6, 6, 6, 6, 6, 6, 6, 6

};

int noteDuration2[] = {8, 8, 8, 3};

int noteDurationRight[] = {8, 8, 8, 8};

int noteDurationWrong[] = {2, 2, 2};

Servo servo;

int servoPos = 250; //position servo in degrees

int buzzer = A0;

int buttonYellow = 5;

int buttonGreen = 9;

int buttonRed = 13;

int buttonReset = A3;

int buttonRight = A4;

int buttonWrong = A5;

const int LEDYellow1 = 2;

const int LEDYellow2 = 3;

const int LEDYellow3 = 4;

const int LEDGreen1 = 6;

const int LEDGreen2 = 7;

const int LEDGreen3 = 8;

const int LEDRed1 = 10;

const int LEDRed2 = 11;

const int LEDRed3 = 12;

int LEDStateYellow1 = LOW;

int LEDStateYellow2 = LOW;

int LEDStateYellow3 = LOW;

int LEDStateGreen1 = LOW;

int LEDStateGreen2 = LOW;

int LEDStateGreen3 = LOW;

int LEDStateRed1 = LOW;

int LEDStateRed2 = LOW;

int LEDStateRed3 = LOW;

//0 = unanswered

//1 = answering

//2 = right

//3 = wrong

int answerState = 0;

int pointsYellow = 0;

int pointsGreen = 0;

int pointsRed = 0;

//0 = no team

//1 = yellow team

//2 = green team

//3 = red team

int currentTeam = 0;

unsigned long previousMillis = 0;

const long interval = 400;

const long interval2 = 100;

void setup() {

pinMode(buttonYellow, INPUT);

pinMode(buttonGreen, INPUT);

pinMode(buttonRed, INPUT);

pinMode(buttonReset, INPUT);

pinMode(buttonRight, INPUT);

pinMode(buttonWrong, INPUT);

pinMode(LEDYellow1, OUTPUT);

pinMode(LEDYellow2, OUTPUT);

pinMode(LEDYellow3, OUTPUT);

pinMode(LEDGreen1, OUTPUT);;

pinMode(LEDGreen2, OUTPUT);

pinMode(LEDGreen3, OUTPUT);

pinMode(LEDRed1, OUTPUT);

pinMode(LEDRed2, OUTPUT);

pinMode(LEDRed3, OUTPUT);

servo.attach(A1); //which pin is the servo

}

void loop() {

programLoop();

}

///// LOOP tab /////

void
programLoop() {

int buttonStateYellow = digitalRead(buttonYellow);

int buttonStateGreen = digitalRead(buttonGreen);

int buttonStateRed = digitalRead(buttonRed);

int buttonStateReset = digitalRead(buttonReset);

int buttonStateRight = digitalRead(buttonRight);

int buttonStateWrong = digitalRead(buttonWrong);

digitalWrite(LEDYellow1, LEDStateYellow1);

digitalWrite(LEDYellow2, LEDStateYellow2);

digitalWrite(LEDYellow3, LEDStateYellow3);

digitalWrite(LEDGreen1, LEDStateGreen1);

digitalWrite(LEDGreen2, LEDStateGreen2);

digitalWrite(LEDGreen3, LEDStateGreen3);

digitalWrite(LEDRed1, LEDStateRed1);

digitalWrite(LEDRed2, LEDStateRed2);

digitalWrite(LEDRed3, LEDStateRed3);

servo.write(servoPos);

unsigned long currentMillis = millis();

if (buttonStateReset == 1) { //resets score, servoposition etc.

reset();

}

if (currentTeam == 0 && pointsYellow != 3 && pointsGreen != 3 && pointsRed != 3) { //decides who pressed first only when someone hasnt reached 3 points yet

if (buttonStateYellow == 1) {

currentTeam = 1;

answerState = 1;

}

if (buttonStateGreen == 1) {

currentTeam = 2;

answerState = 1;

}

if (buttonStateRed == 1) {

currentTeam = 3;

answerState = 1;

}

}

/*************************************************

YELLOW PLAYER

*************************************************/

if (pointsYellow == 0 && currentTeam == 1) {

if (answerState == 1) {

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (LEDStateYellow1 == LOW) { //blinks LED after pushing the button

LEDStateYellow1 = HIGH;

} else {

LEDStateYellow1 = LOW;

}

}

if (buttonStateRight == 1) {

answerState = 2; //right

rightSFX();

}

if (buttonStateWrong == 1) {

answerState = 3; //wrong

wrongSFX();

}

}

if (answerState == 2) {

LEDStateYellow1 = HIGH;

pointsYellow = 1;

smallreset();

}

if (answerState == 3) {

LEDStateYellow1 = LOW;

smallreset();

}

}

if (pointsYellow == 1 && currentTeam == 1) {

if (answerState == 1) {

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (LEDStateYellow2 == LOW) {

LEDStateYellow2 = HIGH;

} else {

LEDStateYellow2 = LOW;

}

}

if (buttonStateRight == 1) {

answerState = 2; //right

rightSFX();

}

if (buttonStateWrong == 1) {

answerState = 3; //wrong

wrongSFX();

}

}

if (answerState == 2) {

LEDStateYellow2 = HIGH;

pointsYellow = 2;

smallreset();

}

if (answerState == 3) {

LEDStateYellow2 = LOW;

smallreset();

}

}

if (pointsYellow == 2 && currentTeam == 1) {

if (answerState == 1) {

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (LEDStateYellow3 == LOW) {

LEDStateYellow3 = HIGH;

} else {

LEDStateYellow3 = LOW;

}

}

if (buttonStateRight == 1) {

answerState = 2; //right

rightSFX();

}

if (buttonStateWrong == 1) {

answerState = 3; //wrong

wrongSFX();

}

}

if (answerState == 2) {

LEDStateYellow3 = HIGH;

pointsYellow = 3;

smallreset();

}

if (answerState == 3) {

LEDStateYellow3 = LOW;

smallreset();

}

}

if (pointsYellow == 3 && buttonStateYellow == 1) { //the winner pushes their button again to open the chest

LEDStateRed1 = LOW;

LEDStateRed2 = LOW;

LEDStateRed3 = LOW;

LEDStateGreen1 = LOW;

LEDStateGreen2 = LOW;

LEDStateGreen3 = LOW;

LEDStateYellow1 = HIGH;

LEDStateYellow2 = HIGH;

LEDStateYellow3 = HIGH;

digitalWrite(LEDRed1, LEDStateRed1);

digitalWrite(LEDRed2, LEDStateRed2);

digitalWrite(LEDRed3, LEDStateRed3);

digitalWrite(LEDGreen1, LEDStateGreen1);

digitalWrite(LEDGreen2, LEDStateGreen2);

digitalWrite(LEDGreen3, LEDStateGreen3);

digitalWrite(LEDYellow1, LEDStateYellow1);

digitalWrite(LEDYellow2, LEDStateYellow2);

digitalWrite(LEDYellow3, LEDStateYellow3);

if (servoPos > 200) {

chestLoadSFX();

for (servoPos = 250; servoPos >= 70; servoPos -= 1) { // goes from 250 degrees to 70 degrees

servo.write(servoPos); // tell servo to go to position in variable 'pos'

delay(5); // waits 5ms for the servo to reach the position

}

chestOpenSFX();

}

}

/*************************************************

GREEN PLAYER

*************************************************/

if (pointsGreen == 0 && currentTeam == 2) {

if (answerState == 1) {

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (LEDStateGreen1 == LOW) {

LEDStateGreen1 = HIGH;

} else {

LEDStateGreen1 = LOW;

}

}

if (buttonStateRight == 1) {

answerState = 2; //right

rightSFX();

}

if (buttonStateWrong == 1) {

answerState = 3; //wrong

wrongSFX();

}

}

if (answerState == 2) {

LEDStateGreen1 = HIGH;

pointsGreen = 1;

smallreset();

}

if (answerState == 3) {

LEDStateGreen1 = LOW;

smallreset();

}

}

if (pointsGreen == 1 && currentTeam == 2) {

if (answerState == 1) {

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (LEDStateGreen2 == LOW) {

LEDStateGreen2 = HIGH;

} else {

LEDStateGreen2 = LOW;

}

}

if (buttonStateRight == 1) {

answerState = 2; //right

rightSFX();

}

if (buttonStateWrong == 1) {

answerState = 3; //wrong

wrongSFX();

}

}

if (answerState == 2) {

LEDStateGreen2 = HIGH;

pointsGreen = 2;

smallreset();

}

if (answerState == 3) {

LEDStateGreen2 = LOW;

smallreset();

}

}

if (pointsGreen == 2 && currentTeam == 2) {

if (answerState == 1) {

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (LEDStateGreen3 == LOW) {

LEDStateGreen3 = HIGH;

} else {

LEDStateGreen3 = LOW;

}

}

if (buttonStateRight == 1) {

answerState = 2; //right

rightSFX();

}

if (buttonStateWrong == 1) {

answerState = 3; //wrong

wrongSFX();

}

}

if (answerState == 2) {

LEDStateGreen3 = HIGH;

pointsGreen = 3;

smallreset();

}

if (answerState == 3) {

LEDStateGreen3 = LOW;

smallreset();

}

}

if (pointsGreen == 3 && buttonStateGreen == 1) {

LEDStateRed1 = LOW;

LEDStateRed2 = LOW;

LEDStateRed3 = LOW;

LEDStateGreen1 = HIGH;

LEDStateGreen2 = HIGH;

LEDStateGreen3 = HIGH;

LEDStateYellow1 = LOW;

LEDStateYellow2 = LOW;

LEDStateYellow3 = LOW;

digitalWrite(LEDRed1, LEDStateRed1);

digitalWrite(LEDRed2, LEDStateRed2);

digitalWrite(LEDRed3, LEDStateRed3);

digitalWrite(LEDGreen1, LEDStateGreen1);

digitalWrite(LEDGreen2, LEDStateGreen2);

digitalWrite(LEDGreen3, LEDStateGreen3);

digitalWrite(LEDYellow1, LEDStateYellow1);

digitalWrite(LEDYellow2, LEDStateYellow2);

digitalWrite(LEDYellow3, LEDStateYellow3);

if (servoPos > 200) {

chestLoadSFX();

for (servoPos = 250; servoPos >= 70; servoPos -= 1) { // goes from 250 degrees to 70 degrees

servo.write(servoPos); // tell servo to go to position in variable 'pos'

delay(5); // waits 5ms for the servo to reach the position

}

chestOpenSFX();

}

}

/*************************************************

RED PLAYER

*************************************************/

if (pointsRed == 0 && currentTeam == 3) {

if (answerState == 1) {

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (LEDStateRed1 == LOW) {

LEDStateRed1 = HIGH;

} else {

LEDStateRed1 = LOW;

}

}

if (buttonStateRight == 1) {

answerState = 2; //right

rightSFX();

}

if (buttonStateWrong == 1) {

answerState = 3; //wrong

wrongSFX();

}

}

if (answerState == 2) {

LEDStateRed1 = HIGH;

pointsRed = 1;

smallreset();

}

if (answerState == 3) {

LEDStateRed1 = LOW;

smallreset();

}

}

if (pointsRed == 1 && currentTeam == 3) {

if (answerState == 1) {

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (LEDStateRed2 == LOW) {

LEDStateRed2 = HIGH;

} else {

LEDStateRed2 = LOW;

}

}

if (buttonStateRight == 1) {

answerState = 2; //right

rightSFX();

}

if (buttonStateWrong == 1) {

answerState = 3; //wrong

wrongSFX();

}

}

if (answerState == 2) {

LEDStateRed2 = HIGH;

pointsRed = 2;

smallreset();

}

if (answerState == 3) {

LEDStateRed2 = LOW;

smallreset();

}

}

if (pointsRed == 2 && currentTeam == 3) {

if (answerState == 1) {

if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis;

if (LEDStateRed3 == LOW) {

LEDStateRed3 = HIGH;

} else {

LEDStateRed3 = LOW;

}

}

if (buttonStateRight == 1) {

answerState = 2; //right

rightSFX();

}

if (buttonStateWrong == 1) {

answerState = 3; //wrong

wrongSFX();

}

}

if (answerState == 2) {

LEDStateRed3 = HIGH;

pointsRed = 3;

smallreset();

}

if (answerState == 3) {

LEDStateRed3 = LOW;

smallreset();

}

}

if (pointsRed == 3 && buttonStateRed == 1) {

LEDStateRed1 = HIGH;

LEDStateRed2 = HIGH;

LEDStateRed3 = HIGH;

LEDStateGreen1 = LOW;

LEDStateGreen2 = LOW;

LEDStateGreen3 = LOW;

LEDStateYellow1 = LOW;

LEDStateYellow2 = LOW;

LEDStateYellow3 = LOW;

digitalWrite(LEDRed1, LEDStateRed1);

digitalWrite(LEDRed2, LEDStateRed2);

digitalWrite(LEDRed3, LEDStateRed3);

digitalWrite(LEDGreen1, LEDStateGreen1);

digitalWrite(LEDGreen2, LEDStateGreen2);

digitalWrite(LEDGreen3, LEDStateGreen3);

digitalWrite(LEDYellow1, LEDStateYellow1);

digitalWrite(LEDYellow2, LEDStateYellow2);

digitalWrite(LEDYellow3, LEDStateYellow3);

if (servoPos > 200) {

chestLoadSFX();

for (servoPos = 250; servoPos >= 70; servoPos -= 1) { // goes from 250 degrees to 70 degrees

servo.write(servoPos); // tell servo to go to position in variable 'pos'

delay(5); // waits 5ms for the servo to reach the position

}

chestOpenSFX();

}

}

}

///// RESET tab /////

void reset() {

currentTeam = 0;

answerState = 0;

pointsYellow = 0;

pointsGreen = 0;

pointsRed = 0;

servoPos = 250;

LEDStateYellow1 = LOW;

LEDStateYellow2 = LOW;

LEDStateYellow3 = LOW;

LEDStateGreen1 = LOW;

LEDStateGreen2 = LOW;

LEDStateGreen3 = LOW;

LEDStateRed1 = LOW;

LEDStateRed2 = LOW;

LEDStateRed3 = LOW;

}

void smallreset() { //activates whenever an answer has been judged

currentTeam = 0;

answerState = 0;

///// SOUNDS tab /////

void rightSFX() {

for (int thisNote = 0; thisNote < 4; thisNote++) {

int noteDuration = 900 / noteDurationRight [thisNote];

tone(buzzer, melodyRight [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(buzzer);

}

}

void wrongSFX() {

for (int thisNote = 0; thisNote < 3; thisNote++) {

int noteDuration = 500 / noteDurationWrong [thisNote];

tone(buzzer, melodyWrong [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(buzzer);

}

}

void chestLoadSFX() {

for (int thisNote = 0; thisNote < 48; thisNote++) {

int noteDuration = 500 / noteDuration1 [thisNote];

tone(buzzer, melody1 [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(buzzer);

}

}

void chestOpenSFX() {

for (int thisNote = 0; thisNote < 4; thisNote++) {

int noteDuration = 2000 / noteDuration2 [thisNote];

tone(buzzer, melody2 [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(buzzer);

}

}

Step 3: Making the Case

Make a case by your own design or try mine. I drew my case in Adobe Illustrator and laser cutted it at school.

I found the vectors for the logo and triforce here:
https://seeklogo.com/vector-logo/258099/the-legend...
https://seeklogo.com/vector-logo/312572/the-legend...

You can find my case file in the attachments as .dxf files.

The case is 10 centimeters in height, 20 centimeters in width and 15 centimeters in length. I used a glue-gun to glue it together.

Step 4: Putting Everything Together

Unfortunately something went wrong during soldering the threads and components and I've yet to find the problem. This meant I haven't gotten to fully assembling the box yet, but I am planning on doing so.

Some notes:

- Once the buttons for the team were in place I had extensions I could glue on the buttons, to make the buttons bigger and easier to press.

- I bought the mini chest at a store called 'Action'

- I attached the servo to the inside of the chest and with a paperclip I made the arm that opens it. There's a hole where the arm can go through.

- I actually had a fourth LED for each team that would light up when the chest is about to open. This was to better indicate the winner. Currently the winner's LED's stay lit and the others' go off, when the chest is about to open. This got cancelled because there just aren't enough pins on the Arduino Uno.

- I had the idea of making this also a music quiz, which music fragments the buzzer could play. This however soon got cancelled because I found out that button-presses aren't registered during a songfragment. This is because of the delays.

Be the First to Share

    Recommendations

    • Magnets Challenge

      Magnets Challenge
    • Raspberry Pi Contest 2020

      Raspberry Pi Contest 2020
    • Wearables Contest

      Wearables Contest

    Discussions