Week 4 – Reading Response

Week 4 –  The Design of Everyday Things, The Psychopathology of Everyday Things

In Chapter 1, Don Norman introduces the idea of human-centered design (HCD) and claims that a well-designed object should be intuitive and easy to use. He emphasizes how poor design may lead to confusion and frustration, which highlights that when people are struggling to use a product, it’s often the fault of the designer, not the user. Additionally, there are a few key principles that were introduced including affordances, signifiers, feedback, and conceptual models. Affordances refer to the properties of an object that indicate how it should be used (a handle affords pulling). Signifiers give clues about how an object functions, such as labels or icons. Feedback ensures that users receive a response when they interact with a design (a light turning on when a button is pressed). Lastly, conceptual models help users predict how an object will behave based on previous experiences. Norman critiques some common usability failures, such as confusing doors (push vs. pull) and complicated appliances. He believes that a well-thought-out design prioritizes clarity, simplicity, and usability rather than just aesthetics.

His valuable insights point out how much bad design impacts daily life. Usually, people will blame themselves for struggling with an object when, in reality, the issue lies in poor design choices. This made me think about how many times I’ve encountered objects that don’t work the way I expect them to, especially digitally where buttons are unresponsive. The chapter reinforces the idea that usability should always come before aesthetics in design. One thing that I find annoying is some modern car systems. Many car manufacturers have replaced physical buttons with touchscreen controls for functions like climate control. The reason that this is frustrating is that they often have poor menu structures, which require you to open multiple tabs for simple tasks like changing the AC temperature. There are various ways to improve this with one being to simply bring back physical buttons for frequently used functions like temperature, volume, and hazard lights. Another thing that could be done is the use of haptic feedback on touchscreens so users can feel when they’ve selected something. Applying Norman’s principles to interactive media can significantly improve usability and user experience. For example, buttons should look clickable, and the links should be distinguishable. Loading animations, confirmation messages, or vibrations on a touchscreen can signal that an action has been completed. Similarly, error messages should be clear and instructive and tell users what went wrong and how to fix it. By prioritising usability over aesthetics, designers are able to create interactive media that feels intuitive rather than frustrating.

Week 4 – Generative Text (Infinite Rain)

Concept

For this project, I chose generative text but wanted to take a unique approach. Instead of displaying standard text, I decided to present the Greek alphabet in an interactive and visually engaging way. Finding all the symbols online was surprisingly easy. The inspiration for the rain-like effect came from the current rainy weather, adding a dynamic element to the design. I also incorporated interactivity and animation while making use of arrays, classes, and loops to enhance the experience.

Code Highlights

Working on this assignment introduced me to new JavaScript features and functions, such as

