Week 11 – Arduino Music Megan

Arduino – Harry Potter Music Box

Concept

For this project, I decided to create a mini music pad that can play the Harry Potter theme. The idea came from a small Harry Potter music box that I was gifted when I was younger, since I have always loved Harry Potter and I am a big fan. I also play the piano, so I wanted to design something that felt similar to an instrument and could simulate specific notes like a simplified keyboard.

Process

For the hardware, I used four colored buttons, a potentiometer, and a buzzer to produce sound. I connected each button to a digital pin, the potentiometer to 5V, GND, and analog pin A0, and the buzzer to another digital pin. All components were connected to ground appropriately.

For the coding part, it was a bit challenging at first to find the right notes. I experimented with a basic Arduino buzzer note library and helped myself with Chat GPT to adjust different frequencies until they sounded closer to the melody I wanted. Since the Harry Potter theme has more than four notes, I used the potentiometer as an analog input to change the pitch of the notes. This allowed me to expand the range of sounds using only four buttons. Although it is not perfectly accurate, the result is still very recognizable and captures the essence of the original theme.

// ==============================
// MINI MUSIC PAD - HARRY POTTER SONG
// ==============================


// BUTTON PINS 
int b1 = 2; // E
int b2 = 3; // G
int b3 = 4; // B
int b4 = 5; // C 

// BUZZER 
int buzzer = 8;

// POTENTIOMETER 
int pot = A0;


// NOTES 
#define E4 329
#define G4 392
#define B4 494
#define C5 510


// ==============================
// SETUP
// ==============================
void setup() {

  pinMode(b1, INPUT_PULLUP);
  pinMode(b2, INPUT_PULLUP);
  pinMode(b3, INPUT_PULLUP);
  pinMode(b4, INPUT_PULLUP);

  pinMode(buzzer, OUTPUT);
}


// ==============================
// LOOP
// ==============================
void loop() {

  int potValue = analogRead(pot);

  // HIGH / LOW pitch mode
  bool highPitch = potValue > 512;

  float multiplier;

  if (highPitch) {
    multiplier = 1.3; // slightly higher pitch
  } else {
    multiplier = 0.85; // slightly lower pitch
  }

  if (digitalRead(b1) == LOW) {
    play(E4, multiplier);
  }

  else if (digitalRead(b2) == LOW) {
    play(G4, multiplier);
  }

  else if (digitalRead(b3) == LOW) {
    play(B4, multiplier);
  }

  else if (digitalRead(b4) == LOW) {
    play(C5, multiplier);
  }

  else {
    noTone(buzzer);
  }
}


// ==============================
// FUNCTION
// ==============================
void play(int note, float mult) {
  tone(buzzer, note * mult);
}

Thing That I’m Proud Of

One part of the project I am especially proud of is how I used the potentiometer to control the pitch. This idea allowed me to overcome the limitation of having only four buttons. Initially, I tried pressing multiple buttons at once to create different sounds, but it did not work as expected. Then I realized I could use the potentiometer to dynamically change the pitch, which was a much more effective solution. I am also proud of the overall design of my mini music pad, as it is intuitive to use and much cleaner than my earlier versions, where the wires were more disorganized.

// HIGH / LOW pitch mode
  bool highPitch = potValue > 512;

  float multiplier;

  if (highPitch) {
    multiplier = 1.3; // slightly higher pitch
  } else {
    multiplier = 0.85; // slightly lower pitch
  }

Overall Reflection

Overall, I really enjoyed this project. It allowed me to combine something personal, like my love for Harry Potter and music, with technical skills such as coding and circuit design. The process involved a lot of experimentation and problem-solving, especially when trying to match the melody. This project also made me feel nostalgic, since the song reminds me of my childhood. I am very happy with the final result and how I was able to turn a simple Arduino setup into an interactive musical experience.

SCHEMATIC

VIDEO

Reading Reflections

Reading A Brief Rant on the Future of Interaction Design and the Response honestly changed the way I see technology in a way I did not expect at all. I agree with the author, but what surprised me the most is that I had never even realized this was a problem in the first place. It is not that our devices are bad, but more that they are limiting us from using our full potential, especially when it comes to how we physically interact with the world.

One thing that really stuck with me was when I started thinking about the idea of using devices with your eyes closed. I asked myself what I could actually do like that, and the only thing I could come up with was typing on my laptop keyboard. And then I realized that typing is one of the only truly tactile interactions we still have, and it is not even part of the screen itself. Everything else, especially touchscreens, feels like just sliding your finger on glass with almost no physical feedback. The reading describes this as “Pictures Under Glass,” and I think that is such a perfect way to put it, because it really does feel disconnected from what you are doing.

It also made me think about why we keep simplifying technology more and more. At first it seems like progress, because everything becomes easier and more accessible, but at the same time, it feels like we are reducing the way we interact with the world to something very basic, almost like we are being treated as toddlers. And that idea really stayed with me, because I had never questioned it before. I never thought that maybe we actually deserve more complex and richer ways of interacting, instead of everything being reduced to tapping and swiping.

I also kept thinking about the comparison between the real world and digital interfaces. In real life, our hands are constantly feeling, adjusting, reacting. The reading gives examples like holding a book or a glass and understanding things like weight and position without even thinking about it. That made me realize how much information we are losing when everything becomes flat and two dimensional. It made me wonder if we are actually moving forward or backward by making everything more and more screen based.

At the same time, I thought about things like movie theaters. It took so long for us to even be able to record and display images, but now we have 3D, 4D, and experiences where you can feel water or heat from what is happening on screen. That feels like a step toward engaging more of our senses. But then I started thinking, what if we did not need glasses to see in 3D, or what if devices could actually communicate through touch in a more real way? Something closer to real life, like materials that change shape or give feedback. That is kind of what the author is pushing for with the idea of a “dynamic medium that we can see, feel, and manipulate.”

At some point, though, I also started questioning how far this can really go. If we keep trying to make technology more and more like real life, are we just trying to recreate reality itself? Because the real world is already the most advanced “interface” we have. So it made me think about where the limit is, and whether the goal should be to replicate reality or to create something entirely new.

Overall, this reading really opened my mind. It made me realize that interaction design is not just about making things look nice or easy to use, but about deeply understanding human capabilities and not ignoring them. I had never questioned touchscreens before, but now I cannot stop thinking about how much more is possible and how much we might be missing out on by staying with what we have.

