Final Project: “Light is Like Water”, an Interactive Diorama

I must start off by admitting that time, though endless (as my high school Calculus professor used to say, “there’s more time than life”), is often insufficient. That was my experience these past couple of weeks. There is so much I wanted to do for this project that I couldn’t implement not because of technical difficulties, but because of time.

Thus, my biggest takeaway is this: a project that one is excited about could go on forever. I was thrilled to carry out my ideas for this final assignment, because I’m fascinated by the story that inspired it. It was fruitful in the end: I’m proud of what I made. But I could have continued to work on it more, adding more features and fixing others, and refining the “craftsmanship.” I’m glad this is the case, though. It means that this project motivated and inspired me, in a way few projects throughout the semester had.

Inspiration

The story on which I based my work is titled “La luz es como el agua,” or “Light is like water” in English, written by world-famous Colombian author Gabriel García Márquez in 1978. I learned about the text from a friend who read it in high school, and purchased the book where this short story is featured (Doce cuentos peregrinos, or Twelve Pilgrims Stories) last summer.

Throughout the semester, I wanted to work with a track from Pirates of the Caribbean for my final project. However, having used it for one of our weekly assignments, I began to consider other possibilities, and when I remembered García Márquez’s story, it made perfect sense to use it.

This link contains two edited (abridged) versions of the story: one in English, translated by myself, and the other in Spanish. The story was shortened specifically for this project, but the complete text can easily be found online in both Spanish and English.

What I love about García Márquez’s writing is its richness in imagery. His descriptions very easily make the stories come to life for the reader, and thus (it seems to me) there’s a lot to work with if one wishes to depict his narrations.

Two aspects of this story made it particularly adequate for an interactive media project. Firstly, the text deals with electricity: it tells the story of two brothers who cause light (electricity) to “flow” like water, ending on a tragic note. I’ve been interested in working with neopixels ever since our “Stupid Pet Trick” assignment, and thought that they could be used in this project to literally show light around a house, and to make it appear as water.

Secondly, the story allows for interactivity in a fantastic way. The title of the text comes from the narrator’s confession that he once told the two brothers that light is like water.  Thus, the narrator, who tells most of the story in third person, reveals to the reader his role and direct impact on the events that unfold. I wanted the user to be directly implicated in the story’s events as well, having them “cause” said events.

Process, USER TESTING, & Improvements

I was quite lousy regarding the documentation of this project. I took no photographs of the process, the user testing stage, or of its exhibition during the Interactive Media Spring Showcase.

As the following images (taken after the project was exhibited) show, the “main” component of the project is a house I built mostly out of cardboard. The house can be divided into two sections: the top level (or the fifth floor, according to the story) and the bottom level (or the first floor, in my interpretation a basement). The top level contains the setting of the story, plagued with LEDs, and the roof of the building, which has two servo motors hidden inside it. The bottom level is full of wires that connect the top level’s components to power, as well as to Procesing and Arduino through a RedBoard.

Left: View of the complete house. Center: Bottom level (LEDs and wires). Right: Top level (decorative elements, LEDs, and servo motors).

I now include a video of the final project, to serve as the frame of reference for the explanation of the process. This video shows the interaction in English.

I mentioned that the video’s interaction is in English because, as the starting page of the Processing sketch shows, there is also a version of the project in Spanish, which the user can opt for. To me, it was important to include a version of the experience guided by the original story, given that I could never accomplish an accurate imitation of García Marquez’s style in a translation. Because I’m such a big fan of his writing, I wanted his words to be available to Spanish-speaking users.

On a related note, I asked a fellow classmate to help me with the project because I imagined that his voice, specifically, would make the narration of the story much richer than if I had done it myself. Not only is he a great speaker, but he is also Colombian; thus, I thought, it becomes easier to imagine García Márquez himself reciting the text. Perfect casting (thank you, Sebastián!).