splice()
splice()for managing arrays and the fourth argument in
background()
background()
, which allows for transparency effects. These discoveries helped refine the animation and improve the overall visual aesthetic. Some key blocks of code demonstrating these techniques are included below.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Remove symbols that reach the bottom
if (particles[i].y > height) {
particles.splice(i, 1);
// Remove symbols that reach the bottom if (particles[i].y > height) { particles.splice(i, 1);
// Remove symbols that reach the bottom
if (particles[i].y > height) {
  particles.splice(i, 1);
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function draw() {
background(10, 10, 30, 100);
function draw() { background(10, 10, 30, 100);
function draw() {
  background(10, 10, 30, 100);

Reflections & Future Improvements

I enjoyed working on this assignment and gained valuable insights into generative art. However, I originally wanted to explore data visualization but faced challenges in loading data effectively. Moving forward, I plan to practice more with data handling so I can confidently incorporate it into future projects. Additionally, I aim to experiment with more complex interactivity to further enhance the user experience.

PRESS C TO CHANGE COLOR, G TO INCREASE SPEED, CLICK MOUSE TO ENJOY🙂

 

Week 4 – Reading Reflection

One thing that frustrates me is the complexity of using ACs on campus. Despite using them regularly, I have never fully mastered their functions beyond adjusting the temperature. This might seem minor, but it highlights a larger issue—many devices include extra features without clear instructions or intuitive design. Manufacturers often add numerous buttons and settings beyond a device’s core function, but without proper labeling or guidance, users are left guessing. For example, dryers come with multiple buttons beyond basic power and fabric selection, yet their purposes are unclear. Without clear signifiers, users may misuse the device, leading to frustration or even damage. A simple improvement would be better labeling, intuitive icons, or brief explanations to enhance usability and ensure users get the most out of these everyday appliances.

With respect to interactive media, one beneficial concept from the reading is the importance of contributions from people in other disciplines. As Norman states toward the end of the reading, “Design requires the cooperative efforts of multiple disciplines.” I could seek feedback from non-CS students or those without an interactive design background to determine whether my interface is easy to navigate without prior technical knowledge. For example, art students may provide insights on clarity and aesthetic appeal, ensuring the design is both functional and visually engaging. By actively involving diverse perspectives, I can create interactive media that is more intuitive, inclusive, and user-friendly, making my designs accessible to a wider audience rather than just functional for me.

Week 4 – Displaying text

Week 4 – Displaying Text

For this project, I wanted to make something fun, so I created a random law generator. The goal was to create absurd but still convincing-sounding fake laws that feel like they could exist in some strange town. The program works by randomly generating a town name, a weird law, and an exception. When the user clicks on the canvas, a new random law appears. As for the visual aspect, the law is displayed on a lined piece of paper with a pencil next to it. I added a brown background to make it look like the paper is resting on a wooden table.

One of the main parts of the project is how the laws are randomly generated and displayed:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
function generateLaw() {
let town = random(towns);
let action = random(illegalActions);
let exception = random(exceptions);
randomLaw = `In the town of ${town}, it is illegal to ${action} ${exception}.`;
}
function generateLaw() { let town = random(towns); let action = random(illegalActions); let exception = random(exceptions); randomLaw = `In the town of ${town}, it is illegal to ${action} ${exception}.`; }
function generateLaw() {
  let town = random(towns);
  let action = random(illegalActions);
  let exception = random(exceptions);

  randomLaw = `In the town of ${town}, it is illegal to ${action} ${exception}.`;
}

This selects a random town name from the towns array and picks a random illegal action from illegalActions. Then it selects a random exception from exceptions and combines them into an absurd law.

I faced a few challenges I had to overcome, including correctly aligning the pencil. At first, the pencil eraser and tip didn’t align properly with the body, so I had to adjust the x and y positions carefully to ensure the pencil remained vertical. Additionally, the lines on the paper were too bold, which made it feel unrealistic so I had to adjust the stroke colour and spacing.

Overall, I am satisfied with the way this turned out as it was a fun way to practice generative text output in p5.js. I learned how randomization in programming can create entertaining and unexpected results. Additionally, I had another chance to explore loops, which were useful for drawing repetitive elements like notebook lines. However, there are a few things I could improve on next time like including a hand holding the pencil or making the paper slightly curved for a more realistic effect. I also thought of an interesting element I could add, where I may add a “law history” section that can keep track of the previous laws.

Reading Reflection – Week 4

One of the things that frustrates me a lot and is not mentioned in the reading are the air blowers found in public bathrooms. As you might now some of the malls or other public bathrooms for some reason decide to put air blowers instead of paper towels for drying hands. In most cases these blowers can’t detect when we place our hands under and we are left there standing next to to the machine going forwards and backwards with our hands like we are doing some stupid dance choreography. Not to mention how some bathrooms have very strong blowers which will dry my hands faster, but I will go out with a wet shirt. Papers are towels are easier to use, straight forward and do the job much quicker and better than the blowing machines.

In order to avoid my design being hard or unpleasant to use I will apply the following principals to my design. I will make the buttons look clickable and the links underlined or colored differently so it is obvious to the user that button or link is intended for clicking. I will make sure that the user gets immediate response to their interaction of any part of the design and I will place buttons and other interactive objects in places where it makes sense. No hidden menus or buttons which are weirdly colored or hidden so they are barely visible. Some websites don’t do the color matching correctly so the links look like every other word in the sentence and is hard to determine on what to click, I will make sure I don’t do such thing.

Week 4: Data Visualization

Concept

I was going through Kaggle, looking at interesting datasets that I could use to visualize some data. I stumbled upon a dataset about “IMDB Top 250 Movies Dataset” and decided to give it a look. After looking through the dataset I became interested to how the budget the movie had initially gotten corelates to the Box-office revenue it received so I decided to make a graph using that data and present it using p5js.

The project might have a simple look, but I believe the data that it shows and the results are quite interesting.

Process

For the process I first looked at the dataset on my computer, trying to find interesting data that I could present visually. After finding the budget and the box office values I then loaded them into the p5js and first printed a few values just to see if the dataset works. Then came the process of actually pulling all the data and plotting it on the preview. This process was a bit tricky as I had to play around with the map function to understand it completely and make the graph look how it should. I am proud of the way I found mins and maxes and the way I mapped them.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// Getting the minimums and maximums, by pulling only the budget or only the boxOffice data
let minBudget = min(movieData.map((m) => m.budget));
let maxBudget = max(movieData.map((m) => m.budget));
let minBoxOffice = min(movieData.map((m) => m.boxOffice));
let maxBoxOffice = max(movieData.map((m) => m.boxOffice));
//Maping and placing the data
for (let movie of movieData) {
let x = map(movie.budget, minBudget, maxBudget, 50, width - 50);
let y = map(movie.boxOffice, minBoxOffice, maxBoxOffice, height - 50, 50);
fill(0, 255, 0);
ellipse(x, y, 5, 5);
}
// Getting the minimums and maximums, by pulling only the budget or only the boxOffice data let minBudget = min(movieData.map((m) => m.budget)); let maxBudget = max(movieData.map((m) => m.budget)); let minBoxOffice = min(movieData.map((m) => m.boxOffice)); let maxBoxOffice = max(movieData.map((m) => m.boxOffice)); //Maping and placing the data for (let movie of movieData) { let x = map(movie.budget, minBudget, maxBudget, 50, width - 50); let y = map(movie.boxOffice, minBoxOffice, maxBoxOffice, height - 50, 50); fill(0, 255, 0); ellipse(x, y, 5, 5); }
// Getting the minimums and maximums, by pulling only the budget or only the boxOffice data
let minBudget = min(movieData.map((m) => m.budget));
let maxBudget = max(movieData.map((m) => m.budget));
let minBoxOffice = min(movieData.map((m) => m.boxOffice));
let maxBoxOffice = max(movieData.map((m) => m.boxOffice));

//Maping and placing the data
for (let movie of movieData) {
  let x = map(movie.budget, minBudget, maxBudget, 50, width - 50);
  let y = map(movie.boxOffice, minBoxOffice, maxBoxOffice, height - 50, 50);
  fill(0, 255, 0);
  ellipse(x, y, 5, 5);
}
Reflection and Future improvements

For the future improvements I would maybe want to find a bigger dataset and try to plot more movies into the existing one and see what the difference it makes. Maybe I could also incorporate allowing user to tweak what other “filters” are present to see what maybe affects the budget to box office revenue difference in movies. Overall I found this project very interesting and challenging, but at the same time tons of fun!

Week 4 – Reading Response

Faucets, soap dispensers, and towel dispensers in public restrooms can be really frustrating. One reason is because of the uptick in automatic dispensers and sinks. Sometimes, faucets look like they’re automatic but are really operated by handles, and same thing goes for soap/towel dispensers. Another frustrating point is when soap dispensers look like faucets. I also once saw an air/hand dryer, soap dispenser, and faucet all with the same color, build, and shape surrounding a sink; the only distinguishing factor was their size. I had to test out all of them to figure out which one was which.

Don Norman says, “The same technology that simplifies life by providing more functions in each device also complicates life by making the device harder to learn, harder to use. This is the paradox of technology and the challenge for the designer”, which I thought was interesting. The designer has to make complicated information easily digestible. Designers are like the middlemen between new technology and users.

I also think the point about having to spell out a function or affordance for users with words is poor design is compelling, but also very difficult to get right. Making designs intuitive is the ultimate goal, but the thing about intuition is that you don’t consciously think about it, so designers can’t know immediately what it intuitive. Too often, I personally lean towards words to let people know what a design does. However, I need to get more used to designing without words and simply use visual or physical cues to guide a user’s attention.

Don Norman’s main idea about how people aren’t at fault for poor design is also very important. It’s up to designers, engineers, manufacturers, and businesses to create a pleasant user experience; if a user isn’t enjoying their product, it’s not the user’s fault. Too often, experts are biased in their own highly skilled perspective that they expect others to be on that level. For example, sometimes when I’m teaching someone a skill like crochet, I see the stitches and shapes very easily, but they can’t. If I were to design a beginner’s crochet kit or tutorial, I need to take into account the average beginner’s perspective.

I really liked how Don Norman distinguishes between affordances and signifiers, indicating that affordances are relationships between people and designs, and signifiers are physical attributes that lend to discovering affordances. Distinguishing them helps designers understand what they’re working towards and how to work towards it.

Week 3 – Assignment

Introduction: Inspiration and Thought Process

When approaching this project, I wanted to create something that felt organic, dynamic, and visually engaging while staying true to my interest in systems, patterns, and movement. I’ve always been fascinated by the hidden structures that govern the natural world—whether it’s the way air currents shape cloud formations, how magnetic fields interact with charged particles, or how fluid dynamics influence ocean currents. These invisible forces dictate movement and structure on both microscopic and massive scales, yet they often go unnoticed in daily life.

This fascination led me to explore generative art as a way to reveal these hidden forces. By using a flow field generated through Perlin noise, I aimed to simulate an abstract yet realistic movement of particles through a force-driven system. The goal was to make the movement feel both unpredictable and structured—like a balance between chaos and order, mirroring how natural systems operate.

Another reason this concept resonated with me is my interest in interactive media and computational design. I see creative coding as a bridge between logic and aesthetics—using algorithms not just to solve problems but to create emotionally engaging experiences. This project became a way to explore how simple rules (vector fields and movement constraints) can lead to complex, emergent behaviors.

How I Decided on the Approach

Initially, I considered different ways of visualizing movement:

  • Cellular automata (which follows a discrete rule set)
  • Particle systems with basic physics (which simulate real-world gravity and collisions)
  • Algorithmic drawing techniques (such as recursive fractals)

However, I specifically wanted smooth, flowing movement, where particles appear to drift through an unseen force field rather than follow rigid, predictable patterns. This led me to research flow fields, a technique often used in generative art to create dynamic motion based on vector fields derived from Perlin noise. The key insight was that by giving each particle a force vector at every point in space, I could create an artwork where movement itself became the visual expression.

Connecting to My Interests

This project ties into my broader interest in interactive systems and generative design. In the future, I could see expanding this into an interactive piece, where users could manipulate the flow field in real-time, changing the behavior of the particles with gestures or sound inputs. Additionally, this exploration of emergent patterns aligns with my curiosity about how simple rules can create complexity, something that applies not just to visual art but also to fields like engineering, physics, and artificial intelligence.

Ultimately, this artwork serves as both a study of motion and structure and a reflection of how natural forces shape our world in ways we don’t always perceive.

My code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
let particles = [];
let flowField;
let cols, rows;
let scl = 20; // Scale of the grid
let zOff = 0; // Noise offset for animation
function setup() {
createCanvas(600, 600);
cols = floor(width / scl);
rows = floor(height / scl);
flowField = new Array(cols * rows);
// Create particles
for (let i = 0; i < 500; i++) {
particles.push(new Particle());
}
}
function draw() {
background(0, 10); // Faint trail effect
// Generate the flow field using Perlin noise
let yOff = 0;
for (let y = 0; y < rows; y++) {
let xOff = 0;
for (let x = 0; x < cols; x++) {
let index = x + y * cols;
let angle = noise(xOff, yOff, zOff) * TWO_PI * 4;
let v = p5.Vector.fromAngle(angle);
flowField[index] = v;
xOff += 0.1;
}
yOff += 0.1;
}
zOff += 0.01;
// Update and display particles
for (let particle of particles) {
particle.follow(flowField);
particle.update();
particle.edges();
particle.show();
}
}
// Particle class
class Particle {
constructor() {
this.pos = createVector(random(width), random(height));
this.vel = createVector(0, 0);
this.acc = createVector(0, 0);
this.maxSpeed = 2;
this.color = color(random(255), random(255), random(255), 100);
}
follow(vectors) {
let x = floor(this.pos.x / scl);
let y = floor(this.pos.y / scl);
let index = x + y * cols;
let force = vectors[index];
this.applyForce(force);
}
applyForce(force) {
this.acc.add(force);
}
update() {
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed);
this.pos.add(this.vel);
this.acc.mult(0);
}
edges() {
if (this.pos.x > width) this.pos.x = 0;
if (this.pos.x < 0) this.pos.x = width;
if (this.pos.y > height) this.pos.y = 0;
if (this.pos.y < 0) this.pos.y = height;
}
show() {
stroke(this.color);
strokeWeight(2);
point(this.pos.x, this.pos.y);
}
}
let particles = []; let flowField; let cols, rows; let scl = 20; // Scale of the grid let zOff = 0; // Noise offset for animation function setup() { createCanvas(600, 600); cols = floor(width / scl); rows = floor(height / scl); flowField = new Array(cols * rows); // Create particles for (let i = 0; i < 500; i++) { particles.push(new Particle()); } } function draw() { background(0, 10); // Faint trail effect // Generate the flow field using Perlin noise let yOff = 0; for (let y = 0; y < rows; y++) { let xOff = 0; for (let x = 0; x < cols; x++) { let index = x + y * cols; let angle = noise(xOff, yOff, zOff) * TWO_PI * 4; let v = p5.Vector.fromAngle(angle); flowField[index] = v; xOff += 0.1; } yOff += 0.1; } zOff += 0.01; // Update and display particles for (let particle of particles) { particle.follow(flowField); particle.update(); particle.edges(); particle.show(); } } // Particle class class Particle { constructor() { this.pos = createVector(random(width), random(height)); this.vel = createVector(0, 0); this.acc = createVector(0, 0); this.maxSpeed = 2; this.color = color(random(255), random(255), random(255), 100); } follow(vectors) { let x = floor(this.pos.x / scl); let y = floor(this.pos.y / scl); let index = x + y * cols; let force = vectors[index]; this.applyForce(force); } applyForce(force) { this.acc.add(force); } update() { this.vel.add(this.acc); this.vel.limit(this.maxSpeed); this.pos.add(this.vel); this.acc.mult(0); } edges() { if (this.pos.x > width) this.pos.x = 0; if (this.pos.x < 0) this.pos.x = width; if (this.pos.y > height) this.pos.y = 0; if (this.pos.y < 0) this.pos.y = height; } show() { stroke(this.color); strokeWeight(2); point(this.pos.x, this.pos.y); } }
let particles = [];
let flowField;
let cols, rows;
let scl = 20; // Scale of the grid
let zOff = 0; // Noise offset for animation

function setup() {
  createCanvas(600, 600);
  cols = floor(width / scl);
  rows = floor(height / scl);
  flowField = new Array(cols * rows);

  // Create particles
  for (let i = 0; i < 500; i++) {
    particles.push(new Particle());
  }
}

function draw() {
  background(0, 10); // Faint trail effect

  // Generate the flow field using Perlin noise
  let yOff = 0;
  for (let y = 0; y < rows; y++) {
    let xOff = 0;
    for (let x = 0; x < cols; x++) {
      let index = x + y * cols;
      let angle = noise(xOff, yOff, zOff) * TWO_PI * 4;
      let v = p5.Vector.fromAngle(angle);
      flowField[index] = v;
      xOff += 0.1;
    }
    yOff += 0.1;
  }
  zOff += 0.01;

  // Update and display particles
  for (let particle of particles) {
    particle.follow(flowField);
    particle.update();
    particle.edges();
    particle.show();
  }
}

// Particle class
class Particle {
  constructor() {
    this.pos = createVector(random(width), random(height));
    this.vel = createVector(0, 0);
    this.acc = createVector(0, 0);
    this.maxSpeed = 2;
    this.color = color(random(255), random(255), random(255), 100);
  }

  follow(vectors) {
    let x = floor(this.pos.x / scl);
    let y = floor(this.pos.y / scl);
    let index = x + y * cols;
    let force = vectors[index];
    this.applyForce(force);
  }

  applyForce(force) {
    this.acc.add(force);
  }

  update() {
    this.vel.add(this.acc);
    this.vel.limit(this.maxSpeed);
    this.pos.add(this.vel);
    this.acc.mult(0);
  }

  edges() {
    if (this.pos.x > width) this.pos.x = 0;
    if (this.pos.x < 0) this.pos.x = width;
    if (this.pos.y > height) this.pos.y = 0;
    if (this.pos.y < 0) this.pos.y = height;
  }

  show() {
    stroke(this.color);
    strokeWeight(2);
    point(this.pos.x, this.pos.y);
  }
}

 

Week 4 – Data Visualization

Link to sketch: https://editor.p5js.org/bobbybobbb/full/rBBWMFyxx

When brainstorming for this project, I wanted to represent data in a way unique to the dataset. I wanted to use what the data was about and frame it in a visually engaging way that best represented what it was about. I was digging through Kraggle and found a simple dataset about streaming platforms, so I thought it’d be cool to represent it inside a TV and the glitchy effects of a TV screen. Each bar of glitch/color is proportional to the percentage of shows or movies the streaming platform has compared to the others. Since there were two sets of data, I created buttons on the TV to toggle between them; I really liked how the functionality of the system was tied in to the visual cohesion of the piece. The colors for the glitches are also randomized, so each time you click the buttons, the colors will change regardless of whether or not the dataset changed.

Some challenges I encountered included not being able to pass in arguments to a function I call when the buttons are pressed. To overcome it, I found a way to change the mousePressed function:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
showsButton.mousePressed( function(){
displayData(2);
});
showsButton.mousePressed( function(){ displayData(2); });
showsButton.mousePressed( function(){
  displayData(2);
});

In the future, I want to make this piece more engaging because it feels a bit more static right now. Maybe users can click on the specific streaming platform and learn more about it. Or I can find more data on these platforms and users can see even more data visualization upon clicking each individual platform. Overall, this project came with a lot of testing and looking for datasets. I had to frequently test the spacing of the rectangular bars used to represent each streaming platform, text rotation, and button sizing. There was also a lot of math involved for turning the values in the dataset into rectangles that fit within a confined space.

Reading Reflection – Week #4

In The Design of Everyday Things by Don Norman, the main argument is that usability issues stem from poor design rather than user error. This challenges the common assumption that people are to blame when they struggle with everyday objects. Come to think of it, well-designed objects should naturally guide users, minimizing confusion.

One example of poor design that was not mentioned in the reading but has always frustrated me are cable, especially USB ones. The traditional USB connector can only be inserted one way, yet there is rarely a clear indication of which side is correct. This often leads to flipping the plug multiple times before it fits. A simple signifier like a physical marker or a visible point, could solve this issue and make the interaction effortless.

Norman’s principles are also highly relevant to interactive media. Websites and apps often suffer from unclear navigation, hidden menus, or buttons that don’t look clickable. Applying affordances and signifiers like distinct buttons and clear labels would improve usability. Similarly, feedback is important as when users submit a form or click a link, they should receive a confirmation to avoid uncertainty.