Assignment #4 – New Jeans by NewJeans

For this assignment, I wanted to do something involving my favorite musical band called NewJeans. I decided to use my favorite quote of theirs “New hair, New tee, NewJeans. You and me.” Which they repeat twice. The repetition of the phrase “New hair New tee / NewJeans” is followed by “You & me”, suggesting that the speaker is extending an invitation to the listener to join them in this journey of transformation and self-discovery. I decided to put my everlasting love for musical games into use; I wanted to create something simple. I wanted simply a phrase where I could play the song and click on this at the same time.

For my code, I faced issues with getting the phrase to repeat after it’s done, but chatGPT helped me figure that out by using % in the mouseClicked(); function.

function mouseClicked() {
    currentIndex = (currentIndex + 1) % phrases.length;
}

 

Reflection:

I am honestly very proud of this piece but I would like to someday develop a rhythm game that I could play using my favorite songs.

Raya Tabassum: Reading Response 3

“The Psychopathology of Everyday Things” lays a foundational understanding of how good design should bridge the gap between user experience and functionality.
One intriguing aspect that Norman highlights is the concept of “affordances,” which refers to the perceived and actual properties of an object that determine how it could possibly be used. A door handle, for example, affords pulling, while a push plate suggests pushing. This concept raises questions about how well the design communicates possible actions to users and how intuitive these actions are. It leads one to ponder: How many everyday frustrations are due to poor design rather than user error?
Norman also introduces the idea of “signifiers,” signals that communicate where the action should take place. This is particularly interesting when considering interactive media, where the interface must clearly communicate how to interact with digital environments. These concepts beg the question of how digital interfaces can be designed to be more intuitive and reduce the cognitive load on the user.
“Good design makes a product understandable” – it encapsulates the essence of user-centered design—making the purpose of an object or interface self-evident. Consider the evolution of smartphone interfaces. Early smartphones often required users to navigate through multiple menus to perform simple tasks. Modern smartphones, however, have refined their interfaces to be more intuitive, using design principles like those Norman discusses. Icons are designed with affordances and signifiers in mind, making actions like deleting an app or finding settings more intuitive. This evolution showcases the impact of good design on everyday technology and its role in enhancing user experience.

How can we, as future designers, ensure that our creations are not just functional but also joyous to interact with? How can we minimize frustration and maximize satisfaction? That are the questions it’s high time we ask ourselves.

Afra Binjerais – reading response 4

This week’s reading has been incredibly enlightening, offering valuable insights into the realm of interaction and design. It prompted me to reconsider the intricacies of design processes and their impact on user experience. The discussion on the challenges of everyday interactions, particularly with objects like doors, emphasized the pivotal role of effective design in usability. The concept of “Norman doors” sheds light on the common struggle users face in navigating poorly designed interfaces, a challenge I’ve personally encountered.

Similar to the confusion of push and pull doors, I also get confused every time I try to open my curtains. It annoys me when I pull the curtain string to open and it gets closer even further instead.

the white curtain string, you need to pull one (I don’t know which till this day ;)) to open or close the curtain

Through engaging anecdotes and examples, the reading emphasized the importance of discoverability and understanding in design, advocating for intuitive products that require minimal instruction. One aspect that stood out to me and that I believe is crucial to keep in mind for my future career in IM is the exploration of human-centered design and its integration of psychology and technology. Understanding how to prioritize human needs, capabilities, and behavior in design solutions is paramount, as it ensures products are not only aesthetically pleasing but also functional and user-friendly. This insight is something I find both intriguing and essential to carry forward as I pursue my career in IM.

Raya Tabassum: Generative Text Assignment

Concept:

This kinetic typography transforms static text into an interactive visual display. By treating each point of the font’s letters as a vehicle, the sketch brings the text “Dream” to life, allowing it to respond dynamically to the viewer’s mouse movements. Vehicles “arrive” at their designated spots to form the letters of the word and “flee” when the mouse comes close, creating an engaging effect that feels both chaotic and ordered. The addition of the gradient background adds depth and visual interest, making the typography a part of an aesthetically pleasing composition of a sunset.

Use your mouse to go through the word to interact with it:

Font Points Extraction and Vehicle Initialization:

//Extract points from the font
let points = font.textToPoints(textString, 75, 320, fontSize, {
  sampleFactor: 0.1
});

//Initialize vehicles for each point
for (let i = 0; i < points.length; i++) {
  let pt = points[i];
  let vehicle = new Vehicle(pt.x, pt.y);
  vehicles.push(vehicle);
}