In terms of the structure, the bottom level was made by cutting a cardboard box and covering it with black adhesive material (I’m not sure whether to call it paper, plastic…). I cut a small rectangle on one of its sides to let the cables of the RedBoard, neopixel strips, and a small light out, so that I could connect them all to an external power source.

The aforementioned small light was used to illuminate the four wires that the user has to connect. I chose to use a breadboard and breadboard wires for the user interaction for a couple of reasons. In the first place, because the story deals with electric circuits, I wanted the user to have the experience of messing with the house’s actual circuits. I originally left the entire “basement” open, such that the user could easily see not only the four wires they had to manipulate, but also the ones that they didn’t have to use (the ones connected to the RedBoard and a second breadboard). I added the four LEDs that are associated to these wires so that they could act not only as indicators for my own code (of whether or not the wires are connected), but also as indicators for the user.

However, during user testing, my first user expressed that it was confusing to know which wires to connect and disconnect, given that there were so many. To the user, it wasn’t clear what was expected of them. Following his advice, I added a piece of transparent acrylic (hence, it still allows some visibility) to completely separate the four wire-LED pairs and the rest of the circuit.

I also incorporated written instructions in the Processing sketch, right before the narration begins. In them, I tell the user that they must pay attention to the narration (audio) and both the screen and the house (visual). In this way, they know they must be aware of all these components throughout their experience.

The same user also suggested not having written instructions at all, making the computer screen go black after the title clip, with the instructions transmitted through audio. He thought that this would make the experience with the house more immersive, and to separate the narration from the instructions, I could read the latter out loud myself. I recorded these instructions, and was willing to make these changes. But… time. This is definitely an improvement that I would have liked to try, even though I did have one preoccupation: what if the user didn’t understand the instructions right away? Another user who tested the project was slightly confused at the beginning as to where the wires should be connected, but she figured it out after reading the instructions a second time. I think the solution would have been to loop the audio instructions as long as the required task has not been completed.

Another advantage of using a breadboard as the interface is that, by covering up most of the board with tape and leaving one of the positive rails uncovered, I ask the user to connect the wires “along the red line” and don’t have to worry about where exactly they’ll connect them, or in which order, given that all the openings in the rail act the same.

Regarding decorative elements, the bottom level has a large number 47, in reference to the story’s building number, and a set of stairs and floors on one of its sides. I did this because the story mentions that the brothers and their parents live in the fifth floor of their building. Therefore, there’s the bottom level, three floors in between, and the top level, all connected by stairs.

These decorations (as well as the ones in the top level) were very successful during user testing. People appreciate these small details, even if the information of the building is provided until the very end of the narration.

Stairs and floors and stairs and floors and stairs and floors and stairs and floors…

The top level was more complex. I built the box myself, because it needed double walls. The neopixels strips that simulate the water-electricity are glued to the outer walls and the inner walls are covered with translucent paper that allows the user to see the light of the neopixels, diffusing it a bit as well. The same was done with the ceiling.

There are two small openings in the ceiling that go through the cardboard and the paper. I cut a straw to get two small pieces that I glued to these openings. Each of the two servo motors has a wire tied to its arm (which has openings itself, facilitating the process of tying the wire), which moves up and down through the straw when the servo rotates. This mechanism allows the up and down movement of the boat.

The decorative elements inside the top level were printed out on paper and made sturdy by glueing them to cardboard and wooden sticks that go through the cardboard floor. For the four lamps, wires attached to yellow LEDs also go through the cardboard, so that each of the lamps turns on and off in response to the user’s actions. Additionally, there are two other pieces of furniture inside the house: a grand piano and a bar with a wine bottle. These are also referenced in the story.

I decided to make the “flooding” neopixels blue until the very end of the story, when they become yellow and “end” the metaphor of light as water. If one googles this story, the image results mostly show yellow waves and currents, and in the story, the children’s adventures are very explicitly described as occuring in the light, and not water (though water-related terms are constantly used in the text). The advantage of using actual light to depict García Márquez’s water-electricity is that no matter its color, the light is still (actual, physical) light. Thus, in my opinion, the metaphor becomes stronger with lights in blue, like water. I also made them randomly change to different shades of blue with every loop in the Arduino code, to resemble shimmering water.

This is a compilation of Google Images results for “la luz es como el agua”; all of them show the water colored yellow, or alternatively, the light shaped as waves.

The following show the code that was used in this assignment.

Arduino:

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h>
#endif

#include <Servo.h>

Servo boatRight;
Servo boatLeft;

const int ledGreen = 10;
const int ledRed = 11;
const int ledBlue = 2;
const int ledYellow = 13;

const int tallLeft= 8;
const int shortLeft = 7;
const int tallRight = 4;
const int shortRight = 3;

const int PIN = 6;

const int NUMPIXELS = 180;

int stage;

int serialComm;

const int colors[] = {47, 86, 233, 45, 100, 245, 47, 141, 255, 51, 171, 249,
52, 204, 255, 82, 219, 255};
const int colorsFire[] = {255, 127, 0, 255, 143, 0, 255, 105, 0, 229, 83, 0};

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
 pinMode(ledGreen, INPUT);
 pinMode(ledRed, INPUT);
 pinMode(ledBlue, INPUT);
 pinMode(ledYellow, INPUT);
 pinMode(tallLeft, OUTPUT);
 pinMode(shortLeft, OUTPUT);
 pinMode(tallRight, OUTPUT);
 pinMode(shortRight, OUTPUT);

boatRight.attach(9); 
 boatLeft.attach(5);

setupStuff();

Serial.begin(9600);
 Serial.println("100");
}

void setupStuff(){
 boatRight.write(180); 
 boatLeft.write(0);

pixels.begin();
 pixels.setBrightness(10);
 pixels.clear();
 pixels.show();
 
 stage = -1;

serialComm = 0;
}

