Assignment 4 – Generative Text

Concept

Well, so I wanted to create something that would bring words to life based on their emotional weight. The idea came to me while I was writing an essay and then I was just thinking about how certain words just hit differently; like how “thunder” feels more intense than “whisper,” for example. So I built this visualization that reads emotion data from a CSV file and animates words according to their intensity levels. Each word gets its own personality through movement – high-intensity words explode across the screen in chaotic circles, medium-intensity ones flow like waves, and gentle words just float peacefully. The colors and sizes change too, so you can literally see and feel the emotion in each word. Every 3 seconds it switches to a new word automatically, but you can also hit the spacebar to jump ahead if you’re impatient (like me).

Highlight of the code I’m proud of

The part that really clicked for me was figuring out how to make each letter move independently while still keeping the word readable. At first, all my letters were just clumped together or flying off in random directions, but then I realized I needed to treat each letter as its own little character with its own animation offset.

// Animate each letter individually
for(let i = 0; i < word.length; i++) {
  let x, y, size;
  
  if(intensity >= 80) {
    // High energy - explosive circular movement
    let angle = time * speed + i * PI/3;
    let radius = sin(time * 6 + i) * intensity * 0.5;
    x = cos(angle) * radius * 0.4 + i * 40 - (word.length * 20);
    y = sin(angle) * radius * 0.3;
    size = 45 + sin(time * 8 + i) * energy * 15;
  }
  // ... more animation types
}

Using i * PI/3 and i * 0.6 as offsets made each letter follow the same pattern but at slightly different phases, so they stay connected as a word but each one has its own rhythm.

I’m also pretty happy with how I handled the CSV parsing. I decided to do it manually instead of using a library.

// Parse CSV manually - split into lines then extract values
const lines = csvText.trim().split('\n');
const headers = lines[0].split(',');

// Process each data row (skip header row)
for (let i = 1; i < lines.length; i++) {
  const values = lines[i].split(',');
  csvData.push({
    word: values[0],
    intensity: parseInt(values[1]),
    color: [
      parseInt(values[2]),  // red
      parseInt(values[3]),  // green
      parseInt(values[4])   // blue
    ]
  });
}

Sketch

The visualization cycles through emotional words automatically, or press spacebar to advance manually.

 

Future Improvements

There are definitely some things I want to tackle next. First, I’d love to add sound. Another idea is to let users upload their own word lists or even type in words manually to see how the system interprets them. Right now it’s limited to my CSV file, but it would be cool to make it more interactive. I also want to experiment with particle effects – maybe letters could leave trails or break apart into smaller pieces for really explosive words.

The color system could be smarter too. Right now I’m manually assigning colors, but it would be interesting to generate them automatically based on the word’s emotional category or intensity. Maybe cooler colors for calm words and warmer ones for energetic words, or even colors that shift gradually as the intensity changes.

Week 4 Coding Assignment

Concept:

When I see words like generative text, I immediately think of the code rain effect that happened in the movie matrix.

(screenshot of the code rain visual effect in the movie matrix)

I intend to recreate this effect by using p5js.

Code that I am proud of:

To recreate this effect, there must be at least two types of objects that we want to define. First, the “word stream” that appears in the screen. Second, the individual elements of the characters. By writing these two classes, the rest of the setup should be easy.

