Week 8 : Reading Response

Reading about Margaret Hamilton’s story was incredibly inspiring—especially the way she navigated a male-dominated field with intelligence and persistence. What stood out to me most was how seriously she took her code, and how she fought to ensure software was treated as a critical part of the Apollo mission. I admired her foresight and the way she challenged the idea that software was somehow secondary to hardware or engineering. As someone learning to code, I often feel like software is invisible or taken for granted, so seeing Hamilton’s impact reinforced how powerful and essential it really is. Her story makes me feel like being detail-oriented, stubborn, and thoughtful in code can actually change history.

Norman’s piece made me reflect on how often I prioritize function over form—especially as someone who tinkers with circuits and code. But his argument that emotional design improves usability resonated with me deeply. I’ve definitely had moments where a sleek interface or an intuitively designed device made me feel more confident and willing to explore, even if I didn’t fully understand the technical side yet. It’s fascinating to think that our emotional response can override frustration or confusion. The idea that beauty encourages persistence really stuck with me—I now realize that good design isn’t just about solving a problem, but about shaping how people feel while solving it.

Week 8 – Creative switch

 

Link to demo :

https://drive.google.com/drive/folders/1VTiRrGRrAj3aiTELux77pBYvCo3-3btS?usp=drive_link

For this week’s unusual switch assignment, I wanted to create something active and game-like — something that felt more like play than a standard circuit. That’s how I ended up designing a target switch using a cardboard folder, aluminum foil, and a ball. Instead of pressing a button or stepping on a pedal, the switch is triggered when I successfully throw a ball at the target. The core of my design is a DIY target made by slightly opening a cardboard folder and placing aluminum foil inside each flap. These foil strips are wired to the Arduino, and act as the two sides of a switch. When the ball hits the folder, it causes the foil pieces to touch momentarily — closing the circuit and turning on an LED.

const int SwitchPin = 3;
const int LEDPin = 12;

void setup() {
  pinMode(SwitchPin, INPUT_PULLUP); 
  pinMode(LEDPin, OUTPUT);
}

void loop() {
  const int Input = digitalRead(SwitchPin);

  if (Input == LOW) {
    digitalWrite(LEDPin, HIGH); // LED ON when ball hits target
  } else {
    digitalWrite(LEDPin, LOW);  // LED OFF otherwise
  }
}

The biggest challenge was making sure the foil only touches when I want it to — in this case, only when the ball hits the folder. I had to tape the foil securely and position it so that the folder remained slightly open. If it’s too loose, the foil touches on its own; too tight, and the impact doesn’t close the circuit. This project gave me a better understanding of how a simple digital input can be adapted into a physical interaction, using only basic materials like cardboard and foil. I also gained more confidence working with pull-up resistors and reading pin states accurately.

Midterm Project

Concept

I’ve always been fascinated by spooky stories, yet wanted to create something more lighthearted than a typical horror game. That is how I ended up making a short, click-based project in which the player buys a haunted house at a bargain price and must purge it of unwanted guests—literally ghosts—to unlock its true potential. From the outset, I imagined a game with a touch of urgency: each wave of ghosts adds just enough pressure to keep your heart rate up, but not so much as to be punishing or relentlessly scary. The result is a game that blends frantic clicking with a fun, eerie atmosphere and a simple storyline that sets the stakes clearly: fail, and the ghosts overwhelm you; succeed, and the house is yours, free of all things that go bump in the night.

To cement that narrative, I designed three distinct levels, each with its own flavor of tension. Level 1’s stationary ghosts ease the player in, Level 2’s moving ghosts ramp up speed and require more hits, and Level 3 features a boss ghost who teleports unpredictably to keep the player on their toes. Across these levels, the fundamental goal never changes—click fast, or you risk running out of time—but the variety of ghost behavior and the gradually intensifying difficulty create a neat progression. The final reward is a bright, newly revealed house, signifying the end of the haunting and the triumph of actually getting to live in your newly bought property.

How the Project Works

The code behind this game employs a simple state machine to orchestrate its various parts. I found this approach more intuitive than cramming all logic into one giant loop. Whenever the player transitions from, say, the INTRO state to LEVEL1, the script calls startLevel(level), which resets the timer, spawns the appropriate ghosts, and ensures there’s no carry-over from earlier states. Here is a small excerpt that illustrates how the game transitions from one level to the next or ends if all ghosts are defeated:

if (ghosts.length === 0) {
  if (level === 1) {
    state = "LEVEL2";
    startLevel(2);
  } else if (level === 2) {
    state = "LEVEL3";
    startLevel(3);
  } else if (level === 3) {
    state = "WIN";
    ghostSound.stop();
    victorySound.play();
  }
}

