Midterm Project: Dinner Theater
“Dinner Theater” – Eva Weisenfeld – Andy Garcia
One of the original inspiration for “Dinner Theater” came from the stress of the dinner rush. I have worked in a restaurant before, and know that as pressure builds, so does a person’s fallibility. I was also inspired by the hotel room service challenge in Master Chef Junior, which displayed the same concept. Although these may not be interactive in and of themselves, I felt we could take the experiences of these chefs and food workers, and turn it into an interactive project for a broader community.
We were initially going to make a two-player game that challenged players to be the first to finish plating a steak dish. Our plan was to use pressure sensors to determine the correct placement of each component of the dish, keeping track of which player could plate quickly, while maintaining accuracy. We hoped that this would help simulate a rush hour environment, while engaging the players in some competitive fun. Since people often overlook the struggles of working in the food industry, I hoped that this could help the players gain a greater understanding of the pressures people face when preparing their food.
However, when we learned that the pressure sensor was not a viable option, we turned to Professor Garcia, who steered us in the direction of the digital scale. Since there was only one available, our project immediately shifted from a two-person game to a one-person game. Additionally, the focal point of the project had to shift from plating to making certain recipes. In our discussion with Professor Garcia, we also decided to switch from a steak dish to a burger.
We had a lot of issues with calibrating the scale, so we eventually gave up on calibrating it to accuracy and instead getting to a point where we received consistent values. Once we got there, we started making our burger ingredients. We initially planned to make everything from clay, but quickly realized that to accomplish this goal, we would need way more clay than we previously thought. So, we settled on a clay burger patty, while everything else was 3D printed. Once we had our ingredients prepared, we realized that the weight differentiation was not significant enough for the purpose of our project. That was when Professor Garcia suggested we use gears that had been in the studio for a while. Since we already had the ingredients prepared, we decided to hot glue the gears to the ingredients (though it would have been ideal to have found a way to hide them). To make the ingredients prettier (and to avoid confusion as to what shape represents what ingredient), I painted all of the objects we made to get them to look as similar to the real thing as I could. In order to make the gears blend in more, I painted over the gears to match the paint job on top (a la Disney).
More on the programming side: figuring out how to get everything to work was definitely difficult at first. As I mentioned before, the main issue was learning how to program the scale. Once that was figured out, all I had to do was figure out what size margin of error I should use when checking an item’s weight. Then, I got to the random burger. This one was particularly tricky for me because I did not yet understand how to use arrays/lists/arrayLists (yes, I tested all three) in C++. At a certain point, I gave up and decided to create recipes and use the random feature to pick one. Luckily, the answer to my array problem came to me in a dream and I was able to implement my original goal for that level (which felt amazing). Initially, implementing the LCD was a little difficult because documentation regarding its usage is hard to come by. However, after some trial and error, we were able to figure it out. Once we got that down, the rest was really easy to do. Random thing about the programming: I found that everything is nicer to me when I cast it as a double. I don’t know why but if it works, it works I guess.
FULL CODE:
#include "HX711.h"
#include <LiquidCrystal.h>
const int dtPin = 2;
const int sckPin = 3;
const double calibration = 2640.0;
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
const int hatPin = 13;
int hatState = 0;
int counter = 0;
int escape = 0;
double reading;
int startTime;
int finalTime;
int record = INT8_MAX;
double topBun = 91.2;
double pat = 77.8;
double lettuce = 37.5;
double tomato = 75.6;
double cheese = 37.0;
double botBun = 83.3;
double ingreds[6] = {topBun, pat, lettuce, tomato, cheese, botBun};
double cheeseBurg[4] = {topBun, pat, cheese, botBun};
double classic[6] = {topBun, pat, lettuce, tomato, cheese, botBun};
HX711 scale;
void setup() {
Serial.begin(9600);
pinMode(hatPin, INPUT);
lcd.begin(16, 2);
lcd.clear();
Serial.println("Initializing the scale...");
scale.begin(dtPin, sckPin);
scale.set_scale(calibration);
scale.tare();
reading = scale.get_units();
Serial.print("The raw reading is: ");
Serial.println(scale.read());
Serial.print("Your dish weighs: ");
Serial.println(reading, 1);
}
void loop(){
reading = scale.get_units();
if(counter == 0){
lcd.setCursor(2, 0);
lcd.print("Restarting ");
lcd.setCursor(4, 1);
lcd.print("game... ");
delay(1000);
}
else if(counter == 1){
lcd.setCursor(1, 0);
lcd.print("Starting up...");
delay(1000);
}
else if(counter > 1){
lcd.setCursor(1, 0);
lcd.print("Leveling up...");
delay(1000);
}
delay(500);
waitingRoom();
}
void start(){
lcd.setCursor(2, 0);
lcd.print("Welcome to ");
lcd.setCursor(0, 1);
lcd.print("Dinner Theater!");
while(escape == 0){
hatState = digitalRead(hatPin);
if(hatState == HIGH){
reading = scale.get_units();
lcd.clear();
startTime = millis();
escape++;
counter++;
}
}
}
void levelUp() {
if(counter == 0){
start();
}
if(counter == 1){
burger_one();
}
else if(counter == 2){
burger_two();
}
else if(counter == 3){
burger_three();
}
}
void waitingRoom(){
lcd.clear();
while(reading > 1){
lcd.setCursor(0, 0);
lcd.print("Don't forget to");
lcd.setCursor(0, 1);
lcd.print("serve your dish!");
delay(1500);
reading = scale.get_units();
}
lcd.clear();
levelUp();
}
void reset(){
lcd.clear();
escape = 0;
}
void burger_one(){
double weight = 0;
for(int val = 0; val < 4; val++){
weight += cheeseBurg[val];
}
lcd.print("Welcome to");
lcd.setCursor(2, 1);
lcd.print("Challenge 1: ");
delay(1500);
lcd.clear();
lcd.print("The Cheeseburger");
delay(1500);
lcd.clear();
lcd.print("You may begin in");
delay(1500);
lcd.setCursor(7, 1);
lcd.print("3... ");
delay(1000);
lcd.setCursor(7, 1);
lcd.print("2... ");
delay(1000);
lcd.setCursor(7, 1);
lcd.print("1... ");
delay(1000);
lcd.setCursor(7, 1);
lcd.print("GO! ");
delay(1000);
lcd.clear();
while(escape == 1){
if((int)reading >= (int)(weight - 1) && int(reading) <= (int)(weight + 1)){
lcd.print("Great job!");
delay(1000);
lcd.clear();
lcd.setCursor(1,0);
lcd.print("Now let's make ");
lcd.setCursor(2, 1);
lcd.print("it harder... ");
delay(1500);
lcd.clear();
escape ++;
counter++;
}
else if((int)reading < weight - 1){
lcd.setCursor(1, 0);
lcd.print("Way too light!");
delay(150);
}
else if((int)reading > weight + 1){
lcd.setCursor(1, 0);
lcd.print("Way too heavy!");
delay(150);
}
reading = scale.get_units();
delay(1000);
}
}
void burger_two(){
double weight = 0;
lcd.print("Welcome to");
lcd.setCursor(2, 1);
lcd.print("Challenge 2: ");
delay(1500);
lcd.clear();
lcd.setCursor(2, 0);
lcd.print("The Classic ");
delay(1500);
lcd.clear();
lcd.print("You may begin in");
delay(1500);
lcd.setCursor(7, 1);
lcd.print("3... ");
delay(1000);
lcd.setCursor(7, 1);
lcd.print("2... ");
delay(1000);
lcd.setCursor(7, 1);
lcd.print("1... ");
delay(1000);
lcd.setCursor(7, 1);
lcd.print("GO! ");
delay(1000);
lcd.clear();
for(int val = 0; val < 6; val++){
weight += classic[val];
}
while(escape == 2){
if((int)reading >= weight - 1 && (int)reading <= weight + 1){
lcd.setCursor(5, 0);
lcd.print("Wow! ");
delay(1500);
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("You seem like ");
lcd.setCursor(1, 1);
lcd.print("a good chef... ");
delay(3000);
lcd.clear();
lcd.setCursor(2, 0);
lcd.print("But can you ");
delay(1000);
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("figure out the ");
lcd.setCursor(1, 1);
lcd.print("secret recipe? ");
delay(2000);
lcd.clear();
escape ++;
counter++;
}
else if((int)reading < weight - 1){
lcd.setCursor(1, 0);
lcd.print("Way too light!");
delay(150);
}
else if((int)reading > weight + 1){
lcd.setCursor(1, 0);
lcd.print("Way too heavy!");
delay(150);
}
reading = scale.get_units();
delay(1000);
}
}
void burger_three(){
doublenewBurger[6];
lcd.print("Welcome to");
lcd.setCursor(2, 1);
lcd.print("Challenge 3: ");
delay(1500);
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Secret Recipe ");
delay(1500);
lcd.clear();
lcd.print("You may begin in");
delay(1500);
lcd.setCursor(7, 1);
lcd.print("3... ");
delay(1000);
lcd.setCursor(7, 1);
lcd.print("2... ");
delay(1000);
lcd.setCursor(7, 1);
lcd.print("1... ");
delay(1000);
lcd.setCursor(7, 1);
lcd.print("GO! ");
delay(1000);
lcd.clear();
int num = rand() % 5 + 1;
for(int i = 0; i < num; i++){
int n = rand() % 6;
newBurger[i] = ingreds[n];
for(int j = 0; j <= i; j++){
if(newBurger[j] == newBurger[j - 1]){
newBurger[j] = ingreds[int(rand() % 4)];
}
}
}
double weight = 0;
for(int val = 0; val < num; val++){
weight += newBurger[val];
}
delay(1000);
while (escape == 3){
if((int)reading <= (int)weight + 1 && (int)reading >= (int)weight - 1){
finalTime = (millis() - startTime) / 1000;
lcd.print("Congratulations!");
lcd.setCursor(1, 1);
lcd.print("You have won!! ");
delay(3000);
lcd.clear();
if(finalTime < record){
lcd.print("You have beaten");
lcd.setCursor(2, 1);
lcd.print("the record! ");
delay(3000);
lcd.clear();
}
lcd.print("Your time was");
lcd.setCursor(0, 1);
lcd.print((String) finalTime + " seconds");
delay(3000);
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("You really are ");
lcd.setCursor(0, 1);
lcd.print("an amazing chef!");
delay(1000);
counter = 0;
reset();
}
else if((int)reading < weight - 1){
lcd.setCursor(1, 0);
lcd.print("Way too light!");
delay(150);
}
else if((int)reading > weight + 1){
lcd.setCursor(1, 0);
lcd.print("Way too heavy!");
delay(150);
}
reading = scale.get_units();
delay(1000);
}
}
I also made a chef’s hat with copper tape on the bottom (another great idea of Professor Garcia 🙂 ). The original idea was for the user to put the hat on as the cue for the game to start. However, the hat was too light, so the tape did close the circuit. If we had more time, I would have liked to have added something to the hat’s cardboard brim to weigh it down more, so that part of the interaction would work properly.
User Testing: Our project was still a bit buggy during the User Testing: most things were not painted, the third level of the game did not work, and the project itself was not very pretty. A lot of the feedback we received were things we were already planning on fixing in later stages (i.e. making the ingredients more differentiable, communicating more with the player regarding instructions, etc.). For us, the User Testing mostly affirmed a lot of the decisions we had already made regarding the future of the project.
One piece of feedback we received during the User Testing was that players wanted better indications when they were above or below the goal (the burger was above/overweight). Our original plan for this was to install LEDs that would work like a guitar tuner: one would light up if the burger was too heavy, one would light up if the burger was too light. Once the burger was the perfect weight, the plan was to have the LCD display the “congratulations” page, then go on to next steps. However, we had issues with connecting the LEDs, as the jumper cables kept disconnecting, even after we hot glued them. At the end of the day, we ran out of time to finish implementing, so we wound up having all instructions and cues displayed on the LCD instead.
We were also told that there were a lack of instructions regarding the burger recipes. In early iterations of the game, we had planned to have a menu giving the recipes for the first two burgers. However, we decided it would be more fun to let the players figure it out for themselves. I do think that this was a better choice, but, as Professor Garcia mentioned during the final presentation, it does leave a cultural barrier between those who know about American burgers, and those who don’t. Nonetheless, I think our game does help bridge that gap by including the weight indicators. That way, even if a player does not know exactly what goes in a cheeseburger, the LCD can help guide them to their final goal.
As I have mentioned before, at the start of this class, I defined “interaction” as both “mutual or reciprocal action or influence,” as the Merriam Webster Dictionary puts it, and as something that helps deepen one’s understanding of the world. I feel this project met both requirements. The game responds to the actions of the user, prompting the user to do something else, until a specific goal is met, which fulfills the Merriam Webster part of my definition. In addition, my hope is that the project gives the player a deeper understanding of what it is like to prepare food in a high-pressure situation, like that of a professional kitchen. I feel that our audience interacted with the project exactly as expected. We received consistently positive reviews once the project was completed, and I am very proud of what we were able to accomplish. If we had more time, I would have liked to have seen what the LEDs would have looked like. I think we both learned a lot about perseverance and grit throughout the course of the project, but despite everything we were able to follow through with essentially all of our initial goals, so I am really happy with the outcome of this project.
APPENDIX: