Week 4 Reading Response – Saeed Lootah

I personally have not always thought much about the appliances or objects we always interact with even though I sometimes get annoyed by them so when going through the chapter I began to think more about the things I use on a day-to-day basis. Moreover, the beginning of the chapter outlines a philosophy which I have started hearing more of today: Human Centered Design. In my last semester I believe it came up in one of my classes, I am personally surprised that it didn’t exist until recently because I always imagined that designers (anyone that designed anything to be specific) always had the person at the center but what’s new is that designers are accounting for the worst possible mistakes or misunderstandings to best “foolproof” their work.

By the end of the chapter I began to think about two things. How have designers or the discipline of design in general changed since this book has been published. I ask this because as I’m reading it sometimes feel obvious and maybe thats because it has become more ingrained into the culture or perhaps it’s obvious when its spelled out. Then my second thought was about a recent product. The Apple vision pro, which I’m sure almost everyone has heard of by this point, uses the senses in a way which comes naturally to people whereas before with other virtual reality headsets people would have to be taught or spend more effort learning. It made me consider how sometimes a designer might approach a problem from the perspective of how can we make it with the tools we have already or some designers might approach a problem with the perspective of what tools do we have to make the product we should. Maybe I didn’t explain myself very well but thats what came to mind.

 

 

Reading Reflection #4

Don Norman presents a key idea in “The Design of Everyday Things,” which is feedback in design. According to Norman, feedback is a means of informing the user of the outcomes of an action. He uses commonplace examples to demonstrate this, such as sitting at a traffic light without seeing any indication that the system has spotted your automobile, or pushing buttons on an elevator without knowing if the elevator is on its way. This idea emphasizes how crucial it is to provide users with prompt, understandable feedback so they may be assured that their action has been recorded and is being handled. Ineffective feedback can cause consumers to feel doubtful, angry, or confused, which can make them dislike the system or product.

When I think about it, this idea has really changed the way I think about user interface and design. I can think of several instances where I kept pressing buttons on gadgets or user interfaces and got no reaction. I’ve always found this experience disconcerting because I’m not sure if my activities were acknowledged. I completely agree with Norman’s assessment on the importance of receiving feedback that is both clear and fast. It draws attention to a prevalent problem found in many designs and emphasizes how crucial it is to include transparent feedback methods in order to increase usability and user happiness. This understanding highlights the vital role feedback plays in enabling successful human-machine interactions, and it motivates me to examine designs more closely, both those I work with on a daily basis and those I might develop.

Week 4 Readings – Norman Doors

Ah yes, should I pull or should I push this door? From the image, we can already tell that something is off with the door. The sign says to pull the door, yet the handle is flat. These doors are commonly referred to as Norman Doors, introduced by Donald A. Norman in his book we read this week.

When designing something, it is always best to remember the target audience. Most object designs require human senses as an input to be used. While this does sound able-ist, we should also ask ourselves the question: How would this object be used for those who require more assistance? 

People will always seek the path of least resistance. An intuitive design is always good. We can measure how good a design is by simply using our senses. If it feels ‘natural’ to use, as if it is part of our body, it means the object is well designed. Otherwise, if we stop to think about how to use the object, that means it is redundant.

I believe that the concept of affordances Norman wants us to embed in our minds is this: As a designer, we need to put ourselves in the shoes of the audience. Designers can impact the lives of its users, be it for good, or for the worse. Being able to distinguish the holes or problems in the experience of our design is an important aspect to always remember.

Assignment 4 (production 4) Word Search

The concept of this assignment is a word search. I was inspired to do this because of how much I help my younger brother with his word search activities at home. So I immediately started working on the idea.

I started y creating a grid and then have randomized letters in the grid. There are three specific words that you need to find: “WOW” “FUN” “CAT”. Obviously there are more extra and bonus words that you will find in the grid. The process was long but this is what I ended up with. Please mouse click on the letter that you want to highlight:

A big part of the code that I am proud, which was the most challenging part is the WordGrid Class that I created to have many different functions.

class WordGrid {
  
  
  