I’m particularly proud of how coherent each ghost type’s logic is, thanks to object-oriented design. I broke down the ghosts into three classes—StaticGhost, MovingGhost, and BossGhost—so each can handle its own movement and hit requirements. For instance, the MovingGhost class includes velocities in both x and y directions. It updates its position each frame and bounces off the canvas edges, which felt more elegant than scattering if-conditions all over the main draw() loop. This design choice also eases extension: if I someday add a new ghost that splits into two smaller ghosts on hit, I can isolate that behavior in yet another class.

Moreover, I love the inclusion of sound elements, as it heightens the atmosphere. The ghostly background audio starts the moment you tackle Level 1, giving a sense of stepping into a haunted property. On every successful hit, a short “blast” sound triggers, reinforcing the feedback loop for players clicking in a hurry. When the boss ghost is defeated, the game transitions to a “WIN” screen with a triumphant sound, showing off the newly purified house. These little touches bring a pleasant cohesiveness to the otherwise basic act of clicking on sprites and add a layer of fun that purely visual feedback might not achieve.

Areas for Improvement & Challenges Faced

While I’m delighted with the final result, I definitely noticed some spots that could be enhanced through further iteration. First, game balancing was tricky. If I set the time limits too high, the game lost its tension because players could leisurely pick off ghosts. If I made them too strict, new players often found themselves losing before they fully grasped the ghost patterns. I settled on modest values for each level, but it still demands some quick reflexes—if someone isn’t used to rapid clicking, they might find the default times a bit harsh. Introducing difficulty modes, or maybe timed boosts that freeze the ghosts for a short period, would give me more fine control over that difficulty curve and cater to different skill levels.

Another challenge was ensuring that state transitions stayed seamless. At one point, I had ghosts from Level 1 lingering into Level 2, causing the dreaded “two waves at once” bug. The fix involved carefully resetting arrays and timers inside startLevel(level) and confirming no leftover references were carried over. Though it took some debugging, it taught me the importance of thorough housekeeping when cycling through game phases—particularly in an experience that uses back-to-back waves, each with its own unique ghost behaviors. If I expand the project in the future, perhaps adding more levels or extra ghost abilities, I’ll rely heavily on these same organizational principles to keep the code from becoming unwieldy and prone to surprises. I feel the game meets my initial ambition: to craft a short, fun, and spooky challenge that doesn’t overstay its welcome. It balances straightforward gameplay—just point-and-click to vanquish ghosts—with enough variety to keep the three levels distinct and interesting. As I continue refining or building upon the concept, I plan to experiment with new ghost types or reward systems that push the idea even further, but I’m proud of how the current version stands on its own as a playful haunted-house journey.

Week 5: Reading Response

When I first delved into Golan Levin’s discussion of computer vision, I was amazed by how fundamentally different it is from our human way of perceiving the world. We can glance at a room and instantly recognize faces, objects, or even subtle differences in lighting, but a computer needs methodical instructions to interpret even the simplest movements or contrasts. Techniques like background subtraction and frame differencing demonstrate how each pixel’s change or brightness must be computed step by step, and how crucial controlled environments can be for effective tracking. In a way, I found this both exciting and challenging: exciting because it opens up possibilities for precise, algorithmic interactions, but challenging because it shows just how quickly a system can fail if the lighting shifts or a background changes color. Through these examples, I realized that crafting the right physical setup—whether that means backlighting a subject or using distinct color markers—can dramatically improve what a computer can “see” and do.

Building on these observations, I became even more intrigued when I saw how these vision techniques are applied in interactive art. While projects like Myron Krueger’s Videoplace demonstrate the joyful, participatory side of computer vision—allowing people to engage with entire environments using body gestures—David Rokeby’s Sorting Daemon reminds us that the same technology can be used for unsettling surveillance. Reflecting on these projects, I’ve come to appreciate how computer vision can empower artists to transform spectators into active participants, yet it also raises important ethical questions about privacy and consent. This duality fascinates me: on one hand, the capacity to create immersive, responsive installations feels almost magical; on the other, the act of monitoring people, even for art, can be deeply discomforting. Levin’s exploration emphasizes that as designers and creators, we need to balance our excitement for technical innovation with a thoughtful awareness of its broader social implications.

Week 5: Midterm Progress

Concept