Extracting points from text and converting them into “vehicles” was a bit complex due to the need to handle font rendering and point manipulation. The textToPoints() function is used to get the vector points for each letter, which are then used to create vehicle objects that simulate motion.

Also for the Vehicle class, implementing behaviors such as “arrive” and “flee” required understanding of steering behaviors and force accumulation in a physics-based simulation. Balancing these forces to achieve smooth and natural movement was challenging, especially when trying to simulate both attraction to a target point and repulsion from the mouse cursor.

Full code:

//Preload the font
let font;
let vehicles = []; //Array to hold the 'vehicle' objects

function preload() {
  //Load the font from the assets
  font = loadFont('Hogfish DEMO.otf'); 
}

function setup() {
  createCanvas(700, 500); //Set up the canvas
  //Create a background gradient
  setGradient(0, 0, width, height, color('#EBC249'), color('#A52D56'), Y_AXIS);

  //Define the text properties
  let textString = 'Dream';
  let fontSize = 180;
  //Convert the text to a series of points
  let points = font.textToPoints(textString, 75, 330, fontSize, {
    sampleFactor: 0.1 //Determines the density of the points
  });

  //Create a vehicle object for each point
  for (let i = 0; i < points.length; i++) {
    let pt = points[i];
    let vehicle = new Vehicle(pt.x, pt.y);
    vehicles.push(vehicle);
  }
}

function draw() {
  //Refresh the gradient background each frame
  setGradient(0, 0, width, height, color('#EBC249'), color('#A52D56'), Y_AXIS);

  //Update and display each vehicle
  for (let i = 0; i < vehicles.length; i++) {
    let v = vehicles[i];
    v.behaviors();
    v.update();
    v.show();
  }
}

//Constants for gradient direction
const Y_AXIS = 1;
const X_AXIS = 2;

//Function to create a gradient background
function setGradient(x, y, w, h, c1, c2, axis) {
  noFill();

  //Create a vertical gradient
  if (axis === Y_AXIS) {
    for (let i = y; i <= y + h; i++) {
      let inter = map(i, y, y + h, 0, 1);
      let c = lerpColor(c1, c2, inter);
      stroke(c);
      line(x, i, x + w, i);
    }
  } 
  //Create a horizontal gradient
  else if (axis === X_AXIS) {
    for (let i = x; i <= x + w; i++) {
      let inter = map(i, x, x + w, 0, 1);
      let c = lerpColor(c1, c2, inter);
      stroke(c);
      line(i, y, i, y + h);
    }
  }
}

//The Vehicle class
class Vehicle {
  constructor(x, y) {
    this.pos = createVector(random(width), random(height)); // Start position
    this.target = createVector(x, y); //Target position
    this.vel = p5.Vector.random2D(); //Initial velocity
    this.acc = createVector(); //Acceleration
    this.r = 8; //Radius
    this.maxspeed = 10; //Maximum speed
    this.maxforce = 1; //Maximum steering force
  }

  //Combine behaviors
  behaviors() {
    let arrive = this.arrive(this.target);
    let mouse = createVector(mouseX, mouseY);
    let flee = this.flee(mouse);

    arrive.mult(1);
    flee.mult(5);

    this.applyForce(arrive);
    this.applyForce(flee);
  }

  //Apply a force to the vehicle
  applyForce(f) {
    this.acc.add(f);
  }

  //Update the vehicle's position
  update() {
    this.pos.add(this.vel);
    this.vel.add(this.acc);
    this.acc.mult(0); //Reset acceleration each frame
  }

  //Display the vehicle
  show() {
    stroke(255);
    strokeWeight(8);
    point(this.pos.x, this.pos.y);
  }

  //Steer the vehicle towards a target
  arrive(target) {
    let desired = p5.Vector.sub(target, this.pos); //A vector pointing from the position to the target
    let d = desired.mag();
    let speed = this.maxspeed;
    if (d < 100) {
      //Adjust speed based on distance to the target
      speed = map(d, 0, 100, 0, this.maxspeed);
    }
    desired.setMag(speed);
    let steer = p5.Vector.sub(desired, this.vel);
    steer.limit(this.maxforce);
    return steer;
  }

  //Make the vehicle flee from the mouse
  flee(target) {
    let desired = p5.Vector.sub(target, this.pos);
    let d = desired.mag();
    if (d < 50) {
      desired.setMag(this.maxspeed);
      desired.mult(-1); //Go in the opposite direction
      let steer = p5.Vector.sub(desired, this.vel);
      steer.limit(this.maxforce);
      return steer;
    } else {
      return createVector(0, 0); //No force if the mouse is far away
    }
  }
}

 

