“Aqua Arcade: A Pinball Odyssey” – Jessica Yu – Andy

Context and Significance 

In building upon the foundation laid by my previous group project, “The ProMax Nebulous 3000 Cyber,” I was encouraged to create another project with equally significant impact. This previous project helped shape my perception of interaction as a dynamic two-way exchange requiring communication between multiple parties. The most effective form of interaction, within the context of our projects, is one where two entities actively communicate, process information, and engage in a meaningful dialogue. My group members and I agreed that this principle would be important to guide our project and was instrumental in our decision to develop “Aqua Arcade: A Pinball Odyssey.” 

Our team decided to make an engaging, lighthearted game that responded to the player’s actions while subtly prompting contemplation on critical issues such as water pollution and ocean degradation. We believe that this underlying theme lends our pinball machine a unique narrative and meaningful existence, setting it apart from traditional arcade games. Our versatile “Aqua Arcade” game is designed for individuals of all ages who appreciate the timeless appeal of classic arcade games. Beyond offering anyone a fun gaming experience, it serves as a subtle educational tool. Players might initially view it as a simple ocean-themed game, but as they engage with it, they gradually become more aware of the sad reality of their waste disposal choices. This subtle yet impactful messaging is what sets our project apart – it not only entertains but also educates, making it relevant and valuable to a broad audience.

 

Conception and Design 

Our understanding of how users would engage with “Aqua Arcade: A Pinball Odyssey” influenced our design decisions. We aimed to create a visually appealing game that intuitively communicated its rules and objectives. 

[PHOTOS: our original brainstorm sketches]

Initially, we built a prototype of our project using cardboard, rubber bands, and sticks. While this prototype served as a valuable starting point, user testing revealed the need for sturdier materials. We opted to switch to double-layered wood that we carved using the laser cutter for key components, ensuring better durability and mobility. This improvement helped the game’s structural integrity and mobility, especially in crucial components like the pivoting flippers, the underlying mechanism system, and the user handles. 

Wood Flippers

[PHOTOS: close up of the cardboard flippers vs. wood flippers]

Another significant design decision was the choice of materials for the sensors. We wanted LEDs to light up as the ball interacted with the game’s elements but struggled to select the right sensor for this purpose. At first, we considered leaf switch sensors to be placed on the inside of the rubber bands but found they might not respond effectively to the ball’s light impact. Instead, we opted for a double-layering technique utilizing copper wires to line the components where the ball could interact. This approach would provide a more sensitive response to the ball’s movements, ensuring that the LEDs lit up as intended when the ball bounced within the game.

[PHOTO: close up of our copper wire sensor mechanisms]

 

Fabrication and Production 

Throughout our production process for “Aqua Arcade: A Pinball Odyssey,” several key steps were instrumental. These included blueprint planning, cardboard cutting, fabrication lab work, soldering, gluing, wiring, and coding. Our team, including Tammy Huang, Nicole Cheah, and myself, worked very cohesively by efficiently dividing tasks based on our individual strengths.

[PHOTO: our production process]

My primary role involved fabricating project components, including extensive cardboard and wood cutting and work in the fabrication lab, where I laser-cut components, drilled holes in various materials, and soldered the copper wires for our sensors.

[PHOTO: using the fabrication lab laser cutter]

As our fabrication process drew to a close for the prototype, we eagerly approached the User Testing Session. After lots of effort in blueprint planning, fabrication, and coding, we were ready to put our pinball game to a fun user test. On the testing day, a diverse group of participants tried out our game. Fortunately, the session went smoothly, and it seemed that the players enjoyed their experience. The positive response from our testers confirmed our belief in the game’s potential for providing an engaging and entertaining experience.

[PHOTO: our finished prototype ready for user testing]

 

[VIDEO: a full video of an user interacting with prototype]