    // Constructor 
    constructor(gridSize, cellSize) {
      // Number of cells along one edge of grid 
        this.gridSize = gridSize; 
      // Size of each cell in pixels
        this.cellSize = cellSize; 
        this.words = ['FUN', 'WOW', 'CAT']; 
      // Initialize grid layout
        this.grid = this.initGrid(); 
      // Place words in the grid
        this.placeWords(); 
      // Fill empty spaces in grid
        this.fillGrid(); 
    }

  
  
    // Initializes grid with empty values.
    initGrid() {
      // Array to hold grid data 
        let grid = []; 
      // Iterate over each row 
        for (let i = 0; i < this.gridSize; i++) { 
          // Initialize an empty row
            grid[i] = []; 
          // Iterate over each column in row
            for (let j = 0; j < this.gridSize; j++) { 
      // Set each cell to default state with no letter and not colored
                grid[i][j] = { letter: '-', colored: false };
            }
        }
        return grid; 
    }

  
  
    // Places words from 'words' array into grid 
    placeWords() {
        // Iterate over each word and its index in the array
        this.words.forEach((word, index) => {
    // Calculate row number based on word's index to space out words
            let row = index * 2; 
            // Place each letter of the word into grid.
            for (let i = 0; i < word.length; i++) {
       // Set cell at calculated row and current column to letter of word
                this.grid[row][i] = { letter: word[i], colored: false };
            }
        });
    }

  
  
    // Fills empty cells of grid with random letters
    fillGrid() {
        // Iterate over each cell in grid
        for (let i = 0; i < this.gridSize; i++) {
            for (let j = 0; j < this.gridSize; j++) {
                // Check if cell is empty (marked by '-') 
                if (this.grid[i][j].letter === '-') {
                    // Set the cell to random letter
                    this.grid[i][j].letter = this.getRandomLetter();
                }
            }
        }
    }


  
    // Returns random letter from the alphabet
    getRandomLetter() {
      // String containing all letters 
        const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
        // Return random letter from alphabet string 
        return alphabet[Math.floor(Math.random() * alphabet.length)];
    }

    // Toggles color state of specific cell
    toggleCell(row, col) {
        // Check if cell contains a valid letter (not '-')
        if (this.grid[row][col].letter !== '-') {
            // Toggle 'colored' state of cell
            this.grid[row][col].colored = !this.grid[row][col].colored;
        }
    }

  
  
    // Draws grid on screen
    draw() {
        // Iterate over each cell in grid
        for (let i = 0; i < this.gridSize; i++) {
            for (let j = 0; j < this.gridSize; j++) {
              // Set fill color based on cell's 'colored' state
                fill(this.grid[i][j].colored ? 'red' : 255);
                // Draw border around cell 
                stroke(0);
                // Draw cell as rectangle
                rect(j * this.cellSize, i * this.cellSize, this.cellSize, this.cellSize);
                // Set fill color for text (letter) to black
                fill(0);
              // Align text to center of cell and draw letter
                textAlign(CENTER, CENTER);
                text(this.grid[i][j].letter, j * this.cellSize + this.cellSize / 2, i * this.cellSize + this.cellSize / 2);
            }
        }
    }
}

initGrid(): This function creates a two-dimensional array with objects that correspond to each cell in order to set up the grid’s basic structure. At first, I had trouble seeing the grid as an arrangement of objects instead than just letters or empty spaces. But structuring every cell as an object with letter and color characteristics made managing the state of the grid more adaptable.

placeWords(): It was difficult to arrange the words on the grid, especially to make sure they matched and did not overlap. Every word in this condensed form is arranged horizontally and separated by rows. This function established the foundation for comprehending how words interact with the grid, even though the true problem lay in creating more sophisticated placement algorithms.

fillGrid(): To finish the setup of a standard word search puzzle, random letters had to be placed into the remaining vacant cells of the grid. This method iterates across the grid, substituting random letters for unassigned cells. It filled all the cells that had “-” instead of letters of the words that we placed in the grid.