Week 10 – Production and Reading Reflection Megan

Production: LED Lights Memory Game

Concept

The concept of my project was to create a memory-based LED game inspired by the small game we watched in class. In that example, a light would turn on and the first person to press the button on their side would win. I found that idea very engaging, so I wanted to build something similar but with a stronger focus on memory and sequence. While looking for ideas, I came across the concept of a “Simon Says” style memory game, which immediately reminded me of a toy I used to play with as a child, similar to a Pop It memory game with lights and patterns. This connection made the idea more personal and interesting to develop, so I decided to create a game where the Arduino generates a sequence of LED lights and the player must repeat it correctly using buttons.

Process

To build this project, I started by learning the basic components separately. I watched several tutorials by Paul McWhorter, which helped me understand more things on how LEDs and buttons can work, as well as how to structure Arduino code using functions, loops, and conditionals. I also explored the Arduino documentation to better understand how different functions work and how Arduino programming compares to tools like p5.js. The good thing is that both use similar logical structures, which made it easier for me to understand the code. I programmed the Arduino to generate a random sequence, display it using LEDs, and then check the user’s input through buttons. I also added a startup LED test to verify that the circuit was working correctly before the game begins.

// LED MEMORY GAME


// PIN SETUP

// LED pins
int redLED = 12;
int yellowLED = 9;
int greenLED = 6;
int blueLED = 3;

// Button pins
int redButton = 11;
int yellowButton = 8;
int greenButton = 5;
int blueButton = 2;


// GAME VARIABLES
int sequence[10];   // stores up to 10 steps
int level = 0;      // current level


// ==============================
// SETUP 
// ==============================
void setup() {

  // Set LED pins as OUTPUT
  pinMode(redLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
  pinMode(greenLED, OUTPUT);
  pinMode(blueLED, OUTPUT);

  // Set button pins as INPUT (with internal pull-up)
  pinMode(redButton, INPUT_PULLUP);
  pinMode(yellowButton, INPUT_PULLUP);
  pinMode(greenButton, INPUT_PULLUP);
  pinMode(blueButton, INPUT_PULLUP);

  // Start random generator
  randomSeed(analogRead(0));


  // ==============================
  // STARTUP LED TEST
  // ==============================

  // Turn on each LED one by one
  digitalWrite(redLED, HIGH);
  delay(300);
  digitalWrite(redLED, LOW);

  digitalWrite(yellowLED, HIGH);
  delay(300);
  digitalWrite(yellowLED, LOW);

  digitalWrite(greenLED, HIGH);
  delay(300);
  digitalWrite(greenLED, LOW);

  digitalWrite(blueLED, HIGH);
  delay(300);
  digitalWrite(blueLED, LOW);

  delay(500); // small pause before game starts
}


// ==============================
// MAIN LOOP 
// ==============================
void loop() {

  addStep();        // add new random color
  showSequence();   // show LED sequence

  bool correct = checkPlayer(); // check user input

  if (correct == false) {
    gameOver();     // if wrong → game over
    resetGame();    // restart
  }

  delay(1000);
}


// ==============================
// FUNCTIONS
// ==============================


// Add a new random step
void addStep() {
  sequence[level] = random(0, 4);
  level++;
}


// Show the sequence using LEDs
void showSequence() {

  for (int i = 0; i < level; i++) {

    turnOnLED(sequence[i]);
    delay(500);

    turnOffAll();
    delay(250);
  }
}


// Turn on the correct LED
void turnOnLED(int number) {

  if (number == 0) digitalWrite(redLED, HIGH);
  if (number == 1) digitalWrite(yellowLED, HIGH);
  if (number == 2) digitalWrite(greenLED, HIGH);
  if (number == 3) digitalWrite(blueLED, HIGH);
}


// Turn off all LEDs
void turnOffAll() {

  digitalWrite(redLED, LOW);
  digitalWrite(yellowLED, LOW);
  digitalWrite(greenLED, LOW);
  digitalWrite(blueLED, LOW);
}


// Check player input
bool checkPlayer() {

  for (int i = 0; i < level; i++) {

    int buttonPressed = waitForButton();

    // Show feedback
    turnOnLED(buttonPressed);
    delay(300);
    turnOffAll();

    // Check correctness
    if (buttonPressed != sequence[i]) {
      return false;
    }
  }

  return true;
}


// Wait for button press
int waitForButton() {

  while (true) {

    if (digitalRead(redButton) == LOW) {
      delay(200); // debounce
      return 0;
    }

    if (digitalRead(yellowButton) == LOW) {
      delay(200);
      return 1;
    }

    if (digitalRead(greenButton) == LOW) {
      delay(200);
      return 2;
    }

    if (digitalRead(blueButton) == LOW) {
      delay(200);
      return 3;
    }
  }
}


// Game over animation
void gameOver() {

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

    digitalWrite(redLED, HIGH);
    digitalWrite(yellowLED, HIGH);
    digitalWrite(greenLED, HIGH);
    digitalWrite(blueLED, HIGH);

    delay(300);

    turnOffAll();

    delay(300);
  }
}


// Reset game
void resetGame() {
  level = 0;
}

Difficulties

One of the main difficulties I encountered was related to the physical design of the circuit, especially the buttons. It was challenging to make the buttons clearly visible and easy to press during gameplay. At times, the wires made the setup look cluttered and slightly uncomfortable to use. To improve this, I adjusted the layout of the breadboard and repositioned it to the left side instead of the right, which made the buttons more accessible. However, I still believe the design could be improved. A possible solution would be to use shorter wires, since the ones included in the kit are relatively long and make the circuit less organized.

Thing that I’m Proud Of

One aspect of the project that I am particularly proud of is the feedback system when the player loses. I programmed all the LEDs to blink simultaneously several times, creating a clear and satisfying visual indication that the game is over. This small detail enhances the user experience and makes the game feel more complete and interactive.

Reflection Overall

Overall, I found this project very enjoyable and rewarding. It allowed me to combine creativity with technical skills and to better understand how hardware and software interact. I especially liked how I could take a simple idea and gradually build it into a functional game. If I were to improve this project in the future, I would like to add sound effects, such as tones that play when each LED lights up, to make the experience more immersive. Although I have not yet implemented this feature, it is something I would like to explore next. This project helped me gain confidence in working with Arduino and problem-solving in both coding and physical design.