draw() {
    // Slight green variance between streams
    const g = map(sin(this.colorPhase), -1, 1, 180, 255);
    if (this.isHead) {
      fill(180, g, 180); // brighter/whiter head
    } else {
      fill(120, g, 120);
    }
    text(String(this.value), this.x * this.glyphSize, this.y * this.glyphSize);

when writing matrix symbol class, I am proud of these lines of code. by using very simple mathematics, I successfully achieved the effect of having green variance across different streams.

output:

reflection:

after reading the design post, I feel like if i want to add any design to this animation, I would try to add the effect of when users swipe their mouses across the screen, the length of the streams would change or the stream would be stroked by where the mouse is at.

 

Week 4 – Post Response

Post Response: The Psychopathology of Everyday Things

One thing that drives me crazy, which wasn’t directly mentioned in Norman’s reading, is the “close door” button on elevators. It feels like a control I should have, but in most modern elevators, pressing it does absolutely nothing for ordinary passengers. The button is just there to give the illusion of control, which is frustrating when you actually want the doors to close faster. A simple improvement would be to either remove the button entirely or make it functional for real—perhaps by allowing it to slightly shorten the automatic door timer, while still respecting safety regulations. This would reduce the cognitive dissonance between what the interface suggests and what it actually does.

Another example is the volume slider on phones. While it looks linear, the actual increase in volume is logarithmic to match human perception. This hidden design is clever, but it highlights how designers are constantly manipulating reality to feel “natural.” I find it fascinating—and slightly maddening—how often interfaces are designed to trick our senses into thinking things are more intuitive than they are.

Applying Norman’s principles to interactive media, these insights are extremely valuable. For example, in a music app or video game, sliders for volume, brightness, or character speed should be perceptually adjusted so that changes feel smooth and intuitive. Similarly, buttons or controls should give honest feedback: if an action can’t actually happen (like the elevator door closing instantly), the interface should indicate that limitation rather than pretend otherwise. This reduces user frustration and improves overall satisfaction.

In general, understanding the psychopathology of everyday things encourages designers to consider the gap between perception and reality. By designing interactions that match how humans perceive the world, we can make digital interfaces feel more natural and enjoyable.

Week 4 – Text Art

Concept

My artwork “Can You Understand Me?” explores human connectedness through language and the barriers that can arise when communication breaks down. The phrase “Can you understand me?” is a simple but powerful question, expressing both the desire for connection and the frustration of being misunderstood. By placing this phrase in multiple world languages on the screen, I wanted to highlight the diversity of expression and the universality of the human need to be heard.

The floating words and question marks represent the fluid, sometimes chaotic nature of communication. They drift, interact, and repel—mirroring how language can bring people closer or push them apart, depending on understanding.


Code Highlight (what I’m most proud of)

One feature I’m especially proud of is the repelling effect from the mouse. I designed this so that when the mouse gets too close, the words push away. It represents the tension we sometimes feel in conversation—when misunderstanding or pressure creates distance, even when connection is desired.

Repel from mouse let mouse = createVector(mouseX, mouseY);
let d = dist(this.pos.x, this.pos.y, mouse.x, mouse.y);
if (d < 200) {
let force = p5.Vector.sub(this.pos, mouse);
force.setMag(8 / max(d, 1));
this.vel.add(force);
}

This snippet calculates the distance between each word and the mouse, then generates a force pushing the word away when the mouse is within 200 pixels. It’s a small detail but adds a lot of dynamic personality to the sketch.


Embedded Sketch


Reflection

Working on this project taught me how much movement and interaction can symbolize deeper human experiences. The floating words show how languages circulate and intermingle globally, while the mouse repulsion adds an element of friction, symbolizing the challenges of cross-cultural communication.


Reference

Week 4 – Reading Response

One thing that always frustrates me are the elevator button panels. I can’t count the number of times I’ve stood in front of a shiny panel of identical metal buttons, with no clear distinction between “door open,” “door close,” or the emergency button. Sometimes the “door open” symbol is barely visible or located in an unintuitive spot, and more than once I’ve pressed the alarm instead of the open button (which is always a bit embarrassing).A small redesign could go a long way: using clearer icons, color coding, or even tactile differences would make it more intuitive. Norman’s point that “when something goes wrong, the user is often blamed instead of the design” fits perfectly here. It’s not that people are clumsy, it’s that the system doesn’t communicate well.

I’m still thinking about the line that said “Good design starts with an understanding of psychology and technology. It is not enough that we build products that work; they must be understandable and usable.” This directly brings us to the UX. UX is important because it shapes the way people experience and connect with a product, space, or interaction. Good UX reduces confusion, frustration, and wasted effort, making tasks feel natural and even enjoyable. As Norman emphasizes, design isn’t just about how something looks, it’s about how it communicates its purpose and supports human behavior. When UX is overlooked, people often end up blaming themselves for “not getting it,” when in reality it’s the design that failed to guide them.

When I think about applying Norman’s principles of design to interactive media, the biggest lesson is clarity in signifiers and feedback. In my projects, I’ve sometimes assumed that users will “just know” what to click or press, but Norman’s reminder is that what feels intuitive to me as the designer may not feel that way to someone else. Adding clear visual cues like arrows, hover highlights, or simple instructions makes interactions discoverable and satisfying. Affordances and signifiers should be obvious, users shouldn’t have to guess what to click, drag, or press. Feedback is just as important: when someone interacts with my project, they should instantly see or hear a response. That way, instead of frustration, interaction feels like a satisfying loop.

 

Week 4 – Bump please

Concept

For this assignment I wanted to create something to do with text and the first thing that came to my mind was how we ask our friends to Bump! our posts on our Facebook RoR group (Room of Requirement, a group in Facebook for NYU Abu Dhabi students). So then I decided why not create something to do with this legendary word Bump?

When I think of that word, multiplication comes to my mind because the more times you write it, the more audience sees your post. So that lead me to an idea that when you press the word, it spawns another Bump!, with a random color and its own bouncing behavior.

Creation

I created a Bump class that stores position, speed, color, and the text itself. Each bump moves across the canvas and bounces when it hits the edges. When the user clicks on a bump, a new one is created in a random position with a random color, and it moves independently. I also added a restart option so that pressing the key C or c clears the screen and brings back just one bump in the center.

Difficulties

The most challenging part for me was figuring out how to detect if the mouse actually clicked on the text. Since text doesn’t have a simple rectangle in p5.js, I had to calculate the approximate bounding box using textWidth and the text size. After that, I also had to make sure the bumps bounced correctly on the edges, which meant checking both horizontal and vertical boundaries.

Favorite Part

My favorite part of the code is definitely the spawning of new bumps. I love how every click brings a surprise because the new text gets a random color and a random speed. It gives the sketch a playful and unpredictable feeling, which matches the energy of the word Bump! itself.

function mousePressed() {
  // check each bump to see if mouse is inside it
  for (let b of bumps) {
    if (b.clicked(mouseX, mouseY)) {
      // if clicked, create a new bump at random position
      bumps.push(new Bump(random(width), random(height)));
      break; // only add one new bump per click
    }
  }

Future Improvements

In the future, I would like to add a few more playful features. For example, making the bumps grow or shrink over time, adding sound effects when they collide with the walls, or even keeping track of how many bumps were created. Another fun idea would be to make the bumps interact with each other—like bouncing off one another instead of just overlapping.

So here’s my end result, and if you see my post on RoR, please bump it :))

Press bump! to multiply it, and press C to reset

Week 3 – The Art of Interactive Design Ch.1

My definition of interactive was always just… I do something, and the thing does something back. A game, a movie, whatever. As long as we were both making actions, I figured that was it.

But in the chapter putting the interaction or being interactive into the frame of a conversation (listen, think, speak) made me stop and question that. It makes me wonder if the actions have to actually depend on each other. Like, the system’s reaction should be different based on what I did, not just a pre-programmed response to any action.

This makes me look at a lot of stuff we’ve made in p5.js completely differently. Most of those examples aren’t really interactive by this standard. I mean, you click the mouse and a shape appears, but it’s the same shape every single time. The code isn’t really thinking about my input, it’s just reacting. It’s a glorified light switch. True interaction needs that middle ‘think’ step, where the response is actually considered, not just triggered. That’s a way more interesting goal to aim for.

Week 3 – art work

Title: Does the Power of Lover overcome the Love of Power

This is an interactive generative artwork that explores the dynamic struggle between two opposing forces: Power of Love and Love of Power. Using color, motion, and shape, the piece visualizes how these forces interact, dominate, and fade.

Users can interact with the artwork using the keyboard: pressing X strengthens the Power of Love, Z increases Love of Power, and R resets the canvas. As one force grows, it overwhelms the other, creating a constantly shifting visual narrative of dominance, balance, and fragility.

Highlight of Code I’m Proud Of:

One part I’m particularly proud of is the heart shape formula used in the Heart class. Creating a convincing pulsing heart shape took a bit of trial and error—adjusting the sine and cosine coefficients to get the proportions and curves right. When I looked it up to check my work, I was pleasantly surprised to realize that I had remembered the formula almost perfectly! The code also incorporates time-based pulsing and subtle distortions influenced by the interaction of the two forces:

class Heart {
  constructor(battle) {
    this.battle = battle;
  }

  display() {
    let { t, loveStrength, powerStrength } = this.battle;

    let heartOpacity = map(loveStrength, 0, 1, 10, 90);
    let heartPulse = map(loveStrength, 0, 1, 0.4, 2.5);

    stroke(340, 80, 100, heartOpacity);
    strokeWeight(2 * heartPulse);

    for (let i = 0; i < 3; i++) {
      let s = 100 + sin(t * 2 + i) * 50 * heartPulse; // pulsing size
      beginShape();
      for (let a = 0; a < TWO_PI; a += 0.1) {
        // classic heart shape formula
        let x = s * 16 * pow(sin(a), 3) / 10 + sin(t + i) * 30 * powerStrength;
        let y = -s * (13 * cos(a) - 5 * cos(2 * a) - 2 * cos(3 * a) - cos(4 * a)) / 10
                + cos(t + i) * 30 * powerStrength;
        vertex(x, y);
      }
      endShape(CLOSE);
    }
  }
}

This section highlights the combination of mathematical formula, animation, and interaction to make the heart both accurate and dynamic.

Week 1 – Self Portrait

This is a self-portrait created with p5.js, inspired by Picasso’s cubist style. I focused on abstracting key features such as the hair, glasses, beard, and mustache into bold geometric forms and playful colors to emphasize expression over realism.

Week 3 – Reading Reflection

It was really interesting (and funny) to read this first chapter of The Art of Interactive Design. I have never thought that interactivity could be so different and have its’ ‘levels’. And to answer the question proposed at the end of the book, Are rugs interactive? my answer is yes, but the interaction is low, because it’s one sided (just like a fridge).

If I talk about my idea of interaction, I think it’s when the users can engage with the interface. A strongly interactive system is characterized by its ability to respond to user input in meaningful and timely ways. Such systems provide clear cues about how the user can act, make the results of actions visible, and maintain a balance between user control and system guidance. Importantly, they allow exploration and learning by allowing users to experiment without fear of irreversible mistakes.

In my p5 sketches, these principles suggest several ways to improve interaction. For example, I can add more responsive feedback, like visual or auditory cues when users click or hover over elements. Allowing users to customize aspects of the sketch, such as colors, speeds, or behaviors, can enhance engagement. Introducing elements of exploration, like hidden surprises or random effects, encourages experimentation. Additionally, implementing smoother animations and more natural movements, rather than abrupt changes, can make interactions feel more intuitive and satisfying. Overall, designing sketches that are predictable yet playful, and that reward user input, aligns with the chapter’s emphasis on creating systems that are both interactive and enjoyable.