I’m in the process of creating a haunted-house-themed game where the player has purchased a dilapidated property, mainly because it was so cheap—no one else wanted it. The catch is that it’s infested with ghosts. My overarching goal is for the player to banish these ghosts, wave by wave, ultimately revealing the house’s true beauty once it’s free of any supernatural presence. I want to capture a sense of gradual transformation: at first, the environment is dim and unnerving, but it transitions to a bright, welcoming home as the player defeats all the ghosts.

Progress So Far

So far, I have built out a state machine that includes an intro screen, a main “PLAY” state, and placeholders for the final “WIN” and “END” screens. In the intro, the game briefly explains the story—that the house was bought cheaply because of the hauntings—then moves to the main gameplay once the user clicks the start button. The basic logic for wave progression is in place: after the initial wave of slower ghosts, I plan to introduce a second wave of faster ghosts, and ultimately a boss ghost that requires multiple hits to defeat. Each ghost’s code has been thoroughly tested in small increments, ensuring that the transition between waves feels smooth. I also integrated a rudimentary health system; each time a ghost vanishes without being clicked, the player’s health decreases, raising the stakes as they progress.

Class Implementation

A key aspect of my current setup is the Ghost class, which I designed to handle movement, timing, and click interaction. By encapsulating these behaviors, I’ve managed to keep my main draw() loop more organized and make it simpler to test the game’s logic wave by wave. Here is a condensed version of the Ghost class:

class Ghost {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.size = 60;
    this.visible = true;
    this.wasClicked = false;
    this.vx = random(-2, 2);
    this.vy = random(-2, 2);
    this.spawnTime = millis();
    this.lifespan = 5000; // 5 seconds
  }

  move() {
    if (!this.visible) return;
    this.x += this.vx;
    this.y += this.vy;
    if (this.x < 0 || this.x + this.size > width) {
      this.vx *= -1;
    }
    if (this.y < 0 || this.y + this.size > height) {
      this.vy *= -1;
    }
    if (millis() - this.spawnTime > this.lifespan) {
      this.visible = false;
    }
  }

  display() {
    if (this.visible) {
      image(ghostImg, this.x, this.y, this.size, this.size);
    }
  }

  isClicked(mx, my) {
    return (
      this.visible &&
      mx > this.x && mx < this.x + this.size &&
      my > this.y && my < this.y + this.size
    );
  }

  vanish() {
    this.visible = false;
    this.wasClicked = true;
  }
}

Using this as a foundation, I have also been working on subclasses like FastGhost and BossGhost to provide unique behaviors—faster speed, shorter lifespans, or requiring multiple hits to defeat. This object-oriented structure ensures I can easily add or modify ghost types without complicating the main game flow.

Frightening / Challenging Aspects

One of the biggest challenges I’m facing is tuning the difficulty so it feels suspenseful without being overly punishing. In particular, I need to strike a balance between ghost speed, lifespan, and the number of ghosts per wave. If ghosts vanish too slowly, it’s too easy; if they move or time out too quickly, it becomes frustrating. Another tricky part is creating a strong contrast between the haunting atmosphere at the start and the serene, beautiful environment at the end—this requires careful coordination of art assets, lighting (or color usage), and the timing of transitions so players truly feel like they’ve “rescued” the house from a dark fate.

Risk Prevention

I have set up the game flow using distinct states—“INTRO,” “PLAY,” “WIN,” and “END”—to keep code separated and avoid any messy overlaps. Testing each state individually helps isolate potential bugs early. I also made sure that all ghost interaction, movement, and collision logic lives within their respective classes, so if there’s an issue with a particular ghost type, I know exactly where to look for a fix. By incrementally adding waves and testing them (rather than coding all three at once), I can ensure that each wave behaves as intended and that wave transitions don’t break the health or scoring systems. This structured approach reduces the chance of large-scale errors going unnoticed until late in development.

Next Steps

I still need to fully integrate the final boss ghost, which will serve as the game’s climactic encounter. Once the boss is in place, I will refine the wave progression so that defeating the boss triggers a major visual shift—the unveiling of the house’s hidden beauty. Finally, I’ll spend time polishing transitions between states, adjusting ghost behaviors, and ensuring that the health system and scoring remain engaging but fair. My aim is for players to feel a real sense of accomplishment when they see the haunting gloom replaced by a warm, inviting dwelling, thereby completing the game’s central promise of transforming a scary, cheap purchase into a comfortable new home.

 

Assignment 4: Generative Text

In this assignment, I created an interactive visualization featuring animated letters that swirl, drift, and change colors as they fall across the screen. The letters are selected randomly from a character set of uppercase English letters and numbers. Each letter moves independently with unique properties such as speed, rotation, color cycling, and sinusoidal horizontal drift. The use of transparency in the background creates a subtle trailing effect, enhancing the sense of motion and fluidity. The goal of this project was to create an aesthetically engaging and dynamic animation with a mix of structured randomness and organic movement.