Following the User Testing Session, we found some bugs in our design, such as the ball getting stuck, weak flipper mechanisms, and loosened copper wires. We addressed these by replacing cardboard flippers with double-layered wood flippers and adding extra obstacle guides to prevent ball blockages. As for our response to the loosening copper wires which we had spent several hours on to ensure the ball would be able to trigger both lines at the same time, I suggested attaching additional stick braces to the segments where the wires were loosening. This saved us lots of time which allowed us to focus on other enhancements like adding a buzzer and timer system. One of the many suggestions thrown out during user testing was to add more signifying mechanics such as introducing a buzzer winning/losing outcome or a timer system for the game to restart. My partners worked diligently on refining the code, enhancing interactions and significantly improving our project’s quality and user experience. 

 if (led1hitnum % 2 == 1 && led2hitnum % 2 == 1 && led3hitnum % 2 == 1) {

   if (millis() - startTime < 60000) {
     win();
   }
 if (startTime != -1 && millis() - startTime > 60000) {

   noTone(7);       // turn it off
   startTime = -1;  // mark as stopped again
 }
 Serial.println(millis() - startTime);
    if (millis() - startTime > 600000) {
     lose();
   }
void win() {

 for (int thisNote = 0; thisNote < 9; thisNote++) {
   int noteDuration = 1000 / noteDurations[thisNote];
   tone(7, melody[thisNote], noteDuration);
   int pauseBetweenNotes = noteDuration * 1.30;
   delay(pauseBetweenNotes);
   noTone(7);
   digitalWrite(led1, LOW);
 }
 delay(10000);
}

void lose() {

 for (int thisNote = 0; thisNote < 12; thisNote++) {
   int noteDuration = 1000 / noteDurations2[thisNote];
   tone(7, melody2[thisNote], noteDuration);
   int pauseBetweenNotes = noteDuration * 1.30;
   delay(pauseBetweenNotes);
   noTone(7);
   digitalWrite(led1, HIGH);
 }
 delay(10000);
}
[CODE: excerpts of the code for the new win/lose response, buzzer, and timer parts]

All our production choices were aimed at improving the game’s quality and making it more enjoyable. The additions of stronger components, buzzer sounds, and the timer system aligned with our project’s goals of delivering an engaging, fun, and interactive gaming experience. 

 

Conclusions

Our project aimed to create an engaging and thought-provoking gaming experience in “Aqua Arcade: A Pinball Odyssey.” We envisioned an interaction where players would not only enjoy the game but also gain awareness about environmental issues like water pollution and ocean degradation. In our game, players engaged with the pinball machine through their actions, and the game responded in kind, creating an interactive and dynamic experience. This aligns with our definition of interaction as a two-way exchange that requires meaningful communication among participants. However, some aspects did not align perfectly with our initial vision. We had encountered technical setbacks during user testing and so we could not make it as complex and detailed as we originally intended. 

As for our audience’s interaction with the project, it was very positive. I think players found “Aqua Arcade” to be a fun and enjoyable game, appreciating the mechanisms and simplicity of our game theme. The game also partially succeeded in stimulating curiosity about the theme behind our design being ocean issues without being overly obvious. Given more time, I think we would further explore the educational elements to more clearly get our point across about ocean conservation and hopefully deepen the player’s ability to understand those environmental challenges. In some ways, a failure was that we wanted our project to be even more refined with fewer technical glitches and a more clearly defined theme. On the other hand, my group had a wonderful, extremely memorable experience working together to create our project and our accomplishments filled us with pride, as we successfully created an entertaining game with educational value.

 

[PHOTOS: the final product “AQUA ARCADE: A PINBALL ODYSSEY”]
[VIDEO: winning buzzer sound]
 

 

[VIDEO: user interacting with the final project]

 

Appendix

Materials List: 

  • Cardboard 
  • 5mm Ply Wood
  • Chopsticks
  • Skewer Sticks
  • Popsicle Sticks
  • Lollipop Stick
  • Rubber Bands
  • Small Metal Ball
  • LEDs
  • Copper Wires
  • Wires
  • Arduino 
  • Hot Glue
  • Super Glue
  • Markers

Credits: 

We would like to extend our gratitude to the creator of the previous pinball machine project that inspired our initial brainstorming phase. Their project provided us with valuable inspiration, demonstrating a visually appealing and engaging approach that resonated with our project’s goals. It served as a guiding example in our pursuit of naturally attracting the audience into the game. I have included a reference photo as well as the original link to the project page.

https://projecthub.arduino.cc/Frogger1108/homemade-arduino-pinball-machine-65b3db

Full Code:

int pushButton1 = 2;  // wire 1

int pushButton2 = 6;  // wire 2

int pushButton3 = 4;  // wire 3

int pushButton4 = 8;  //start button

int led1 = 13;

int led2 = 12;

int led3 = 11;

int led1hitnum = 0;

int led2hitnum = 0;

int led3hitnum = 0;

//int buttonState = 0;

long startTime = -1;  // starts out as stopped

#include "pitches.h"

// notes in the melody:

int melody[] = {

 NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5, NOTE_C4

};

// note durations: 4 = quarter note, 8 = eighth note, etc.:

int noteDurations[] = {

 8, 8, 8, 4, 8, 8, 8, 2, 4

};

int melody2[] = {

 NOTE_C4, NOTE_F4, NOTE_F4, NOTE_F4, NOTE_E4, NOTE_D4, NOTE_C4, NOTE_G3, NOTE_E3, NOTE_C3

};

// note durations: 4 = quarter note, 8 = eighth note, etc.:

int noteDurations2[] = {

 8, 4, 8, 8, 8, 8, 8, 8, 8, 8

};

// the setup routine runs once when you press reset:

void setup() {

 // initialize serial communication at 9600 bits per second:

 Serial.begin(9600);

 // make the pushbutton's pin an input:

 pinMode(pushButton1, INPUT);

 pinMode(pushButton2, INPUT);

 pinMode(pushButton3, INPUT);

 pinMode(pushButton4, INPUT);

 pinMode(led1, OUTPUT);

 pinMode(led2, OUTPUT);

 pinMode(led3, OUTPUT);

}

// the loop routine runs over and over again forever:

void loop() {

 int buttonState4 = digitalRead(pushButton4);

 // print out the state of the button:

 //Serial.println(buttonState);

 delay(1);  // delay in between reads for stability // moved up from loop, green and yellow don't work

 // // read the input pin:

 int buttonState = digitalRead(pushButton1);

 //print out the state of the button:

 //Serial.println(buttonState);

 delay(10);  // delay in between reads for stability

 if (buttonState == 1) {

   //Serial.println(led1hitnum);

   led1hitnum = led1hitnum + 1;

   if (led1hitnum % 2 == 1) {

     digitalWrite(led1, HIGH);

   } else {

     digitalWrite(led1, LOW);

   }

   delay(100);

 }

 int buttonState2 = digitalRead(pushButton2);

 //Serial.println(buttonState2);

 delay(10);  // delay in between reads for stability

 if (buttonState2 == 1) {

   //Serial.println(led2hitnum);

   led2hitnum = led2hitnum + 1;

   if (led2hitnum % 2 == 1) {

     digitalWrite(led2, HIGH);

   } else {

     digitalWrite(led2, LOW);

   }

   delay(100);

 }

 int buttonState3 = digitalRead(pushButton3);

 // print out the state of the button:

 //Serial.println(buttonState3);

 delay(10);  // delay in between reads for stability

 if (buttonState3 == 1) {

   //Serial.println(led3hitnum);

   led3hitnum = led3hitnum + 1;

   if (led3hitnum % 2 == 1) {

     digitalWrite(led3, HIGH);

   } else {

     digitalWrite(led3, LOW);

   }

   delay(100);

 }

 if (buttonState4 == HIGH) {

   startTime = millis();

   tone(7, 262);  //

   delay(500);

   noTone(7);

 }

 if (led1hitnum % 2 == 1 && led2hitnum % 2 == 1 && led3hitnum % 2 == 1) {

   if (millis() - startTime < 60000) {

     win();

   }

 }

 if (startTime != -1 && millis() - startTime > 60000) {

   noTone(7);       // turn it off

   startTime = -1;  // mark as stopped again

 }

 Serial.println(millis() - startTime);

 //Serial.println(millis() - startTime);

    if (millis() - startTime > 600000) {

     lose();

   }

 }

void win() {

 //for(int thisNote = 0; thisNote < 9; thisNote++) {

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

   // to calculate the note duration, take one second divided by the note type.

   //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.

   int noteDuration = 1000 / noteDurations[thisNote];

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

   digitalWrite(led1, LOW);

 }

 delay(10000);

}