getRandomLetter(): This function selects a letter at random from the alphabet. It fills in the blank cells in the grid, completing the word search problem and enabling gameplay. It’s a little but essential component of the code. It works directly with the function before it.

toggleCell(row, col): The requirement for grid interaction made this function difficult to implement. Users can choose which cells to change color by clicking them. The gameplay revolves around this interaction, which lets players highlight words they come across.

draw(): Lastly, the draw method gives the word grid a visual representation of each cell’s condition, bringing it to life. For the game to be visually appealing and functional, it was essential that every cell’s content—a letter—and state—colored or not—be shown clearly.

 

There are a couple of limitations for my assignment though. First of all the function that places the words in the grid is placing them all horizontally and under each other which makes the word search game less interesting. Moreover, I only chose three words all with three letters only which again makes this game easy and will end fast. From the technical side, you are required to press on every letter of the grid when you find a word which makes it harder and less appealing to play the game. Making it more realistic like striking through the letters when the correct word is found will make the game more realistic and more appealing to the player. However, overall, I think I did a good job with the representation of the grid and creating a separate  file for the WordGrid class to make the code more organized.

 

Assignment 4 – Saeed Lootah

Going into this project I originally had no idea what I was going to do. With the previous projects it was easy to come up with ideas but when it came to typography I didn’t know how I was going to make it aesthetic. I could have done data visualization but I couldn’t think of any data or statistics that mattered to me. In any case, the first idea that came to mind was to first try and make a bouncing ball which goes across the screen, then to make it about typography I would have said ball go to a certain point on the screen to spell out a word. It was a simple idea but as you will see down the line I added a few small details to make it more appealing.

I began first with creating the bouncing circle as you can see below

 

For some reason it has decided to fall through the bottom of the screen, but I promise when I first made it it worked fine :). In doing this simple animation I learned a lot. I had taken a lot of inspiration from my previous assignment where I wanted to make circles that went around. In that previous assignment I wanted to use vectors originally but didn’t know how to. However, after showcasing it in class my professor as well as Pi explained to me how to use the vector to add a new position. It was done by adding the vectors x or y value to the x or y value of the circle. You can see this in more detail in the code below.

update() {
    
    angleMode(DEGREES);
    
    this.posX = this.posX + this.v0.x;
    this.posY = this.posY + this.v0.y;
    
   // theres a problem where when it hits the corner it decides to go in a straight line into the next corner. Not sure why this happens, I think its to do with the if statements, but its rare enough where debugging isn't worth it (at least by my standards).
    
    // overarching if statement, if false then it goes into other if statements to see which part is false
    
    if(!(this.posY < height && this.posY > 0 && this.posX > 0 && this.posX < width)) {
      
        if(this.posX > 0 && this.posX < width) {
        // top and bottom
        if(this.posY < 0) {
          // top reflect
          print("reflect top");
          this.v0 = p5.Vector.reflect(this.v0, this.upVector);
        }

        if(this.posY > height) {
          //bottom reflect
          print("reflect bot");
          this.v0 = p5.Vector.reflect(this.v0, this.downVector);
        }
      } else {
        // left and right
        if(this.posX <= 0) {
          // left reflect
          print("reflect left");
          this.v0 = p5.Vector.reflect(this.v0, this.leftVector);
        }

        if(this.posX >= width) {
          // right reflect
          print("reflect right");
          this.v0 = p5.Vector.reflect(this.v0, this.rightVector);
        }
      }
    
    }
    
    // noise for the heading
    
    
  }

The specific line where I do the adding of the vectors x and y component is at the top. Afterwards I made a lot of if statements and created some other vectors from which the object could reflect off. The reason I did this with vectors again was because there was a method that already existed which I could use instead of doing math. By the time I had gotten all of this to work I was very happy with how it turned out. You’ll see with the bottom comment that I at one point was going to add noise to make the direction slightly random, but it didn’t work out unfortunately. I may work on this for the next assignment just as I worked on vectors for this assignment.

Then after that, I made another sketch. The plan for this other sketch was to just make the points surrounding text. Up to this point I had only ever done it once in class and that wasn’t enough for me to really understand how it works.

 