Assignment #4 – Stefania Petre

For this week’s assignment I decided to do aa text with an interactive part.

First, I did the sketch and put the text in. I have to admit, it was difficult to choose the background color because I wanted something that would suit every single random color generated when you press the button. At first I thought of a beige, sand color but it did not look right. So, I decided to stick with black.

After that, I created a function for the mouse interaction.

I have to admit, I did not have much time to do this but this is the end result! All in all, I am pretty proud of my improvement on coding giving the fact that I started 4 weeks ago.

For the future, I want to figure out how to use other fonts as well.

 

Reading Reflection – #4 Stefania Petre

The banality of evil design is everywhere. Don Norman’s argument is trying to prove that there should be thought behind every new idea. On top of that, there is also a need for some boxes to be checked before coming out with a new product.

This first chapter of his work reminded me of the book ‘Universal Principles of Graphic Design’ by Jill Butler and how there are certain instructions when it comes to good design.

Since my arrival at NYUAD in August, I have encountered several instances of design oversights within the campus environment. For instance, the positioning of football court seats on the incorrect side of the field exposes them to relentless sunlight, diminishing their utility and comfort. Similarly, the placement of the alarm button adjacent to the toilet flush button presents a comical yet concerning scenario, where inadvertent activation could disrupt the tranquility of the Arts Center.

All in all, I believe that good designers think ten times before coming out with a product. It is better to think twice at first than having to deal with redesigning it over and over again.

Reading Response Week 4

After delving into the first chapter of Don Norman’s “The Design of Everyday Things,” I find myself resonating deeply with his emphasis on the significance of understanding human behavior and psychology in design. Norman’s argument about the importance of putting ourselves in the shoes of users resonates with my own approach to design. I firmly believe that creating anything without considering the end user’s perspective is futile. Design should always prioritize usability and functionality to ensure a seamless interaction between users, systems, and designers.

Norman’s discussion on the paradox of technology also caught my attention, particularly his insight into how experiences shape users’ perceptions of interactions. It serves as a reminder that even the most aesthetically pleasing designs must prioritize functionality and user experience above all else. This resonates with me as I reflect on instances where overly complex features have hindered rather than enhanced my experience with products.

Moreover, Norman’s critique challenges the prevailing notion that more features equate to better functionality. It prompts me to reconsider what truly defines a good design and the balance between form, complexity, simplicity, and functionality. As I continue to contemplate Norman’s insights, I aim to adopt a dual perspective—as both a user and a designer—to ensure that my designs are not only visually appealing but also intuitive and user-friendly. Norman’s work serves as a valuable guide for navigating the complexities of design and human interaction, prompting me to strive for designs that enhance users’ lives without adding unnecessary complexity.

Assignment 4: Generative Text Output

Concept

The concept I aimed to replicate the captivating streams of 1s and 0s that are frequently shown in movies or GIFs, which represent the fundamentals of digital computing and communication. I wanted to achieve something similar to seeing a complex dance of binary digits, therefore I represented these streams with random characters.

Inspiration 

Sketch


Code

function draw() {
  background(0); 
  
  // Display and animate characters
  for (let x = 0; x < cols; x++) {
    for (let y = 0; y < rows; y++) {
      let yOffset = (millis() * speed + x * 50 + y * 50) % (height + 200) - 100;
      
      if (grid[x][y].bright) {
        // Set bright neon blue color for highlighted characters
        fill(0, 255, 255); 
      } else {
        // Set light neon blue color for other characters
        fill(0, 150, 255); 
      }
      
      text(grid[x][y].char, x * charSize, y * charSize + yOffset);
    }
  }
}

In the draw() method, I have a nested loop that iterates over each cell of the 2D grid array. The location of the characters are calculated and its appearance based on its coordinates and a time-based offset (yOffset). This offset is computed given the cell coordinates, a predetermined speed value, and the current value of millis(), which indicates the milliseconds since the sketch began operating.

if (grid[x][y].bright) {
        // Set bright neon blue color for highlighted characters
        fill(0, 255, 255); 
      } else {
        // Set light neon blue color for other characters
        fill(0, 150, 255); 
      }

Each character’s color is chosen according to the entry that corresponds to it in the grid array. fill() method applies a bright neon blue color to a cell if its bright attribute is set to true. Otherwise, ordinary characters are shown in a lighter neon blue hue.

Full Code

// 2D array to display the characters
let grid;
// the font size of the characters
let charSize = 20;
// columns and rows for the 2D array (grid)
let cols, rows;
// speed of the characters falling
let speed = 0.2;