PHOTO OF PHYSICAL CIRCUIT

PHOTO OF SCHEMATIC

Reading Reflections

Making Interactive Art

Reading this text me rethink what art even is, especially interactive art, because I feel like I’ve always thought of art as something where the artist is trying to say something very specific, and the audience is supposed to understand that meaning. But here it’s kind of the opposite. It’s saying that if you control too much, if you explain too much, you’re actually limiting the experience. And I find that really interesting but also a bit uncomfortable, because it means you’re giving up control over your own work. Like, you create something, but then people might completely misunderstand it, or interact with it in a way you didn’t expect, and that’s supposed to be part of it. I think what stood out to me the most is this idea that the artwork is not the final product, but more like the beginning of a conversation, and the audience kind of finishes it. At the same time, I feel a bit conflicted, because I wonder if that means the artist’s intention doesn’t matter as much anymore, or if it just becomes too vague. But I do like the idea that interaction is more real when it’s not forced, when people figure things out on their own. It makes the experience more personal instead of just following instructions. So I think the main thing I take from this is that good interactive art is not about telling people what to think, but about creating a space where they can think for themselves, even if that means losing some control over what your work becomes.

Physical Computing’s Greatest Hits (and misses)

This article made me realize something that I hadn’t really thought about before, which is how much creativity is not about doing something completely new, but about how you reinterpret things that already exist. At first, I kind of agreed with that instinct of “if it’s already been done, it’s not original,” but reading this made me see that that idea is actually very limiting. The author shows how the same types of projects keep coming back, like gloves or sensors or interactive spaces, but what changes is how people give meaning to them. And I think that’s the part that stood out to me the most, because it’s not really about the technology itself, it’s about the interaction and what it makes people feel or do. At the same time, I also feel a bit conflicted, because some of these projects sound very repetitive or even a bit shallow, like things that look cool but don’t really have depth. So it made me question where the line is between something that is genuinely creative and something that is just visually interesting. I think overall the article is kind of saying that originality doesn’t come from the idea itself, but from the intention behind it, but I’m not sure if I fully agree, because I still feel like at some point things can become too repetitive. But I do like the idea that you shouldn’t immediately discard something just because it’s been done before, because that mindset probably stops a lot of good ideas before they even start.

 

Week 9 – Reading Response Megan

Norman,“Emotion & Design: Attractive things work better”

In my opinion, the most interesting takeaway from the reading is when it talks about this “gut feeling” we have, like a sixth sense that immediately tells us what we want or do not want to deal with just based on how something looks. It is like a small light turns on in your brain from the beginning, and that already affects how willing you are to interact with something and how you are going to deal with it.

I also found the connection to the debugging video we saw earlier in class really clear. We talked about how when you are stressed or anxious, your thinking becomes very narrow and you get stuck. The reading explains this as “tunnel vision,” where you focus too much on one thing and cannot see other solutions. That might be useful in a survival situation, but for debugging or any kind of creative problem solving, it is the worst mindset to be in. It makes a lot of sense now why working while stressed feels so unproductive, because your brain is literally limiting your ability to think creatively.

Again, what stood out to me the most, especially because I am interested in design, is the idea that emotions happen before conscious thought. Because of course your brain is already reacting to a design before you even process it. I used to think usability and aesthetics were kind of separate, like one is how it works and the other is how it looks, but now I see that they are actually connected. This quote: If something makes you feel good, you are more likely to overlook small issues and just have a better experience overall. Is actually crazy to me, because I think this applies to many thinks, like for example the apple ecosystem. because of the aesthetics of it and how smoothly it runs even when it it loading, you could be waiting more time for something to download in a mac than on a windows laptop and you would feel like the mac is working better just for the aesthetics of it.

In future projects, I want to use design to influence how the user feels from the beginning. Since as the reading shows us, if I can make someone feel calm and comfortable, they will probably think more clearly, be more flexible, and have a much smoother experience using what I create.

Her Code Got Humans on the Moon

Reading about Margaret Hamilton really blew my mind. It is honestly incredible that a woman, and a working mother at that, was the one who made the moon landing possible during a time when women were not even encouraged to go into technical fields. What is even crazier to me is that she was the only one thinking about a backup plan or worst case scenarios. NASA literally told her that error checking code was not necessary because “astronauts were trained to be perfect.” To me, that is such a wild assumption because humans make mistakes all the time, but back then they just ignored that reality.

It actually makes so much sense to me that a mother would think this way. She saw her daughter, Lauren, accidentally crash a simulator by pressing a button that was not supposed to be used during flight, and she immediately understood that users will eventually do something they are not supposed to do. She used that to try to protect the astronauts from themselves, and it is honestly lucky she did. An astronaut on Apollo 8 made that exact same mistake, and Hamilton’s team had to spend nine hours figuring out how to fix it and get them home safely.

This whole idea of debugging and making systems intuitive for the user basically started with her. Before she came along, software was not even included in the official Apollo budget or schedule. She had to fight for her work to be taken seriously, even creating the term “software engineering” so it would be respected like other fields. It is insane to think that this one woman, working in what she called the “Wild West” of coding, helped create an entire field that now impacts the whole world. She did not just help us get to the moon, she helped shape the foundation of the modern digital world.

Week 7 – Midterm Project! – Megan Del Villar

“Salteñada”

Concept

For this project I wanted to create something that actually represents me. I thought about my culture and also something I really enjoy which is cooking. So I asked myself what are my favorite Bolivian dishes and which one feels the most iconic. For me that is the salteña. It is a type of empanada but very unique because it is juicy and has a mix of different ingredients inside.

From that idea I decided to turn it into a game where people can learn how to make salteñas. I was also inspired by a game I used to play when I was younger called Papa’s Pizzeria, where you receive orders and have to complete them correctly. I liked that structure a lot so I adapted it into my own concept but based on Bolivian food.

The main goal of the game is to complete four salteñas correctly by following the recipes shown in the tickets. Each time you play the orders are random so the experience changes every time.

Implementation