Its a very basic sketch, and that was kind of the point. It took me a while to make it and that was mainly because I was trying to center it. The way I did it was by subtracting half of the width of the text to the x position of the text since by default it’s drawn from the bottom left of the text (as far as I know, it may be top left but it doesn’t matter for centering). The problem was getting the width, for some reason textWidth() wasn’t working so I had to use the textBounds() function which is part of the font class which already comes with p5js. After all that I was finally ready to make the final project.

Also I should mention, my original plan was to make the text in arabic but I saw a stack-overflow post which said p5js isn’t great at doing right to left text and so I decided not to in order to save time.

By this point, my plan was that I would have all of these bouncing circles, one for each point in the text and then when the user holds down a button each button would return to it’s appropriate point on the text. Because I had done a lot of work before this working on separate features I was struggling with I could bring it all together and in theory it would mean that I wouldn’t have to spend as much time. I put the text sketch into a function, and since I had made the bouncing circle in a class I copied that too. In hindsight, I could have made the bouncing circle its own class to see how that would work and to learn a bit more but I, again, my try to do that for the next assignment.

Below is the finished product (press left click)

The text can be changed

Assignment 4 – Redha Al Hammad

As I was short on time for my fourth assignment I decided to utilise it as an opportunity to experiment with several different ideas.

The first of these ideas was an attempt to replicate the playfulness of the Pixar opening animation. For me (and I’m sure many others in the class) this opening sequence featuring Pixar’s familiar serif typography and iconic lamp character is incredibly nostalgic. I specifically remember how satisfying the movements  of the lamp and the reaction to the letter was to me as a child. I attempted to replicate the most notable movement from this reference in my sketch by focusing on the element of bouncing.

Pixar Movies and Shows | Disney+

I did this by enabling the individual letters of the word ‘jump’ to  jump and bounce once they reach their starting point. I am happy with the jumping and bouncing effect as I feel that is smooth and encapsulates the playfulness I was going for. However, as I was unfamiliar with how to go about it I used ChatGPT as a reference and, while it did give me a good starting point for my desired effect, it also produced a noise-like shaking which I could not figure out how to remove. I am still proud of this piece of code which enables the jumping and bouncing effect onto the individual letters.

 isMouseOver() {
    let letterWidth = textWidth(this.char);
    let letterHeight = this.size;
    return mouseX > this.x - letterWidth / 2 && mouseX < this.x + letterWidth / 2 &&
      mouseY > this.y - letterHeight / 2 && mouseY < this.y + letterHeight / 2;
  }
}

 

Using ChatGPT was a result of my limited time and, had I given myself enough time, I would have avoided the other main problem in my code which is that it became difficult to read after adding my second word – “zoom” – which moves across the screen when pressed. As I was attempting to do many different things (with the help of AI) in a short amount of time, things became overlapped and the “jump” function became used for both words.

Despite this, I feel that I have a better understanding of physics, classes and arrays after producing this work and will look to incorporate them more in my upcoming projects.


 

Week 4 Assignment – What da Names?

In week 4, we learned how to display text by loading custom fonts and manipulating CSV (Comma-Separated Values) files to visualize the contents.

I was originally working on some cool stuff (yes, very cool) by randomizing texts and using custom fonts for them. It was inspired by Typefaces of Toronto, an Instagram page that finds out the fonts used in facilities within the Toronto city. During this I found out that p5js have some limitations, that is the editor can only load specific font file types (such as those from Google Fonts) and not crazy ones like from Da Font.

However, I wanted to go even beyond just displaying text and wanted to manipulate data as well. So I tried to import some data sets from Kaggle and expected to play around with it. But for some reason, these data were not read properly by p5. I tried workarounds to see if appending them to a list would work but I could not get it to display properly and got errors regarding readableStream instead.

In the end, I opted for ChatGPT to help me generate a .csv file with this prompt:

Generate a CSV file. 50 rows, with three columns: name, year, count, for 50 random names within the year 2010 – 2024, in a random quantity between 1 – 5000, no spaces

