Week 4 – Generative Text Output

Concept

For this project, I decided to create a Football Player Stats program because I really love football and I am also really interested in individual player statistics. I wanted to make something that was not only interactive but also connected to something I personally enjoy. The program allows the user to click on different football players and view their all-time goals, assists, and appearances.

I used a CSV file to store the player information and then displayed the information in p5.js. My goal was to make the program simple to use while still making it interactive. Instead of displaying every player’s statistics at the same time, I made buttons for each player so the user can select the player they are interested in.

Code I Am Proud Of

The part of the code I am most proud of is the mousePressed() function because it is what makes the player buttons actually work.

function mousePressed() {
  // Check each player button to see if it was clicked
  for (let i = 0; i < players.length; i++) {
    
    let x = 50 + i * (buttonWidth + spacing);

    // Check if mouse is inside the rectangle(current button)
    if (
      mouseX > x &&
      mouseX < x + buttonWidth &&
      mouseY > buttonY &&
      mouseY < buttonY + buttonHeight
    ) {
      // Store the index of the clicked player
      selectedIndividual = i;
    }
  }

I am proud of this because I had to understand how the mouse position relates to the position and size of each button. The program checks whether the mouse is inside the boundaries of a button and then stores the index of that player. This index is later used to display the correct statistics.

Using a loop made things a bit easy because I did not have to write separate code for every player. The same code works for all of the players in the CSV file.

Implementation

I first created an array called players to store the information from the CSV file. But it was hard getting the CSV file to load correctly. It was really tough to find a method that worked with the latest version of p5.js. I searched online and watched YouTube videos, but I could not get the methods I found to work. I kept getting error messages. To solve this, I thought to asked ChatGPT “How to load things from a CSV file on the latest version of p5.js?” I pasted the error message I was getting when I used one of the methods I found online. From this, I learned how async, await, and fetch can be used together to load an external file. I also learned that “await response.text()” takes the contents of the CSV file and converts them into text that the program can use. This experience taught me that sometimes the code from an older tutorial may not work exactly the same way with a newer version of a library.

I then used .split() to separate the CSV into rows and values. After loading the data, I created a button for each player using a for loop. The position of each button is calculated based on its index, which allows the buttons to be placed next to each other without manually positioning every button. When a player button is clicked, selectedIndividual is changed to that player’s index. The draw() function then uses that index to find the player’s information and display their name, goals, assists, and appearances.

Reflection

Another challenge I faced was making the buttons actually select the correct player. At first, I thought I would have to manually set the values and positions of each button and then check whether the mouseX and mouseY were over each individual button. However, I realized that this would make the code much longer and more complicated. Then it clicked that I could use the same calculations I was already using to create the buttons. Since the for loop already calculates the x-position of each button using the player’s index, I could use that same x-position in mousePressed() and check whether the mouse was inside the button’s boundaries. I used mouseX and mouseY to compare the mouse position with the button’s x and y positions. Once I detected which button was clicked, I stored its index in selectedIndividual, which allowed the program to display the correct player’s statistics.

Overall, I am happy with this project because I was able to create something based on one of my interests while also learning more about arrays, loops, mouse interaction, and external data. If I continued developing this project, I would add more players and statistics and improve the visual design. I could also add player photos, positions, teams, or a feature that allows the user to compare two players. This would make the program more interactive and give the user more ways to explore the football statistics.

Week 4 – Reading Response – The Design of Everyday Things

What stuck with me most about Norman’s chapter isn’t the terminology itself but his point that struggling with a simple object like a door is a design failure, not personal stupidity. That felt oddly validating because I think most of us walk around quietly blaming ourselves for these tiny daily failures, when really we’re just reacting normally to objects that were never designed to communicate clearly with us in the first place.

What’s something that’s not mentioned in the reading but drives me crazy is the motion sensors in soap dispensers in public bathrooms. There’s no signifier at all, no marked spot to wave your hand under, no light indicating the sensor even exists, so you end up doing this awkward hovering ritual in front of a sink hoping something happens. Half the time people assume it’s broken and move to the next one, when really the person standing in the exact invisible zone the sensor is calibrated to detect. It’s a perfect example of an affordance (motion detection) existing with basically zero signifier attached to it. I think this issue could be fixed by putting a small laser light that always points where your hand should go. This would

Applying this to interactive media, I feel that usability isn’t just about clear individual buttons, it depends on whether the user builds an accurate mental model of how the entire system is organized. Take an app with swipe versus tap gestures: if swiping left archives an email but swiping right deletes it, and there’s no visual cue distinguishing the two outcomes beforehand, users are essentially relying on trial and error. That means even if each gesture technically works fine, the app still feels confusing unless the user has a clear, accurate picture of how all the gestures fit together. So Norman’s principles apply here too: good design isn’t just about signifiers on individual elements, it’s about making sure the whole system builds a conceptual model the user can actually predict and rely on.

Week 3 – Generative Art OOP

Concept

For this week’s generative artwork, I decided to create a fireworks effect. The idea was inspired by something that happened recently back home in Fiji. My home football team, Ba FA, won the league, and my dad was showing me videos of the fireworks that were happening that night to celebrate the win. With that in mind, I thought it would be interesting to create my own digital version of fireworks using p5.js.

I wanted the artwork to feel active and unpredictable, so instead of having the fireworks appear in the exact same way every time, I used randomness to control their position, size, colour, and speed. I also added a mouse interaction so the user can click anywhere on the canvas to create a firework.

Code I Am Proud Of

The part of my code that I am most proud of is how I implemented the Firework class and made each firework have its own properties. Doing object oriented programming particularly in p5.js was new to me but with the help of Coding Train tutorials, I managed to pull this off. Each firework has its own position, size, maximum size, colour, and speed. This allowed me to create multiple fireworks that behave slightly differently from each other.

// Firework Class
class Firework {
  constructor(x, y) {
    this.x = x;
    this.y = y;

    // Starting size and the maximum size of the firework
    this.size = 5;
    this.maxSize = random(40, 100);

    // Random color for the firework
    this.r = random(100, 255);
    this.g = random(100, 255);
    this.b = random(100, 255);

    // For random speed of the fireworks
    this.speed = random(0.5, 2);
  }
  
  // Method for making the firework bigger
  update() {
    this.size += this.speed;
  }

  // Method for displaying the firework
  display() {
    noFill();
    stroke(this.r, this.g, this.b);
    strokeWeight(3);
    circle(this.x, this.y, this.size);
    // Small center of the firework
    fill(this.r, this.g, this.b);
    noStroke();
    circle(this.x, this.y, 5);

}
  // Returns true when the firework reaches its maximum size, otherwise false
  finished() {
    return this.size >= this.maxSize;
  }

I am also really proud of how I made the fireworks finish and then get removed from the array. I used a finished() method to check when a firework reaches its maximum size:

function draw() {
  // Goes backwards through the array and removes any fireworks that have finished
  for (let i = fireworks.length - 1; i >= 0; i--) {
    if (fireworks[i].finished()) {
      fireworks.splice(i, 1);
    }
  }
}

This part took me quite a while to figure out. I initially found it really tough to remove fireworks from the array while also going through the array. I eventually realized that I could go through the array backwards. This allows me to safely remove a firework . The finished method checks whether the firework has reached its maximum size. Once it has, the loop removes it from the array.

Implementation

I used an array called fireworks to store all of the firework objects. New fireworks are automatically created at random positions, and the user can also create one by clicking on the canvas.

I also used a transparent background to create the fading effect: background(10, 10, 30, 25);

The 25 is the alpha value, so the background is partially transparent rather than completely covering the previous frame. This allows parts of the previous frames to remain visible and gradually fade away, creating a trail effect behind the fireworks.

I also used random() throughout the program so that the fireworks do not all look or behave exactly the same. Their colours, speeds, maximum sizes, and positions can all be different, which makes the artwork generative.

Reflection

I enjoyed making this artwork because I was able to connect a personal experience from home with what I have been learning in p5.js. It also helped me understand object-oriented programming and arrays better.

The most challenging part was figuring out how to remove finished fireworks from the array. I initially found this confusing, but going through the array backwards and using splice() helped me understand better how fireworks with different speeds that finish at different times can be removed correctly.

If I were to improve this artwork in the future, I would like to make the fireworks look more realistic by adding individual particles that explode outward instead of just making the circle grow. I would also like to experiment with different shapes, sounds, and more mouse interactions to make the celebration feel more dynamic.

Week 3 – Reading Response

I think that a strongly interactive system is one where the user feels involved and where there is a continuous exchange between the user and the system. Crawford describes interaction as a process where two actors “listen, think, and speak.” I found this interesting because it means that a system should not just react to an action, but should take the user’s input, process it, and then respond in a meaningful way. This makes the interaction feel more like a conversation between the user and the system. Based on the examples given by Crawford, I understood that a strongly interactive system needs all three parts working together, not just one or two of them.

For improving the degree of user interaction in my p5.js sketches, I could make the system behave according to the user’s actions. For example, I could add mouse functionalities where objects change depending on where the user moves the mouse or what they click on. I could also use keyboard inputs to let the user control different parts of the sketch. Instead of having the same response every time, I could make the sketch respond differently depending on the user’s actions. This would make the user feel like they have more control over what happens.

In the future, I would like to make these interactions more complex and meaningful. Animations or transitions could be added to make it clear how a specific user action led to a specific outcome. I could also make the system remember previous user actions and use them to affect what happens later, such as in a game where the user’s previous choices change the experience. This would make my sketches feel less like animations that the user is simply watching and more like interactive systems where the user and the program are continuously responding to each other.

Week 2 – Generative Artwork

Concept

For this assignment, I wanted to create something that moves and looks alive using the programming concepts and techniques that I know and have learned so far. The idea that came to me was to create a weather scene showing a house during rainy weather. This idea was inspired by the difference between the weather in my home country, Fiji, where it is currently the rainy season, and Abu Dhabi, where the weather is generally very sunny. I decided to represent these two different environments in the same artwork. I used concepts like arrays, loops, Boolean variables, functions, conditionals, randomness, and animation to create a lively artwork.

Click on it!

Code I am Proud of

function draw() {
  // To draw and move the raindrops
  if (raining == true) {

    // Goes through all 100 raindrops 
    for (let i = 0; i < 100; i++) {
      // To draw the current raindrop 
      drawRainDrop(i);

      // To move the current raindrop
      moveRainDrop(i);
    }
}
// Function for drawing individual raindrop
function drawRainDrop(i) {
  fill(50, 100, 255);
  noStroke();

  // For making each raindrop
  ellipse(rainDropX[i], rainDropY[i], 5, 10);
}

// Function for moving an individual raindrop
function moveRainDrop(i) {
  rainDropY[i] += 5;

  /* If the raindrop reaches the ground, Its moved back randomly to the top with a random x position also */
  if (rainDropY[i] > 500) {
    rainDropY[i] = random(-50,0);
    rainDropX[i] = random(0, width);
  }
}

The part of the code I am most proud of is the falling rain effect. It took me several attempts and a lot of thinking to figure out how I wanted the raindrops to behave. At first, I was thinking about how I could continuously generate new raindrops while older ones were still falling. I eventually realized that I did not actually need to create completely new raindrops every time. Instead, I could create 100 raindrops and continuously reuse them by changing their positions after they reached the ground.

The arrays were important for this because they allow the program to store the position of every raindrop. The for loop then goes through all 100 raindrops and updates each one. I particularly like this approach because there are only 100 raindrops being managed, but they can continue falling and respawning throughout the entire animation. This creates the impression of continuous rain without needing to continuously create more and more objects. I am also proud of use of randomness when the raindrops respawn. If every raindrop started at exactly the same x and y position, the rain would look artificial and repetitive. Randomizing the positions makes the scene look more natural. I was able to connect this programming technique to Casey Reas’ idea of Chance Operation. Rather than using randomness just because it was useful for the animation, I was able to think about randomness as part of the artistic design of the project.

Implementation

I created arrays called rainDropX and rainDropY to store the x and y positions of the 100 raindrops. These arrays allow the program to keep track of every raindrop individually. In the setup() function, I used a for loop to create 100 raindrops and give each one a random starting position. The x-position is randomly generated across the width of the canvas, while the y-position is randomly generated across the canvas. This means that when the program starts, the raindrops are already distributed throughout the scene.

The main animation happens inside the draw() function. I used a Boolean variable called raining to determine which weather condition should be displayed. When the program starts, it shows a rainy scene, and when the mouse is clicked, the rain stops and the scene changes to a sunny one. Clicking again brings the rain back. I used a for loop to go through all 100 raindrops every frame. For each raindrop, the program calls drawRainDrop(i) to draw it and moveRainDrop(i) to move it downward. The movement of each raindrop is relatively simple. Every frame, its y-position increases by 5.

Reflection

The most challenging part was creating the falling rain, but working through it helped me better understand how arrays and loops can be used to manage multiple objects at the same time. In the future, I would like to improve the project by making the transition between rainy and sunny weather smoother, perhaps adding moving clouds and lightning, and possibly adding sound effects. I would also like to experiment more with randomness and explore how I can use programming to create more interactive and visually interesting artwork. Overall, I am happy with the project because I was able to use the programming concepts I have learned to create something animated, interactive and personal.

 

Week 2 – Reading Reflection

Reflection

Casey Reas talk reframed how I think about the role of randomness in creative work. He talks about “controlled randomness,” where the artist doesn’t control every outcome, but does control the rules that the randomness has to follow. So chance is not a lack of decisions, it is just a different kind of decision.

For my own work, I plan to use randomness with some control to make things feel more realistic. I think that too much randomness can make a piece feel meaningless, since it can look like nothing was actually decided or planned before the project. But too much control isn’t great either because it only leaves room for what I’ve already imagined and nothing more.

I don’t think there’s one fixed balance between randomness and control because it really depends on the piece someone is working on. Some ideas need more structure with just a little randomness added in, while others can handle a lot more chance. For me, I would aim to keep the overall rules consistent, but let the small details  like position or timing  be randomized enough to surprise me.

Week 1 – Self Portrait Nidhish

Concept

For my first assignment of making a self-portrait, I wanted to create a drawing that looked as much like me as possible using the basics I learned in p5.js this week. I included details such as my hairstyle, face, ears, eyes, eyebrows, moustache, beard, and clothing to make the portrait recognizable and personal. I also added sunglasses because ever since I came to Abu Dhabi, I have had to mostly wear sunglasses when I go outside because it is often very sunny and bright here. To make this detail more interesting, I programmed the sunglasses to appear when the mouse is pressed.

Since this was my first time coding in p5.js, I wanted to challenge myself while working with the techniques I had learned. I tried to include enough details to represent my appearance without making the drawing too complicated. The interactive sunglasses also allowed me to connect the portrait to my everyday life in Abu Dhabi. Overall, I aimed to create a simple but personal self-portrait that shows both what I look like and a small part of my experience living here.

Press the mouse!

Implementation

I implemented my self-portrait in p5.js using a combination of different shapes, arcs, and lines. I used ellipses to create the face, ears, and eyes, rectangles and triangles for the neck and shirt, and arcs for the hair, eyebrows, mouth, and beard. I also used lines to create the moustache, hair details, and the sunglasses. I used different colours for the skin, hair, shirt, mouth, and background to make the portrait more detailed and visually appealing.

One of the more difficult parts of the implementation was determining the exact x and y coordinates for placing each figure in the correct position. I then thought of displaying the x and y coordinates of the mouse on the screen. This made my work much easier because I could move my mouse to the exact position where I wanted to place a point or shape and then use those coordinates in my code. This helped me position the different parts of the portrait more accurately.

I also used if and else statements to make my portrait interactive. I used an if…else statement to change the background colour depending on whether the mouse was being pressed. When the mouse is pressed, the background changes to a yellow colour indicating sunlight, and when it is not pressed, the background returns to default grey. I also used an if statement with mouseIsPressed to make sunglasses appear on the portrait when the mouse is pressed. This allowed me to make my self-portrait more interactive rather than having it remain as a static drawing.

Code I am Proud of

  function draw() {  
  if (mouseIsPressed){
    background(250, 222, 133);
  }
  else{
    background(220);
  }
// Sunglasses when mouse is pressed
  if (mouseIsPressed){
    strokeWeight(4);
    line(126,198,146,227);
    line(274,198,254,227);
    line(170,235,230,235);
    fill(50);
    ellipse(165,235,50,40);
    ellipse(235,235,50,40);
  }
}

The code I am most proud of is the part of my draw() function that uses mouseIsPressed to add sunglasses to my self-portrait. I am proud of this because it allowed me to make my portrait interactive. When I press the mouse, the sunglasses appear on the face, while the background changes from grey to a bright yellow colour. The yellow background represents the bright sunlight in Abu Dhabi, which is why I connected it with the sunglasses. I liked how I was able to use an if…else statement and the mouseIsPressed function to create an interaction that also has a personal meaning. Since this was my first time coding in p5.js, I was especially proud that I was able to create this effect and connect it to my own experience.

Reflection

I enjoyed experimenting with different shapes, colours, arcs, and lines to see how they could be combined to create different facial features. I was also really happy with how the interactive sunglasses turned out. Something I would still like to improve is to make my sketch more detailed. At the moment, I mainly relied on basic shapes, but in the future I’d like to work with new shapes and explore different ways of creating more interactive and aesthetic sketches. I also think it would be a good idea to add animations in the future, as this could make my sketches more engaging and bring them more to life.