I started by thinking about the aesthetic of the game. I wanted it to match the same style I have been using in my other works which is clean, flat, and stylized with shadows made using shapes instead of realistic textures. That is why I built everything using p5.js shapes instead of drawing or importing detailed images.

I created different classes like Ingredient, Dough, and Order so I could organize the logic better. This helped me control how things move, how they are displayed, and how the player interacts with them.

One of the hardest parts at the beginning was figuring out how to drag the ingredients and the dough. I wanted it to feel smooth but also controlled. Designing the ingredients was also challenging because I wanted them to be recognizable but still look like part of a stylized game.

Then I worked on the main mechanics of the game. I created a system where orders are randomly generated so every game is different. I also built a system that stores the ingredients inside each dough and then checks if they match the recipe. This is a simplified version of how salteñas are actually made but it still represents the main ingredients.

For the visual part I used an image of an aguayo as the background and applied a pointillism effect to make it look more organic and consistent with the rest of the aesthetic. I also added a custom font that matches the vibe of the game and background music to make the experience more immersive.

I did not rely too much on external sources. Most of what I used was the p5.js library for things like collision detection and interaction, class notes, and inspiration from Papa’s Pizzeria and Bolivian cooking. I also spent a lot of time experimenting to make everything look visually consistent.

Another important source was actually my younger brother. I made him play the game when it was almost finished to see how a real user would interact with it. This helped me realize several issues like missing instructions or unclear elements. Because of that I ended up spending more time improving the tutorial than the game itself, since I wanted the player to clearly understand what to do and feel rewarded when they succeed.

I also used AI tools like ChatGPT and Claude mainly for debugging (a big part of this project was honestly debugging haha) and understanding certain technical problems and knowing what function, variable or tool would be useful for what I wanted to do.

Code that I am proud of

The part of the code I am most proud of is the recipe validation system. I had to create a way to store all the ingredients that the player places inside each dough and then count them correctly. After that I needed to compare those counts with the order requirements.

This was challenging because it connects multiple parts of the game. The interaction of dragging ingredients, storing them inside the dough, closing the salteña, and finally checking if everything is correct. Making all of that work together correctly took me a lot of time to understand and debug.