function setup() {
  print(windowWidth,windowHeight)
  createCanvas(windowWidth, windowHeight);
  
  //creating the 2D array
  cols = floor(width / charSize);
  rows = floor(height / charSize);
  
  grid = create2DArray(cols, rows);
  //  initializing the characters font size 
  textSize(charSize);
  
  // Initialize grid with random characters
  for (let x = 0; x < cols; x++) {
    for (let y = 0; y < rows; y++) {
      grid[x][y] = {
        // calling the characters randomly      
        char: randomChar(),
        // Randomly determine if the character should be brighter or not
        bright: random(1) > 0.8 
      };
    }
  }
}

function draw() {
  background(0); 
  
  // Display and animate characters
  for (let x = 0; x < cols; x++) {
    for (let y = 0; y < rows; y++) {
      let yOffset = (millis() * speed + x * 50 + y * 50) % (height + 200) - 100;
      
      if (grid[x][y].bright) {
        // Set bright neon blue color for highlighted characters
        fill(0, 255, 255); 
      } else {
        // Set light neon blue color for other characters
        fill(0, 150, 255); 
      }
      
      text(grid[x][y].char, x * charSize, y * charSize + yOffset);
    }
  }
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  cols = floor(width / charSize);
  rows = floor(height / charSize);
  
  grid = create2DArray(cols, rows);
  
  // Reinitialize grid with random characters
  for (let x = 0; x < cols; x++) {
    for (let y = 0; y < rows; y++) {
      grid[x][y] = {
        char: randomChar(),
        // Randomly determine if the character should be brighter or not
        bright: random(1) > 0.8 
      };
    }
  }
}

// function to create the 2D array grid
function create2DArray(cols, rows) {
  let arr = new Array(cols);
  for (let i = 0; i < arr.length; i++) {
    arr[i] = new Array(rows);
  }
  return arr;
}

// function to generate a random character
function randomChar() {
  return String.fromCharCode(floor(random(65, 91)));
}

 

Challenges

The significant challenge was how to keep the characters’ animation in a fluid and synced motion along with the shifting grid placements while maintaining readability and visual consistency.

Another challenge was assigning different brightness levels to different characters. This required careful coordination to make sure the highlighted characters shone out without overshadowing other characters or creating visual clutter.

Improvements

There is one improvement that I would like to implement in the future. I would want to improve the animation algorithm’s efficiency that may result in more fluid and flawless visual transitions, particularly when working with bigger grids or faster animation rates.

Another improvement could be the inclusion of user interactivity. The user could disrupt the falling characters using mouse hover and the characters trying to get back into the original stream.

Week 3: [Data Viz] Some sort of data visualization

Below is the p5 sketch.

Conceptualization

Pi’s Some sort of data visualization is literally some sort of data visualization and trying to remove things that are not necessary. Inspired by Saturay Morning Breakfast Cereal, this data shows true, but useless facts.

2) ⚙️ Technical Plan of Attack & Implementation

Once we get the data, drawing the bar is just defining some parameters and working with the rectangles accordingly.

  // Calculate dynamic dimensions
  let padding = 200; 
  let graphWidth = width - 2 * padding;
  let barWidth = graphWidth / data.length; 
  let colors = []; // Array to hold the bar colors
  for (let i = 0; i < data.length; i++) {
    colors.push(color(255, 105 + i * 10, 0)); // Gradually changing the color
  }
  // Draw the bars
  for (let i = 0; i < data.length; i++) {
    fill(colors[i]);
    noStroke();
    rect(padding + i * barWidth, height - padding - data[i] * barWidth, barWidth - 1, data[i] * barWidth);
  }
// ... and so on

I could have loaded from the csv file, but the data is small enough.

3) 🎨 Artistic Plan of Attack & Implementation

Just to keep things not boring, I played with some automatic orange gradient for the bar colors by using

  let colors = []; // Array to hold the bar colors
  for (let i = 0; i < data.length; i++) {
    colors.push(color(255, 105 + i * 10, 0)); // Gradually changing the color
  }

4) 💪 Challenges

No challenge.

5) 💡 Potential Improvements

No further improvements are needed, I need to learn to restrain yourself.

6) 🖥️ Source code

🖥️ Source code is just a single sketch.js file at : https://github.com/Pi-31415/Intro-To-IM/blob/main/Assignment-4/sketch.js

📖 References :

Week 4 : Breastmilk, flies and piano stairs – Pi’s Top Human-Centered Design Examples

“The problem with the designs of most engineers is that they are too logical.”