void loop() {
 int green = digitalRead(ledGreen);
 int red = digitalRead(ledRed);
 int blue = digitalRead(ledBlue);
 int yellow = digitalRead(ledYellow);
 if(stage == 0){
 if(green == LOW){
 digitalWrite(tallLeft, LOW);
 }
 else if(green == HIGH){
 digitalWrite(tallLeft, HIGH);
 };
 if(red == LOW){
 digitalWrite(shortRight, LOW);
 }
 else if(red == HIGH){
 digitalWrite(shortRight, HIGH);
 };
 if(blue == LOW){
 digitalWrite(tallRight, LOW);
 }
 else if(blue == HIGH){
 digitalWrite(tallRight, HIGH);
 };
 if(yellow == LOW){
 digitalWrite(shortLeft, LOW);
 }
 else if(yellow == HIGH){
 digitalWrite(shortLeft, HIGH);
 };
 if(green == HIGH && red == HIGH && blue == HIGH && yellow == HIGH){
 serialComm = 1;
 boatRight.write(120); 
 boatLeft.write(50); 
 };
 }
 else if(stage == 1){
 if(green == LOW){
 serialComm = 2;
 digitalWrite(tallLeft, LOW);
 for(int i=0; i<9; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 for(int i=76; i<88; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 for(int i=115; i<124; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 pixels.show();
 for (int pos = 50; pos <= 120; pos ++) {
 boatLeft.write(pos); 
 boatRight.write(120 - pos);
 delay(15);
 }
 for (int pos = 120; pos <= 50; pos --) {
 boatRight.write(pos - 120);
 boatLeft.write(pos); 
 delay(15);
 }
 };
 }
 else if(stage == 2){
 if(red == LOW){
 serialComm = 3;
 digitalWrite(shortRight, LOW);
 for(int i=0; i<18; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 for(int i=63; i<88; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 for(int i=106; i<124; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 pixels.show();
 for (int pos = 50; pos <= 140; pos ++) {
 boatLeft.write(pos); 
 boatRight.write(130 - pos);
 delay(15);
 }
 for (int pos = 140; pos <= 50; pos --) {
 boatRight.write(pos - 130);
 boatLeft.write(pos); 
 delay(15);
 }
 };
 }
else if(stage == 3){
 if(blue == LOW){
 serialComm = 4;
 digitalWrite(tallRight, LOW);
 for(int i=0; i<27; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 for(int i=49; i<88; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 pixels.show();
 };
 for(int i=97; i<124; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 pixels.show();
 for (int pos = 50; pos <= 160; pos ++) {
 boatLeft.write(pos); 
 boatRight.write(160 - pos);
 delay(15);
 }
 for (int pos = 160; pos <= 50; pos --) {
 boatRight.write(pos - 160);
 boatLeft.write(pos);
 delay(15);
 }
 };
 }
else if(stage == 4){
 if(yellow == LOW){
 serialComm = 5;
 digitalWrite(shortLeft, LOW);
 for(int i=0; i<36; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 for(int i=38; i<88; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 for(int i=88; i<181; i++){
 int index = int(random(0,6))*3;
 int R = colors[index];
 int G = colors[index + 1];
 int B = colors[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 pixels.show();
 for (int pos = 50; pos <= 180; pos ++) {
 boatLeft.write(pos); 
 boatRight.write(180 - pos);
 delay(15);
 }
 for (int pos = 180; pos <= 50; pos --) {
 boatRight.write(pos - 180);
 boatLeft.write(pos);
 delay(15);
 }
 };
 }
 else if(stage == 5){
 serialComm = 6;
 for(int i=0; i<181; i++){
 int index = int(random(0,4))*3;
 int R = colorsFire[index];
 int G = colorsFire[index + 1];
 int B = colorsFire[index + 2];
 pixels.setPixelColor(i, R, G, B);
 };
 pixels.show();
 boatRight.write(180); 
 boatLeft.write(0);
 }
 else if(stage == 6){
 setupStuff();
 };
 if(Serial.available() > 0){
 
 stage = Serial.read();
 Serial.println(serialComm);
 };
}

Processing:

import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;

Minim minim;
import processing.sound.*;

import processing.serial.*;
Serial myPort;

SoundFile beginSound;
AudioPlayer iESP, iiESP, iiiESP, ivESP, vESP, viESP, viiESP;
AudioPlayer iENG, iiENG, iiiENG, ivENG, vENG, viENG, viiENG;

PFont font1, font2;
boolean startESP, startENG;
int colorChange;
int colorChangerESP, colorChangerESP1, colorChangerESP2, colorChangerESP3;
int colorChangerENG, colorChangerENG1, colorChangerENG2, colorChangerENG3;
String intro1, intro2, intro3, intro4, intro5, intro6, intro7;
int alphaCounter1, alphaCounter2;
boolean alpha;
boolean begin, narration, story, end, restart;
int track;
int bgColor;
String text1, subtext1, text2, text3, text4, text5;
String og, tr, na;
int serialComm;
int stage;

void menu(){
 textAlign(LEFT);
 if(mouseX >= width/10*2.5 && mouseX <= width/10*4.5 
 && mouseY >= height/9*4 && mouseY <= height/9*5){
 if(mousePressed){
 startESP = true;
 }
 else{
 if(colorChangerESP < colorChange){
 colorChangerESP = colorChange;
 }
 if(colorChangerESP1 < colorChange - 30){
 colorChangerESP1 = colorChange - 30;
 }
 if(colorChangerESP2 < colorChange - 60){
 colorChangerESP2 = colorChange - 60;
 }
 if(colorChangerESP3 < colorChange - 90){
 colorChangerESP3 = colorChange - 90;
 }
 if(colorChangerESP3 < 255){
 colorChangerESP+=10;
 colorChangerESP1+=10;
 colorChangerESP2+=10;
 colorChangerESP3+=10;
 }
 };
 }
 else{
 colorChangerESP-=10;
 colorChangerESP1-=10; 
 colorChangerESP2-=10;
 colorChangerESP3-=10;
 };
 if(mouseX >= width/10*5.5 && mouseX <= width/10*7.5 
 && mouseY >= height/9*4 && mouseY <= height/9*5){
 if(mousePressed){
 startENG = true;
 }
 else{
 if(colorChangerENG < colorChange){
 colorChangerENG = colorChange;
 }
 if(colorChangerENG1 < colorChange - 30){
 colorChangerENG1 = colorChange - 30;
 }
 if(colorChangerENG2 < colorChange - 60){
 colorChangerENG2 = colorChange - 60;
 }
 if(colorChangerENG3 < colorChange - 90){
 colorChangerENG3 = colorChange - 90;
 }
 if(colorChangerENG3 < 255){
 colorChangerENG+=10;
 colorChangerENG1+=10; 
 colorChangerENG2+=10;
 colorChangerENG3+=10;
 }
 };
 }
 else{
 colorChangerENG-=10;
 colorChangerENG1-=10; 
 colorChangerENG2-=10;
 colorChangerENG3-=10;
 }
 colorMode(HSB);
 noFill();
 strokeWeight(4);
 stroke(35, 100, colorChangerESP1);
 rect(width/10*2.5, height/9*4, width/10*2, height/9);
 stroke(140, 100, colorChangerENG1);
 rect(width/10*5.5, height/9*4, width/10*2, height/9);
 strokeWeight(3);
 stroke(35, 100, colorChangerESP2);
 rect(width/10*2.5 - 10, height/9*4 - 10, width/10*2 + 20, height/9 + 20);
 stroke(140, 100, colorChangerENG2);
 rect(width/10*5.5 - 10, height/9*4 - 10, width/10*2 + 20, height/9 + 20);
 strokeWeight(2); 
 stroke(35, 100, colorChangerESP3);
 rect(width/10*2.5 - 17.5, height/9*4 - 17.5, width/10*2 + 35, height/9 + 35);
 stroke(140, 100, colorChangerENG3);
 rect(width/10*5.5 - 17.5, height/9*4 - 17.5, width/10*2 + 35, height/9 + 35);
 fill(30, 100, colorChangerESP);
 text("español", width/10*3, height/9*4.65);
 fill(140, 100, colorChangerENG);
 text("english", width/10*6, height/9*4.65);
}

void begin(){
 if(startESP){
 intro1 = "La luz";
 intro2 = " es como el agua:";
 intro3 = "uno abre el grifo,";
 intro4 = " y sale.";
 intro5 = "Esta es una experiencia interactiva audiovisual.";
 intro6 = "La historia será transmitida por audio, las instrucciones aparecerán en la pantalla, y la casa cobrará vida."; 
 intro7 = "Haz click para continuar.";
 bgColor = 140;
 }
 else if(startENG){
 intro1 = "Light";
 intro2 = "is like water:";
 intro3 = "one turns the tap,";
 intro4 = "and out it comes.";
 intro5 = "This is an audiovisual interactive experience.";
 intro6 = "The story will be transmitted by audio, the instructions will appear on screen, and the house will come to life.";
 intro7 = "Click to continue.";
 bgColor = 22;
 };
 if(begin == false && alphaCounter1 >= 20){
 beginSound.play();
 begin = true;
 };
 if(alpha == false){
 alphaCounter1++;
 if(alphaCounter1 > 65){
 alphaCounter2++;
 }
 };
 if(alphaCounter2 >= 240){
 fill(bgColor, 100, 255, alphaCounter2 - 240);
 rect(0, 0, width, height);
 if(mousePressed){
 beginSound.stop();
 narration = true;
 };
 };
 textSize(250);
 fill(0, alphaCounter1);
 text(intro1, width/10*2, height/9*3.5);
 textSize(100);
 fill(0, alphaCounter2);
 text(intro2, width/10*5, height/9*4);
 fill(0, alphaCounter1 - 150);
 text(intro3, width/10*2, height/9*5);
 textSize(170);
 fill(0, alphaCounter2 - 145);
 text(intro4, width/10*3, height/9*6.5);
 textSize(50);
 fill(0, alphaCounter2 - 200);
 text("- Gabriel García Márquez", width/10*6, height/9*8);
 fill(255);
 textFont(font1);
 text(intro5, width/50, height/15);
 text(intro6, width/50, height/15 + 30);
 text(intro7, width/50, height/15 + 60);
}

void story(){
 textAlign(CENTER);
 textFont(font1);
 fill(0);
 if(story == false){
 alphaCounter1 = -10;
 if(track == 1){
 if(startENG == true){
 iENG.play();
 }
 else if(startESP == true){
 iESP.play();
 };
 }
 else if(track == 2){
 if(startENG == true){
 iiENG.play();
 }
 else if(startESP == true){
 iiESP.play();
 };
 }
 else if(track == 3){
 if(startENG == true){
 iiiENG.play();
 }
 else if(startESP == true){
 iiiESP.play();
 };
 }
 else if(track == 4){
 if(startENG == true){
 ivENG.play();
 }
 else if(startESP == true){
 ivESP.play();
 };
 }
 else if(track == 5){
 if(startENG == true){
 vENG.play();
 }
 else if(startESP == true){
 vESP.play();
 };
 }
 else if(track == 6){
 if(startENG == true){
 viENG.play();
 }
 else if(startESP == true){
 viESP.play();
 };
 }
 else if(track == 7){
 if(startENG == true){
 viiENG.play();
 }
 else if(startESP == true){
 viiESP.play();
 };
 };
 story = true;
 }
 else{
 if(track == 1){
 if(startENG == true){
 text1 = "Connect all the cables to the positive rail";
 subtext1 = "(along the red line)";
 }
 else if(startESP == true){
 text1 = "Conecta todos los cables al bus positivo";
 subtext1 = "(a lo largo de la línea roja)";
 };
 if(! iENG.isPlaying() && ! iESP.isPlaying()){
 stage = 0;
 alphaCounter1++;
 fill(0, alphaCounter1);
 text(text1, width/2, height/2);
 text(subtext1, width/2, height/2 + 35);
 if(serialComm == 1){
 story = false;
 track++;
 };
 };
 }
 else if(track == 2){
 if(startENG == true){
 text2 = "Disconnect the green cable";
 }
 else if(startESP == true){
 text2 = "Desconecta el cable verde";
 };
 if(! iiENG.isPlaying() && ! iiESP.isPlaying()){
 stage = 1;
 alphaCounter1++;
 fill(0, alphaCounter1);
 text(text2, width/2, height/2);
 if(serialComm == 2){
 story = false;
 track++;
 };
 };
 }
 else if(track == 3){
 if(startENG == true){
 text3 = "Disconnect the red cable";
 }
 else if(startESP == true){
 text3 = "Desconecta el cable rojo";
 };
 if(! iiiENG.isPlaying() && ! iiiESP.isPlaying()){
 stage = 2;
 alphaCounter1++;
 fill(0, alphaCounter1);
 text(text3, width/2, height/2);
 if(serialComm == 3){
 story = false;
 track++;
 };
 };
 }
 else if(track == 4){
 if(startENG == true){
 text4 = "Disconnect the blue cable";
 }
 else if(startESP == true){
 text4 = "Desconecta el cable azul";
 };
 if(! ivENG.isPlaying() && ! ivESP.isPlaying()){
 stage = 3;
 alphaCounter1++;
 fill(0, alphaCounter1);
 text(text4, width/2, height/2);
 if(serialComm == 4){
 story = false;
 track++;
 };
 };
 }
 else if(track == 5){
 if(startENG == true){
 text5 = "Disconnect the yellow cable";
 }
 else if(startESP == true){
 text5 = "Desconecta el cable amarillo";
 };
 if(! vENG.isPlaying() && ! vESP.isPlaying()){
 stage = 4;
 alphaCounter1++;
 fill(0, alphaCounter1);
 text(text5, width/2, height/2);
 if(serialComm == 5){
 story = false;
 track++;
 };
 };
 }
 else if(track == 6){
 if(! viENG.isPlaying() && ! viESP.isPlaying()){
 stage = 5;
 if(serialComm == 6){
 story = false;
 track++;
 };
 };
 }
 else if(track == 7){
 if(! viiENG.isPlaying() && ! viiESP.isPlaying()){
 stage = 6;
 end = true;
 alphaCounter2 = -10;
 };
 };
 };
}

void credits(){
 fill(bgColor, 100, 255, alphaCounter2);
 alphaCounter2++;
 rect(0, 0, width, height);
 textAlign(CENTER);
 textFont(font2);
 fill(0, alphaCounter2);
 if(startENG == true){
 og = "Original story";
 tr = "Translation and editing";
 na = "Narration";
 }
 else if(startESP == true){
 og = "Cuento original";
 tr = "Edición";
 na = "Narración";
 };
 textSize(70);
 text(og, width/2, height*0.25);
 textSize(50);
 text("Gabriel García Márquez", width/2, height*0.32);
 textSize(70);
 text(tr, width/2, height*0.5);
 textSize(50);
 text("María Laura Mirabelli", width/2, height*0.57);
 textSize(70);
 text(na, width/2, height*0.75);
 textSize(50);
 text("Sebastián Rojas Cabal", width/2, height*0.82);
 if(startESP == true){
 intro5 = "Haz click para finalizar";
 }
 else if(startENG == true){
 intro5 = "Click to end";
 };
 textAlign(LEFT);
 fill(255);
 textFont(font1);
 text(intro5, width/50, height/15);
 if(mousePressed){
 restart = true;
 };
};

void setup(){
 String portName = Serial.list()[2];
 myPort = new Serial (this, portName, 9600);
 myPort.clear();
 myPort.bufferUntil('\n');
 
 fullScreen();
 font1 = createFont("Arvo-Bold.ttf", 30);
 font2 = createFont("Handycheera.otf", 70);
 
 setupStuff();
}

void setupStuff(){
 startESP = startENG = false;
 colorChange = 200;
 colorChangerESP = colorChangerESP1 = colorChangerESP2 = colorChangerESP3 = 0;
 colorChangerENG = colorChangerENG1 = colorChangerENG2 = colorChangerENG3 = 0;
 intro1 = intro2 = intro3 = intro4 = intro5 = intro6 = intro7 = "";
 alphaCounter1 = alphaCounter2 = -10;
 alpha = false;
 begin = narration = story = end = restart = false;
 bgColor = 0;
 track = 1;
 serialComm = 0;
 stage = -1;
 
 beginSound = new SoundFile(this, "beginSound.wav");
 minim = new Minim(this);
 iESP = minim.loadFile("I.wav");
 iiESP = minim.loadFile("II.wav");
 iiiESP = minim.loadFile("III.wav");
 ivESP = minim.loadFile("IV.wav");
 vESP = minim.loadFile("V.wav");
 viESP = minim.loadFile("VI.wav");
 viiESP = minim.loadFile("VII.wav");
 iENG = minim.loadFile("1.wav");
 iiENG = minim.loadFile("2.wav");
 iiiENG = minim.loadFile("3.wav");
 ivENG = minim.loadFile("4.wav");
 vENG = minim.loadFile("5.wav");
 viENG = minim.loadFile("6.wav");
 viiENG = minim.loadFile("7.wav");
}

void draw(){
 background(255);
 textFont(font2);
 if(startESP == false && startENG == false){
 narration = false;
 menu();
 }
 else{
 if(narration == false){
 begin();
 }
 else{
 if(end == false){
 story();
 }
 else{
 if(restart == true){
 setupStuff();
 };
 credits();
 };
 };
 };
}

void serialEvent(Serial myPort){
 String s = myPort.readStringUntil('\n');
 s = trim(s);
 //println(s);
 if(s != null){
 serialComm = int(s);
 };
 myPort.write(stage);
}