void lose() {

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

   // to calculate the note duration, take one second divided by the note type.

   //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.

   int noteDuration = 1000 / noteDurations2[thisNote];

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

   digitalWrite(led1, HIGH);

 }

 delay(10000);

}







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

  Public Constants

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

#define NOTE_B0 31

#define NOTE_C1 33

#define NOTE_CS1 35

#define NOTE_D1 37

#define NOTE_DS1 39

#define NOTE_E1 41

#define NOTE_F1 44

#define NOTE_FS1 46

#define NOTE_G1 49

#define NOTE_GS1 52

#define NOTE_A1 55

#define NOTE_AS1 58

#define NOTE_B1 62

#define NOTE_C2 65

#define NOTE_CS2 69

#define NOTE_D2 73

#define NOTE_DS2 78

#define NOTE_E2 82

#define NOTE_F2 87

#define NOTE_FS2 93

#define NOTE_G2 98

#define NOTE_GS2 104

#define NOTE_A2 110

#define NOTE_AS2 117

#define NOTE_B2 123

#define NOTE_C3 131

#define NOTE_CS3 139

#define NOTE_D3 147

#define NOTE_DS3 156

#define NOTE_E3 165

#define NOTE_F3 175

#define NOTE_FS3 185

#define NOTE_G3 196