One part of the code that I am particularly proud of is the display() method inside the SwirlingLetter class. This function not only ensures smooth rendering of each letter but also cycles through colors using sinusoidal variations. This approach creates a mesmerizing shifting color effect without requiring predefined color schemes. Another aspect I appreciate is the reset mechanism in update(), which seamlessly resets letters when they fall below the canvas, ensuring a continuous flow of animation. Looking ahead, possible improvements include adding user interactivity, such as allowing the mouse to influence letter movement or introducing gravity variations for more dynamic behavior. Another potential enhancement could involve applying Perlin noise for smoother, more naturalistic drifting patterns, making the animation feel even more organic.

display() {
  // Calculate color based on colorPhase (sin/cos wave)
  let r = 127 + 127 * sin(this.colorPhase);
  let g = 127 + 127 * sin(this.colorPhase + TWO_PI / 3);
  let b = 127 + 127 * sin(this.colorPhase + (2 * TWO_PI) / 3);
  
  push();
    translate(this.x, this.y);
    rotate(this.angle);
    textSize(this.fontSize);
    fill(r, g, b);
    text(this.char, 0, 0);
  pop();
}

Week 4: Reading Response

The reading was an insightful exploration of design principles, especially in how seemingly simple objects can cause unnecessary confusion due to poor design. Norman’s discussion of unintuitive doors resonated with me because I often find myself second-guessing whether to push, pull, or slide a door. It reminded me of how many everyday frustrations are not due to user error but rather poor design choices. This reading reinforced the idea that effective design should be invisible—when done well, users don’t notice the effort behind it, but when done poorly, it becomes a major source of frustration. The comparison to unnoticed yet essential elements in other fields, such as sound design in film, really stood out to me. Just like poor audio mixing can pull you out of a film, bad design disrupts an otherwise seamless interaction with a product. The reading also made me appreciate the balance required in good design—ensuring clarity without overwhelming users with excessive instructions, and making products both functional and aesthetically pleasing.

Applying these design principles to interactive media requires a careful balance of affordances, feedback, and signifiers to ensure an intuitive experience. In previous projects, I’ve experimented with interactive elements like hover effects and keyboard controls, but I’ve realized that just because an interaction is possible doesn’t mean users will know it exists. Without clear signifiers, like visual prompts or subtle animations, the interactivity might go unnoticed, reducing engagement. I’ve also seen cases where too much feedback—like unnecessary pop-ups or redundant instructions—ends up being more annoying than helpful. A major takeaway from Norman’s work is that design should guide users naturally rather than force them to read detailed instructions. For interactive media, this could mean designing with affordances that align with user expectations, like making buttons look clickable or using motion cues to hint at interactivity. Balancing clarity with aesthetics is key to making interactive experiences engaging without being intrusive.

Week 3: OOP assignment

Reflection

In this assignment, I set out to create a whimsical yet recognizable depiction of our solar system, complete with every planet—and even Pluto for nostalgia. The overarching idea was sparked by my longstanding fascination with both outer space and various generative art techniques, as I sought to merge the awe-inspiring nature of celestial bodies with the playful unpredictability of computer-generated visuals. To capture the Sun’s vibrant energy, I used sine waves to animate its pulsing effect, allowing the star’s size and color to oscillate smoothly. This design choice aimed to give the Sun an almost breathing, organic character, setting the tone for the rest of the scene. Each planet follows an elliptical orbit, and I introduced distinct starting angles and orbital speeds to ensure that no two bodies behave exactly alike. This subtle variety makes the animation feel more alive from the outset, preventing it from looking too rigid or scripted. Additionally, I incorporated a feature to generate a random number of moons for each planet, providing further variation across multiple runs. One of the structural highlights of my approach was centralizing each planet’s properties—such as hue, orbit radii, and moon count—within a dedicated data array. This not only simplified the process of tweaking individual planetary attributes but also made it easier to add or remove planets and features without having to refactor the entire codebase.