After some workaround, here is the result that I came up with:

The result is a simple data showcase of Name, with Year in behind it, and the Quantity information under it. I utilized push() and pop() for the texts so that they are separate permutable objects. You can click to refresh the canvas.

//QUANTITY
  push();
  textSize(21);
  countMsg = "In that year, there are " + str(count[myNum - 2]) + " babies.";
  text(str(countMsg), width/2, height/2 + 50);
  pop();

While coding, I also noticed that I needed to subtract the list index by 2 for it to show properly. I am still figuring out why this is the case, but I assume it is because I loaded the header (index[0]), so the program treated it by skipping to the next index immediately.

Overall, it is a fun project. Had I not encountered many problems and gotten sick over the weekend I might have created something much more appealing. But for now, this is the very best I can do with my time.

References

Browse Fonts – Google Fonts

ChatGPT (openai.com)

 

 

Assignment 4, Rama

For this assignment, I experimented with the concept of word clouds using p5.js, where the size and style of each word vary randomly. The word cloud relies on the frequency of words in the input text data. When the mouse is pressed on the screen, the word cloud is restarted, providing an interactive experience for the user.

Initially, I learned how to create the world cloud using a couple of YouTube videos, however, they did not go through the link between word frequency and size of the words in the sketch. So, I found this code (https://editor.p5js.org/dano/sketches/1_RLNdYnT) which uses a different method of text input and method of display than my initial sketch, however what’s cool is the word size is determined through word frequency. Here’s the code:
split(text) {
return text.split(/\W+/);
}

validate(token) {
return /\w{2,}/.test(token);
}


process(tokens) {

for (var i = 0; i < tokens.length; i++) {

if (! tokens[i]) continue;
var token = tokens[i].toLowerCase();
if (this.validate(token)) {
this.increment(token);
}
}
}


getKeys() {
return this.keys;
}getCount(word) {
return this.dict[word];
}

increment(word) {
if (!this.dict[word]) {
this.dict[word] = 1;
this.keys.push(word);
} else {
this.dict[word]++;
}

The code technically breaks down the words in the text and keeps count of their frequency. Then it validates these words (true/false), keeps track of their count/frequency in the passage or text. It’s like a simple tool for counting and analyzing the words in a piece of text.

I incorporated this feature into my sketch,; it just does everything in one loop rather than split up like the linked sketch. And to analyze what function does what I used trial and error to see how I can simplify it to get to my final product.

 
 

One potential improvement I considered is the ability to load external text data so the user could make the word cloud generator more versatile and useful in different contexts.

Assignment 4 + Reading response – Shereena AlNuaimi

For this assignment, I planned to incorporate something that I have been passionate about for 10 years now which is archery. Truthfully, I’m pleased with how this task turned out. My life has involved archery greatly and continues to do so. And it’s awesome to be able to integrate that aspect of myself somewhat with my university education.

In order for this assignment to be interactive, when mouse is clicked the archery target appears circle by circle. Each circle color resembles a score. Realistically speaking, I wanted the colors to be as accurate as possible that’s why I chose the colors that I did. For it to be as close to the target as possible. Overall, i’m pleased with the outcome of this assignment.

let circleColors = [[255, 255, 0], [255, 0, 0], [0, 0, 255], [0, 0, 0]]; // Yellow, Red, Blue, Black
let circleSizes = [100, 200, 300, 400];
let circleIndex = -1;

function setup() {
  createCanvas(600, 600);
  textAlign(CENTER, CENTER);
  textSize(48);
  fill(255, 255, 255);
}

function draw() {
  background(240, 255, 255);
  // Draw the circles for the archery target
  for (let i = circleIndex; i >= 0; i--) {
    fill(circleColors[i][0], circleColors[i][1], circleColors[i][2]);
    stroke(0);
    strokeWeight(1);
    let circleSize = circleSizes[i];
    ellipse(width / 2, height / 2, circleSize);
  }
  
  // Draw the arrow-shaped letters
  let nickname = "Shroon";
  let startX = (width - (nickname.length - 1) * 50) / 2;
  let startY = height / 2;
  let arrowSize = 50;
  let spacing = 50;
  for (let i = 0; i < nickname.length; i++) {
    drawArrow(startX + i * spacing, startY, arrowSize, nickname.charAt(i));
  }
}

function mouseClicked() {
  if (circleIndex === circleSizes.length - 1) {
    circleIndex = -1; // Reset to show innermost circle again
  } else {
    circleIndex++; // Increment to show the next circle
  }
}


function drawArrow(x, y, size, letter) {
  // Draw the arrow body
  fill(255);
  stroke(0);
  strokeWeight(2);
  beginShape();
  vertex(x - size / 4, y - size / 8);
  vertex(x - size / 4, y - size / 2);
  vertex(x + size / 4, y - size / 2);
  vertex(x + size / 4, y - size / 8);
  vertex(x + size / 2, y - size / 8);
  vertex(x, y + size / 2);
  vertex(x - size / 2, y - size / 8);
  vertex(x - size / 4, y - size / 8);
  endShape(CLOSE);
  
  // Display the letter
  fill(0);
  textSize(size / 2);
  textAlign(CENTER, CENTER);
  text(letter, x, y - size / 8);
}


function drawArrow(x, y, size, letter) {
  // Draw the arrow body
  fill(255);
  stroke(0);
  strokeWeight(2);
  beginShape();
  vertex(x - size / 4, y - size / 8);
  vertex(x - size / 4, y - size / 2);
  vertex(x + size / 4, y - size / 2);
  vertex(x + size / 4, y - size / 8);
  vertex(x + size / 2, y - size / 8);
  vertex(x, y + size / 2);
  vertex(x - size / 2, y - size / 8);
  vertex(x - size / 4, y - size / 8);
  endShape(CLOSE);
  
  // Display the letter
  fill(0);
  textSize(size / 2);
  textAlign(CENTER, CENTER);
  text(letter, x, y - size / 8);
}

 

Reading Response:

Don Norman’s book “The Design of Everyday Things” addresses the difficulties people encounter with everyday possessions by emphasizing the design concepts of affordances, signifiers, and mapping. Norman illustrates the uncertainty and frustration brought on by poor design by sharing personal tales about his problems with doors and other everyday items. He highlights the significance of discoverability and understanding in effective design, talking on the necessity of clear and understandable signals that convey the right information about what may be done and how.

Furthermore, he emphasizes how important it is for designers to comprehend both technology and human behavior. He draws attention to the difficulties brought about by technology advancements, such as the growing complexity of everyday items as a result of functional additions. Norman talks on the paradox of technology, which has the ability to improve people’s lives and make things easier, but it also creates complexity that can cause users to become frustrated and struggle. Additionally, when designing products, the interaction of psychology and technology is crucial to making sure that people find the end result delightful and pleasurable as well as useful. Norman’s observations highlight the necessity for designers to put behavior and human needs design (HCD) first while utilizing technology to improve the user experience as a whole.According to him, the foundation of successful design is a thorough understanding of people and their wants, which is attained by observation and adaptive design processes that guarantee products actually satisfy user needs.

Week 4 Reading Response – Khalifa Alshamsi

Reading “The Design of Everyday Things” by Don Norman has made me rethink my everyday frustrations with things like doors and appliances. It’s pretty eye-opening to see how common it is to struggle with objects that are supposed to be simple. The idea of “Norman doors” – doors that confuse you whether to push or pull – is something I can relate to. It turns out these annoyances aren’t just random; they’re often the result of poor design choices that don’t consider the user’s experience.

Norman talks a lot about the importance of making things intuitive, which makes sense. It’s frustrating to need signs or instructions for something as basic as a door. But the book also points out how often design prioritizes looks over functionality, leading to unnecessary complexity. This struck a chord with me because it’s not just about aesthetics; it’s about making things harder to use than needed.

The book has made me more aware of the design choices around me and sparked an interest in looking at everyday objects more critically. It’s one thing to appreciate good design when everything works smoothly, but Norman’s perspective has made me more conscious of how rare that is.