#define NOTE_GS3 208

#define NOTE_A3 220

#define NOTE_AS3 233

#define NOTE_B3 247

#define NOTE_C4 262

#define NOTE_CS4 277

#define NOTE_D4 294

#define NOTE_DS4 311

#define NOTE_E4 330

#define NOTE_F4 349

#define NOTE_FS4 370

#define NOTE_G4 392

#define NOTE_GS4 415

#define NOTE_A4 440

#define NOTE_AS4 466

#define NOTE_B4 494

#define NOTE_C5 523

#define NOTE_CS5 554

#define NOTE_D5 587

#define NOTE_DS5 622

#define NOTE_E5 659

#define NOTE_F5 698

#define NOTE_FS5 740

#define NOTE_G5 784

#define NOTE_GS5 831

#define NOTE_A5 880

#define NOTE_AS5 932

#define NOTE_B5 988

#define NOTE_C6 1047

#define NOTE_CS6 1109

#define NOTE_D6 1175

#define NOTE_DS6 1245

#define NOTE_E6 1319

#define NOTE_F6 1397

#define NOTE_FS6 1480

#define NOTE_G6 1568

#define NOTE_GS6 1661

#define NOTE_A6 1760

#define NOTE_AS6 1865

#define NOTE_B6 1976

#define NOTE_C7 2093

#define NOTE_CS7 2217

#define NOTE_D7 2349

#define NOTE_DS7 2489

#define NOTE_E7 2637

#define NOTE_F7 2794

#define NOTE_FS7 2960

#define NOTE_G7 3136

#define NOTE_GS7 3322

#define NOTE_A7 3520

#define NOTE_AS7 3729

#define NOTE_B7 3951

#define NOTE_C8 4186

#define NOTE_CS8 4435

#define NOTE_D8 4699

#define NOTE_DS8 4978

Leave a Reply

Your email address will not be published. Required fields are marked *