// Each object in this array describes one planet's settings
let planetData = [
  {
    name: "Mercury",
    orbitXRadius: 80,
    orbitYRadius: 70,
    p_speed: 2.0,
    size: 6,
    col: [200, 200, 60],
    moonCount: 0
  },
  {
    name: "Venus",
    orbitXRadius: 120,
    orbitYRadius: 110,
    p_speed: 1.8,
    size: 8,
    col: [220, 150, 70],
    moonCount: 0
  },
  {
    name: "Earth",
    orbitXRadius: 160,
    orbitYRadius: 150,
    p_speed: 1.6,
    size: 9,
    col: [70, 150, 220],
    moonCount: 1 // Earth has 1 moon
  },
  {
    name: "Mars",
    orbitXRadius: 200,
    orbitYRadius: 190,
    p_speed: 1.3,
    size: 7,
    col: [220, 100, 70],
    moonCount: 2 // Mars has 2 small moons
  },
];

During development, a particularly intriguing challenge arose when dealing with the sheer number of moons orbiting the larger gas giants, like Jupiter and Saturn. Rendering a high volume of small objects orbiting in real-time can quickly become computationally expensive. To address this, I experimented with optimizing the drawing routines and ensuring that the code avoids unnecessary calculations—especially when multiple moons share similar trajectories or render states. Another aspect I focused on was enhancing the user’s sense of connection with the simulation. Currently, a single mouse click toggles whether the orbit paths are displayed, letting viewers choose between a minimalistic, clean look and a more instructive, data-rich visualization. As an additional layer of engagement, I plan to implement interactive elements such as hovering over a planet to reveal tooltips or pressing specific keys to label celestial bodies and show background stars. These features would deepen the user’s involvement, granting them not just a visual feast but also the chance to explore and learn.

 

Week 3 : Reading Response

After reading Crawford’s ideas on interactivity, I was struck by how he frames the concept as a cycle of listening, thinking, and speaking. He challenges the simplistic view that “if it responds, it’s interactive,” emphasizing that true interaction requires a more dynamic back-and-forth. This made me question some of my assumptions about interactivity—like whether a simple click-triggered effect is truly interactive, or just a one-way reaction. According to Crawford, a strongly interactive system should give the user a sense that it’s actively “processing” their input rather than just following a fixed script. In other words, the user’s actions should not only trigger changes but also reshape or evolve the system’s behavior in meaningful ways.

Relating this to my p5.js solar system sketch, I see opportunities to move beyond basic clicks and toggles. Right now, you can click to hide or show orbital paths, but that’s still a simple action-reaction loop. To aim for deeper interactivity, I might introduce randomness so that user input doesn’t always yield the same response. For example, clicking could not only show or hide paths but also subtly alter each planet’s orbital speed or inject slight random offsets into their trajectories. Over multiple clicks, the system might “remember” user interaction patterns, causing planets to change color, size, or even generate more moons in unpredictable ways. The idea is to create a sense that the system is actively “listening” and “thinking,” rather than just following a preset script. This approach would align more closely with Crawford’s vision of a conversational cycle of listening, thinking, and speaking. Instead of a purely linear input-output relationship, the randomness and memory would allow the solar system to evolve over time based on both user inputs and the system’s own internal logic. Each interaction would become unique, encouraging the user to explore and discover new outcomes. By blending adaptive responses and probabilistic elements, the solar system sketch could feel more alive and genuinely interactive, giving the user a bigger sense of agency in shaping the cosmic simulation.

Week 2: Reading response (Casey Reas’ Eyeo talk)

How are you planning to incorporate random elements into your work?

Randomness is usually seen as something chaotic, but Casey Reas makes a strong case for it as a necessary ingredient in structured systems. His work shows that when randomness is completely absent, everything eventually settles into sameness—it loses vitality. That idea made me reconsider my approach. I tend to design with a clear sense of control, ensuring everything is deliberate. But maybe randomness isn’t about losing control; maybe it’s about creating space for unpredictability to enhance structure. Instead of placing every element with precision, I want to introduce rules that allow randomness to shape certain aspects—maybe through variation in form, spacing, or subtle movement. This way, my work maintains a structured framework but never becomes rigid. I like the idea of randomness making a piece feel alive, as if it’s still evolving even after it’s complete.

Where do you feel is the optimum balance between total randomness and complete control?

There’s a sweet spot where randomness and control feed into each other, and that’s where the most compelling work happens. Reas talks about how systems that are too rigid become static, while those that are too chaotic lose coherence. That really resonated with me because I’ve felt the same frustration in my own work—when something is too ordered, it feels predictable; when it’s too random, it lacks intention. The best balance depends on what the work is trying to say. If I want a sense of structure, I can set constraints but allow randomness to influence the details—like adjusting spacing, shifting colors, or adding unpredictable textures. It’s not about choosing between order and chaos but about letting them interact, so the piece always has a bit of tension, a sense that it could shift or evolve. That, to me, makes the work more engaging, both visually and conceptually.