function checkRecipe(dough, order){
  let counts = {};

  for(let ing of dough.ingredients){
    counts[ing] = (counts[ing] || 0) + 1;
  }

I am also proud of the full game logic that decides if the player wins or loses. It checks if all salteñas are closed, if they have the correct ingredients, and also handles the timer and the Done button.

for(let d of doughBalls){
  if(!d.closed){
    loseReason = "Some salteñas are not closed";
    endGame(false);
    return;
  }

Finally, one that seemed so simple but it took soooo much time out from me was this multi – clicking to close the salteña

if(now - d.lastClickTime < 400){
  d.clickCount++;
}

Reflection

I really enjoyed making this project and I think I challenged myself a lot. There are still things I would improve. For example there was a moment where I did not like the dragging interaction and I wanted to change it to a pick and release system. However that was very difficult to implement and I was already deep into the project and felt like I was going down a rabbit hole while debugging that, so I decided to keep the drag system to avoid breaking everything.

It bothered me because when I played the game myself I noticed that dragging a lot can get tiring, especially because you are trying to finish quickly. So I think a different interaction system would make it more user friendly.

I also would have liked to add sound effects and more steps to the cooking process. Right now when you close the salteña it is assumed that it already has the juice and is baked. Ideally I would add another stage where the player adds the juice and then bakes the salteña to make the experience more complete.

Another challenge I faced was organization. Because of time changes and breaks in between working on the project, my coding process was not as consistent as before. Sometimes I would go a long time without looking at the code and then come back and work for many hours. That made the code feel a bit disorganized and sometimes I would get lost.

I also struggled at the beginning with making the design responsive to different screen sizes. I could not rely on fixed dimensions like before, so I had to adapt everything to the window size. That was difficult at first but I eventually got used to it.

Overall I am very proud of this project. Even though there are things I would improve, I feel like it represents me, my culture, and my interests. It is also a game that I would actually enjoy playing and I think my friends and family would too.

Week 4 – Reading Reflection Megan

Something that genuinely drives me crazy (and it’s not in the reading) are the old washing machines that were in dorm laundry rooms. Not even because they’re complicated, but because you literally cannot tell what they are doing. You press start, sometimes it locks, sometimes it doesn’t, sometimes it just stops and you don’t know if it’s broken or thinking. I’ve stood there many times not knowing if I should open it, wait, or restart it. And the worst part is everyone reacts differently, some people keep pressing buttons, some unplug it, some hit it (honestly valid).

But after reading Norman I realized the problem is not that the machine is complicated but it’s that it has no feedback and no signifiers. The interface doesn’t communicate what state the machine is in. Norman explains that good design should make the possible actions discoverable and understandable. But here you don’t know if is it washing? paused? locked error?

The machine technically works, but the interaction fails. The simplest improvement would actually not be adding more buttons but adding better communication. A small progress bar, a timer that updates, or even a message like “Door will unlock in 30 seconds” would fix almost all the confusion. Norman talks about how users shouldn’t need instructions for simple objects, and when they do it means the design is wrong  . A washing machine should not require guessing or trial and error.

This connects a lot to interactive media. When someone opens a sketch or website, they don’t read instructions first. They try to understand it immediately. So discoverability becomes really important. Norman calls this human-centered design, which is designing based on how people actually behave, not how we wish they behaved  .

I realized my own project actually needed these ideas too. For example, at first my visualization was confusing because nothing indicated when the music would start, how to make it stop, and even at the beginning it still takes a bit to load and you don’t know why (even though its because the image and sound is uploading). After thinking about Norman’s principles, the play button became a signifier: it communicates the action you should take. Also the movement of the dots works as feedback. When the music gets louder and the dots expand, the system is telling you your action (playing the song) had an effect.

In interactive media especially, feedback is essential, for example, as Norman explains, users keep pressing elevator buttons when they don’t receive feedback. That’s literally what happens in digital projects too, if nothing responds, users assume it’s broken. So animations, hover effects, and sound reactions are not just decoration, they are communication.

Another idea from the reading is conceptual models. People build a mental explanation of how something works. If the system behaves differently from what they expect, they get confused. My sketch actually depends on this a little I would say: people assume music causes motion, so when the dots pulse with sound, it feels intuitive. They don’t need instructions.

Overall, the reading made me realize interactive art still has to be usable. Even if something is artistic, the viewer should understand how to interact with it. Good design is not just aesthetics, it is communication between the system and the user.

Week 4 – Data Visualization Assignment Megan

“YOaMoNUEvAYoL”

“The only thing more powerful than hate is love.”

“Together, we are America.”

– Benito Antonio Martínez Ocasio 2026

Concept

The concept of this project was to create something connected to the recent social and political conversations about Latin American communities, especially in the United States. Recently I watched the Bad Bunny halftime show that became extremely popular, and as a Latina it honestly felt like a huge moment. Seeing someone singing in Spanish in front of all of the USA, especially considering the controversies around immigration and the fact that many immigrants in the USA are Latino, made me want to base my project around that idea.

Therefore, for the project I chose the song “NUEVAYoL” by Bad Bunny, which was part of the performance and also part of the album that just won two Grammys. The song talks about New York and mixes the American image of the city with a Latin cultural perspective of it. Because of that, I used an image of the Empire State Building that felt vibrant and alive. The image has four dominant colors: orange, light blue, white, and gray. Then I found official 2023 data about Hispanic/Latino population in the United States organized by state. I grouped the states into three main regions: South, West, and Northeast.

Each main color in the image (blue, orange and white) represents one of those regional population groups, and so the amount each color appears is controlled by population data.

The idea is that the skyline is not just a picture anymore. The city lights are metaphorically “powered” by the people who live there. If a region has a larger Hispanic population, that color appears more often in the picture. The music adds movement because when the song gets louder, the dots grow and become brighter, so it feels more like a celebration instead of a static visualization.

To see (and listen) it in action just click the little  ⏯  button on the lower left corner!

Click the play ⏯ button!

Process

Originally I tried to make a migration tree showing people moving from Latin America to the U.S. But when I started doing it, technically it was data visualization, but visually I didn’t like it. It looked more like a diagram than something expressive.

After watching The Coding Train videos about sound visualization, I followed the tutorial and experimented with audio-reactive graphics (This tutorial is also why I kept the little toggle button in the corner to play and pause the audio). I then found this Bad Bunny song and immediately thought about using the Empire State Building because the song is about New York. However, I couldn’t use the song because of issues with the UAE library store so I had to extract the audio from the YouTube video of that song and then cut the mp3 so that the intro of the video that wasn’t part of the song itself. I learned how to do this and did it with my terminal.

First I created a sound visualizer using p5.js amplitude analysis (p5.Amplitude()), which gives a number between 0 and 1 representing how loud the music is at each moment. I mapped that value to the size of the dots so louder music makes the building pulse.

Then I converted the image into a pointillism drawing (i based myself of off these p5.js examples 1, 2). Instead of drawing every pixel, the code samples every 5 pixels in both directions. This reduces detail but still makes visible dots.

After that I connected the dataset. I loaded a CSV file using loadTable() and extracted the column HispanicTotal_2023. I summed populations into regional totals (West, South, Northeast). Instead of placing states spatially, I mapped data into a visual variable: color frequency. So, higher population = higher probability a dot of that color appears.

Media and tools used:

  • p5.js

  • The Coding Train tutorials

  • U.S. Census 2023 dataset

  • audio extracted and trimmed from YouTube

  • ChatGPT used to understand pixel arrays and debugging

One of the hardest parts was understanding how images are stored in p5.js. At first the dots appeared randomly because I didn’t understand that each pixel uses 4 values (RGBA). Once I learned how to correctly calculate the pixel index, the image reconstruction finally worked.

Code that I’m proud of

The part of the code I am most proud of is the section where the program reads the color of each pixel from the image and connects it to the demographic dataset. Instead of drawing the Empire State Building manually, the sketch actually reconstructs it from the photograph itself. The program loads the image and then scans across it every few pixels rather than reading every single one. For each sampled position it calculates where that pixel exists inside the image array, extracts the RGB color values, and then classifies the pixel as sky, window light, highlight, or building structure. After that, the demographic data determines whether the dot is drawn or not, so population directly controls how frequently certain colors appear. Because of this, the building is a data-driven reconstruction made of sampled points. The line that makes this possible is the calculation that converts the (x, y) position on the image into the correct position in the pixel array, which allows the code to access the exact color information for that location.

Another reason this is the part of the code I am most proud of is because I tried many different ways of displaying the data before arriving at this solution. I experimented with horizontal assignments, bar-style representations, mapping individual states directly, and even changing the size of the dots to represent population, but none of those approaches worked visually or conceptually. They either made the Empire State Building unrecognizable or the data unclear.

//sampling the image, skiping every 5 px to make dots
  for (let x = 0; x < img.width; x += 5) {
    for (let y = 0; y < img.height; y += 5) {

      // locate pixel inside the 1D pixel array to extract its color
      let index = (x + y * img.width) * 4;

      // RGB values of that pixel
      let r = img.pixels[index];
      let g = img.pixels[index + 1];
      let b = img.pixels[index + 2];

      // brightness decides how visible the dot should be
      let brightness = (r + g + b) / 3;

      // darker parts = bigger dots for the building silhouette to appear
      let dotsize = map(brightness, 0, 255, 2, 0);

      // music reaction: louder song = dots expand
      dotsize = dotsize + vol * 20;

      // classify the pixel color
let regionType;

if (r > 200 && g > 200 && b > 200){
  regionType = "white";      // bright highlights
}
else if (r > 200 && g > 120 && b < 100){
  regionType = "orange";     // other buildings
}
else if (b > r && b > g){
  regionType = "blue";       // background
}
else{
  regionType = "structure";  // gray building
}

// population controls how often each color appears
let maxRegion = max(westPopu, southPopu, eastPopu);
let allow = 0;

if(regionType === "orange"){        // WEST
  allow = map(westPopu, 0, maxRegion, 0.1, 1);
}
else if(regionType === "white"){    // SOUTH
  allow = map(southPopu, 0, maxRegion, 0.1, 1);
}
else if(regionType === "blue"){     // EAST
  allow = map(eastPopu, 0, maxRegion, 0.1, 1);
}
else{
  allow = 0.15; // so that the building structure always faints
}

noStroke();
fill(r, g, b);

if(random() < allow){
  circle(x, y, dotsize);
}
}

Overall Reflection

Overall I’m really happy with the final result. I like thaat it balances data and aesthetics. It is not a traditional chart, but it still encodes real demographic information so you don’t read numbers directly, but still you perceive distribution through color presence.

If I continue this project, I would add multiple years of census data and animate the skyline over time so you could see growth instead of a single snapshot. Another improvement would be adding clearer interaction (for example hovering to reveal which region each color corresponds to). Although, a limitation is that the visualization depends on the colors of this specific image so if the image changes, the mapping must also change.

Week 3 Reading Reflection – Megan

After reading this chapter I realized that a strongly interactive system is really like having a good conversation. Both sides have to listen think and speak well for it to feel alive. If one side fails it just becomes boring or frustrating. So for a system to be truly interactive it has to respond to the user in a way that feels meaningful not just random or automatic. I liked how Crawford explains that interaction is not the same as reaction like with a fridge or a movie you can only watch but you don’t actually talk to it. That made me think about my p5 sketches because sometimes I make things move or change when the mouse touches them but it feels kind of one-sided. I realized that to make them more interactive I could have the objects respond in different ways depending on how you interact with them like changing speed direction color or even start a little animation that is unique for each action. I also liked thinking about giving each object its own “voice” like the dice in my project could react differently to the same input so it feels more alive and less predictable. I want to experiment more with letting the user affect not just the movement but the behavior and appearance over time so it feels like the sketch is listening and thinking a little bit before it reacts. Overall reading this made me want to make my sketches feel more like a real conversation between me and the code rather than just me controlling it.

Week 3 -Object Oriented Programming Megan

Concept:

The concept of this project comes from cacho, a traditional Bolivian dice game. The game is played by putting five dice inside a small leather cup, and you try to roll combinations like a poker hand, for example House, Full, etc. This game caught my attention because all the dice are identical, so I thought I could use them as objects for this project in object-oriented programming.

click it!

Process:

For the process, I first started with a photo of the cubilete, the cup, and the dice inside to be able to draw it in p5.js. I used my iPad to make a sketch highlighting the geometric shapes I needed and how I had to rotate them at different angles. At first, I used translate to set the origin at zero, zero, but later I switched to WEBGL because the dice are 3D geometric shapes.

For the rotations, I set the canvas to use Degrees so I could control exactly how much each shape rotated. That is how I made the base drawing. Then came the dice, which was the most difficult part. I started with 2D using rect, and I wanted them to rotate, so I created a move function inside the Dice class and used rotate so that every time a dice completes a full rotation, it moves forward.

Then I realized 2D did not really give the impression of a real dice, so I switched to 3D and used box from the p5.js 3D examples. For some reason, the box was deforming, its sides would stretch or cut off, so I had to apply rectMode(CENTER), which I was already using for 2D. After trying several methods, this was the only one that kept the cubes from deforming, probably because a box is made of rectangles, and if they are centered, they do not distort.

Next, I wanted to put numbers on the dice, but that turned out to be very complicated. When I tried, the dice faces blinked and did not display properly. The solution I found was to color the different faces with various shades of white and gray to make them look more realistic. I also made sure each dice had a random starting position so they did not all start at the same place.

Another very important part of the process was setting boundaries for the dice. At first, when I got a square to move, it went off the canvas, so I looked at examples from p5.js on how to use the command constrain on balls and adapted that idea. I set random limits so each dice would stop at different places on the table, giving the scene more realism like when you through dice. A key detail was making sure the dice stop rotating once they reach their limits because when I first tried it the dices would keep going on circles once they stopped moving forward.

Full code:

let dice1;
let dice2;
let dice3;
let dice4;
let dice5;

function setup() {
  createCanvas(600, 600, WEBGL);
  colorMode(HSB);
  //Random starting points
  dice1 = new Dice(random(-50, 30), random(-200, 30));
  dice2 = new Dice(random(-50, 30), random(-200, 30));
  dice3 = new Dice(random(-50, 30), random(-200, 30));
  dice4 = new Dice(random(-50, 30), random(-200, 30));
  dice5 = new Dice(random(-50, 30), random(-200, 30));
}

function draw() {
  background("#deb887");
  angleMode(DEGREES);
  
//Table
  push();
  rotate(48);
  fill("black");
  rect(-320, -250, 800, 800);
  pop();
  
  push();
  rotate(20);
  fill("black");
  rect(-210, -310, 500, 200);
  pop();
  
// Cubilete
   //Outside
  fill(30, 85, 30);
  noStroke();
  quad(-193,-286, -250, -130, -100, 40, 40, -230);
  push();
  rotate(14);
  fill(30, 85, 30);
  ellipse(-253, -145, 102, 172);
  pop();
  //Inside
  push();
  rotate(19);
  fill(120, 100, 15);
  stroke(30, 85, 38);
  strokeWeight(15);
  ellipse(-50, -77, 220, 292);
  pop();
  
  //Dice
  dice1.move()
  dice1.show()
  dice2.move()
  dice2.show()
  dice3.move()
  dice3.show()
  dice4.move()
  dice4.show()
  dice5.move()
  dice5.show()
}

// Function to restart dice when clicking
function mousePressed(){
  dice1 = new Dice(random(-50, 30), random(-200, 30));
  dice2 = new Dice(random(-50, 30), random(-200, 30));
  dice3 = new Dice(random(-50, 30), random(-200, 30));
  dice4 = new Dice(random(-50, 30), random(-200, 30));
  dice5 = new Dice(random(-50, 30), random(-200, 30));
}
class Dice{
  constructor(_x, _y){
    this.x= _x;
    this.y= _y;
    
    //So that dice can rotate
    this.angle=0
    
    //Random limit to make dice stop going forward at a certain place in the table 
    this.maxX = random(-10, 260);
    this.maxY = random(-10, 260);
    
    this.colors=["#FFFFFF", "#808080", "#D3D3D3", "#FFFDD0", "#F5F5F5", "#FAEBD7"]
    
    //To stop dice rotation
    this.stopped = false;
    
  }
  move(){
    //To make dice stop rotating when limit reached
    if (!this.stopped){
    
      //Movement forward
    this.x += 3
    this.y += 3
    
    //Limits for dice to not go past the table
    this.x = constrain(this.x, -10, this.maxX);
    this.y = constrain(this.y, -50, this.maxY);

    //If limit reached, stop rotation
    if (this.x >= this.maxX && this.y >= this.maxY) {
        this.stopped = true;
      }
    
    
    //To make them roll
    this.angle += 15; 
    this.angle %= 360;
     
    }
  }
  
 show(){
  push();
  translate(this.x, this.y);
  rotate(this.angle);
  rectMode(CENTER);

  noFill(); // Base box color
  box(65);   // 3D dice

  // Color each face with planes 
  let s = 65/2; // Half the size of the dice, used to position the planes at each face

  // Front face
  push();
  translate(0, 0, s); 
  fill("#FFFFFF");         
  plane(65, 65);       
  pop();

  // Back face
  push();
  translate(0, 0, -s); 
  rotateY(180);         
  fill("#808080");        
  plane(65, 65);        
  pop();

  // Right face
  push();
  translate(s, 0, 0);  
  rotateY(90);          
  fill("#D3D3D3");         
  plane(65, 65);
  pop();

  // Left face
  push();
  translate(-s, 0, 0); 
  rotateY(-90);         
  fill("#FFFDD0");       
  plane(65, 65);
  pop();

  // Top face
  push();
  translate(0, -s, 0); 
  rotateX(90);          
  fill("#F5F5F5");       
  plane(65, 65);
  pop();

  // Bottom face
  push();
  translate(0, s, 0);  
  rotateX(-90);         
  fill("#FAEBD7");       
  plane(65, 65);
  pop();

  pop(); 
  }
}

Code I am proud of:

I am especially proud of the code I wrote to set the boundaries for the dice. As I mentioned, it was really challenging to figure out how to make the dice stop moving and rotating once they reached their limit. Also, making sure the dice did not deform while rolling was tricky, and using rectMode(CENTER) solved that problem perfectly.

//Random limit to make dice stop going forward at a certain place in the table 
    this.maxX = random(-10, 260);
    this.maxY = random(-10, 260);
    
    
    //To stop dice rotation
    this.stopped = false;
    
  }
  move(){
    //To make dice stop rotating when limit reached
    if (!this.stopped){
    
      //Movement forward
    this.x += 3
    this.y += 3
    
    //Limits for dice to not go past the table
    this.x = constrain(this.x, -10, this.maxX);
    this.y = constrain(this.y, -50, this.maxY);

    //If limit reached, stop rotation
    if (this.x >= this.maxX && this.y >= this.maxY) {
        this.stopped = true;
      }
show(){
  push();
  translate(this.x, this.y);
  rotate(this.angle);
  rectMode(CENTER);

  noFill(); // Base box color
  box(65);   // 3D dice

Overall reflection:

The hardest part was definitely trying to put numbers on the dice, which I did not fully achieve. Maybe with more research on 3D objects, I could eventually make it exactly how I intended. But I really liked the final result, especially because it looks a lot like the cacho I play in real life. I also enjoyed working with objects because it made it easy to create multiple dice without repeating code, giving each one different positions and starting points that I could edit freely.

Overall, this project taught me a lot about working with 3D shapes and object-oriented programming. I learned that even small details, like the starting position, rotation, and boundaries, make a huge difference in making the animation feel realistic. I am happy with how I managed to combine my reference from real-life cacho, geometric thinking, and programming, and I feel more confident creating multiple interactive objects in p5.js for future projects.

Week 2 – Creative Reading Megan

Casey Reas Eyeo talk on chance operations

How are you planning to incorporate random elements into your work? Where do you feel is the optimum balance between total randomness and complete control?

Before answering this questions, I wanted to implement by myself the concepts the video was talking about. Randomness. One quote by Casey Reas really stayed with me: “change it by a little so that movement creates chaos in an ordered way.” And I think that perfectly represents what I was trying to do in my work. The things I changed to create this element of randomness were data, small pieces of data that might seem insignificant at first, but machines are built based on that, so even the smallest thousandth can make a difference.

This brings me to another quote from the video, about Dadaism: “Dada wished to replace the logical nonsense of the men of today with an illogical nonsense.” To what point is something considered logical? Computers are supposed to be based on pure logic. And yet, artists find ways to turn that logic into illogical sense. And yet, it still has meaning. It’s like deconstructing the logic embedded in the machine with the purpose of illogically creating something that has meaning behind it. Or the other way around, creating something without meaning by using the logic of the computer. Either way, I feel this can be applied to the artworks shown in the video.

A quote by Gerhard Richter captures this idea very well: “Above all, it’s never a blind chance; it’s a chance that is always planned but also always surprising.” These artists construct from chance as a base. It’s about bringing in disorder that has been curated with intention, in a way that even surprises the artist themselves. I think that finding this balance between total randomness and complete control is about using logic and repetition, patterns and algorithms that allow you to repeat a process, while the outcome is completely different, but the essence of it remains present.

Something that really caught my attention in the video was the idea of the million random digitized values and the 1,000 normal deviates. It honestly amazed me to think about the power, the expectation, and the importance that randomness has in our lives when we understand that art imitates or simulates the real world, and the real world is chaotic and not curated by anyone, but rather filled with randomness. Without a doubt, this video and this work opened my eyes and helped me understand even better the importance of chaos within order, and order within chaos.

Week 2 – Generative Art Megan

Concept

“The whole universe is based on rhythms. Everything happens in circles, in spirals.” — John Hartford

The idea of my artwork was that I wanted to create a spiral using the colors of the flower often called the “national Bolivian” flower, the kantuta. This flower is one of the most amazing ones, not only because of its vibrant colors, but also because it grows up to 3,800 meters above sea level, in its native land in the Andes. This flower has a lot of meaning for me, starting with its colors red, yellow, and green, which are those of the Bolivian flag, and also because it represents the nature and resilience of my home country.

Speaking of nature, I wanted to represent this flower through some kind of shape. Spirals are a shape that is found everywhere in nature and, for me at least, they are mesmerizing to look at and to understand. Inspired by the video we watched on randomness in digital art, I wanted to find an “organic” yet “random” way of showcasing the kantuta. The spiral has movement and flow without breaking its structure or bringing chaos. Moreover, it has such a unique presence, it almost calls the viewer to follow its path, and it feels like you’re watching something alive.

That’s why, and as I promised myself in the last exercise, I wanted to challenge myself, so I looked up many tutorials on how to create spirals in p5.js.

Run it and Click it!

Process

Most of my learning for this project came from these video tutorials on YouTube by Strive Math. First, I had to learn about transformations and translations in p5.js. It has to do with the coordinates in the canvas you’re creating. So, when you translate, you move the entire coordinate plane up, down, left, or right. And when you transform, you’re rotating the entire coordinate plane at an angle that you choose (you must select if the angle will be measured in degrees or radians first). It rotates clockwise if the number is positive and counterclockwise if it’s negative.

With transformations, you rotate the axis around the center point you chose when you did the translation. So, with this, I first learned how to draw a simple circle using these concepts. For example, if I translate the origin so it is right in the middle of the canvas, and I keep making this coordinate plane rotate clockwise while drawing a dot somewhere that is not the origin, the dot will keep moving with the coordinate plane and trace a circle when the coordinate plane completes a full 360° rotation.

This is how the code for that looks (this is no longer in code as such since it was just to practice and understand how it works):

function setup() {
  createCanvas(600, 600);
  angleMode(DEGREES)
}

let angle = 0

function draw() {
  translate(width/2, height/2)
  rotate(angle)
  angle++
  point(30,0)
}

The next step, was to think how this could turn into a spiral. Since the circle shape that I made is actually just a point following a path that is determined by the radius of the circle, if I increase the radius of the circle, and as the point moves more the radius also increases more, this will create a path of a spiral. Therefore now the code will look like this:

let angle = 0
let radius = 0

function draw() {
  translate(width/2, height/2)
  rotate(angle)
  angle+= 31
  radius+= 0.4
  strokeWeight(6)
  point(radius,0)

Now I can control the way the spiral looks by playing with the amount of degrees the angle of the coordinate plane is going to change every time and how wide will the radius of the circle increase be. A small issue with this was that the frame rate of how fast or how slow the points would appear will sometimes be too slow and I wanted to change that. Therefore, just like in the tutorial that i watched, I inserted a for loop to control the frame rate of everything, and for it to not change and save the sate of the canvas I used the ‘push’ and ‘pop’ commands so that the origin always stays in the center of the canvas and doesn’t move every time the for loop repeats.

As I said, I wanted to implement the concept of randomness, so I created random variables for the values of the angle and the radius to be able to make a different spiral every time you click on the screen. To make this happen, I added a mousePressed() function that resets the angle and radius to their initial values, generates new random values for the angle increment and radius increment, and clears the canvas:

function mousePressed() {
  angle = 0;               
  radius = 0;             
  angleValue= random(300, 3000); 
  radiusValue = random(0.009, 0.2);
  background("black");    
}

This way, every time the canvas is clicked, the spiral starts fresh with completely new random parameters, creating a unique pattern while keeping the interaction simple and intuitive. However, it took me a while to figure out this approach, because at first I tried using a boolean variable and a separate restart function in a more complicated way, and my code would get messy: sometimes the spiral wouldn’t appear, or new spirals would overlap with the old ones. Then I realized, why complicate things? I could just reset the main variables and redraw, and it worked perfectly.

Something I did very intentionally was set the limits of the random value of the angle to very big numbers and the numbers of the radius to very small decimals. I did this because I started playing around with those values and I realized the smaller the radius was the more dense the spiral looked and if the angle was a high number there was more chance of there being more ‘spiral lines’. I liked how this looked because it made the spiral look more like a piece of art. I also changed the background color to black so that the colors of the points would stand out more.

Code I am proud of

Then came the most important part: the color of the kantuta image. I uploaded the image to p5.js and made the spiral match the colors of the pixels by randomly selecting a pixel from the image and using its color for each point on the spiral.

let ix = floor(random(img.width))   
    let iy = floor(random(img.height))  
    let c = img.get(ix, iy)             
    stroke(c)

I’m really proud of this code because it wasn’t easy to get it right at first. I had to change the image I was using because the first one had too much black, which blended with the background and made the spiral almost invisible, and it also took too long to load. Then I realized that I needed to extract the colors pixel by pixel from the image, and I did this inspired by the p5.js example of pointillism, where each point takes the color of a random pixel from the image. This finally permited me to have a spiral that not only looked colorful and vibrant, but also represents the kantuta in a way that felt alive and organic, and I really liked it.

Final Code

//Image variables
let img;

//Image upload
function preload() {
  img = loadImage("kantuta.jpg");
}

//==============
//Setup
//==============
function setup() {
  createCanvas(600, 600);
  background("black")
  angleMode(DEGREES);
  frameRate(80);

  angleValue= random(300, 3000)
  radiusValue = random(0.009, 0.2)

  img.loadPixels(); // allow us to access image pixels
}

//Spiral variables
let angle = 0
let radius = 0

let angleValue
let radiusValue

//===================
//Drawing the spiral
//===================

function draw() {
  //To control the frame rate
  for (let i= 0; i<80; i++){
    
  push()//save the state of our canvas
  
  translate(width/2, height/2);
  rotate(angle);
  angle+= angleValue;
  radius+= radiusValue;
  strokeWeight(4);
    
  //Pick a color from the image
    let ix = floor(random(img.width))   
    let iy = floor(random(img.height))  
    let c = img.get(ix, iy)             
    stroke(c)                          
    
   point(radius,0);
  
  pop()//come back to the old state before 'push'
  }
}

// ===================
// Replay spiral on click
// ===================
function mousePressed() {
  angle = 0;               
  radius = 0;             
  angleValue= random(300, 3000); 
  radiusValue = random(0.009, 0.2);
  background("black");    
}

General Reflection

Overall, I think this project taught me a lot about patience, experimentation, and problem-solving. I also realized how important it is to simplify my approach: sometimes trying too many complicated solutions only slows you down, and the best results come from understanding the core idea and working with it directly.

I’m proud of how the final spiral turned out, not just technically but also conceptually. I feel like it feels alive, vibrant, and connected to something meaningful, which reflects the beauty of the kantuta and the creative process behind it. This project was the hands-on reminder of the video we saw that taught me that coding can be as expressive as painting or drawing, and that combining randomness, structure, and careful choices can create something truly mesmerizing.