😱 Ouch ouch! Don Norman’s quote above from “The Psychopathology of Everyday Things” was harsh enough to get my blood boiling. Despite feeling personally attacked, both the devil and the angel on my shoulders say “Wait, wait, he has got a point”. I fully join Don in standing ovation for his idea of Human-Centered Design. When I wrote in my last post “The good design speaks for itself, the learning curve is so smooth such that the users enlightens themselves without any guidance and hitting F1 for user manuals.” I was saying exactly the same points. Discoverability is a vital concept… the user should be able to discover how the thing works, without it being explicitly stated… and how do you mainly achieve this? Nudges!! Although Don has not mentioned it in Chapter 1, I would like to highlight the Nudge Theory to the rescue… and some examples.

The Nudge Theory

I don’t have a human kid, but I know for a fact that at one point, they have to stop breast milk 🍼 and start to eat actual solid food 🍗. This process is called weaning and back home, they start to train babies to stop feeding on breast milk around 6 months to 1 year of age. Like cocaine addicts with withdrawal symptoms, the babies will cry endlessly and become super desperate whenever they come into close contact with their mother… then these little zombies will reach out for the breast.

[Image Source]

This behavior has to change, of course. Back home, they have a traditional method of weaning… where you literally “spice 🌶️ things up”  by putting turmeric powder on the mother’s nipples so that when the baby gets its breastmilk next time, it goes “What the blistering barnacles?” with eyes popping out 😳. Next time, it learnt its lesson… “Chicken wings are tastier than breastmilk from now on”.

[Turmeric Powder – Source]

Cruel, effective, spicy…🔥

Woah woah Pi, how is this spice powered weaning method related to Human-Centered Design?

Wait wait, I am just explaining the idea of a “nudge theory”.

This is an example of nudge theory in action – a nudge is a gentle push towards a desirable behavior without any force or mandate. Here, the baby discovers on its own that it should switch from breastmilk to chicken by itself.

Don Norman’s discoverability in action!

In similar, but less spicy ways, the nudges can be applied to aid discoverability in a lot of human centered designs, to gaslight the humans into figuring stuff out on their own. In the rest of the post, I would like to share 3 of my favorite examples of this discoverability in action.

Applying Nudge Theory to Everyday Design

Flies 🪰

My personal favorite of all time solves the age-old problem of men’s restrooms: the messy urinal area. The aftermath is a nightmare for anyone tasked with cleanup. But here comes the nudge solution, as simple as it is ingenious.

A tiny sticker of a fly, or sometimes a target, is placed strategically in the urinal. It’s almost laughable how such a small thing can redirect a grown man’s attention. Yet, it works!

Men, either out of amusement or subliminal inclination, aim at the sticker.

The result? A cleaner urinal area, less spillage, and a sigh of relief from janitors everywhere.
It’s fun, it’s effective, and the best part? It doesn’t need a user manual or a ‘how-to’ guide. Men just get it, and they go along with it, often without even realizing they’re being nudged into better behavior.

World’s Deepest Bin 🗑️

Traditional bins are all but invisible to the average person. Enter the world’s deepest bin – not literally the deepest, but it sure sounds like it.

The nudge here is a bin that, when used, emits a humorous, exaggerated deep sound. It’s like dropping a piece of trash into a never-ending well. The sound is so unexpected, so comically over the top, that it draws people in. The result is as effective as it is entertaining: people actually look for things to throw away just to hear that sound again.

It turns an ordinary act of disposing of trash into a mini-adventure. And just like that, littering is reduced.

People are engaged, amused, and more importantly, they are nudging themselves and others to keep the surroundings clean.

Piano Stairs 🎹

The last example is a delightful play on human nature’s love for music: the piano stairs. The problem is clear: given the choice, most people opt for escalators or elevators, shunning the stairs, missing out on an easy opportunity for some physical activity.

The nudge solution? Transform a staircase next to an escalator into a giant working piano. Each step is a piano key that makes a sound when you step on it. The result is magical. People are drawn to the stairs, curious and excited. They hop, skip, and jump on the stairs, creating music as they go. What was once a mundane climb turns into a playful experience.

People actually go out of their way to use the stairs, sometimes repeatedly.

It’s human-centered design at its most whimsical and effective.

Conclusion

In each of these examples, the key factor is the design’s ability to communicate and guide behavior without explicit instructions. The fly in the urinal doesn’t need a sign explaining what to do. The World’s Deepest Bin doesn’t have a manual on how to use it. Piano Stairs don’t come with a user guide. They work because they tap into human instincts and make the desired action the more appealing choice. This is the essence of human-centered design – creating solutions that are so in tune with human behavior and needs that they guide us subtly towards better habits.