Week 7 – Midterm Project: Save The Fish!

Concept

For my midterm project, I created a game where the player controls a fish swimming through a river. The main goal of the game is to survive for as long as possible. While swimming through the river, the fish encounters different food objects and garbage objects. The player needs to eat the food to keep the fish healthy while avoiding the garbage. The fish’s health drains constantly, so the player cannot just sit still, and eating three pieces of garbage kills the fish.

The game is also intended to communicate a message about pollution in freshwater environments. Pollution in rivers can seriously affect the aquatic creatures living in that ecosystem. By making this the main idea of the game, I want the player to experience this problem through the gameplay rather than simply being told about it. Every piece of garbage the fish touches costs it a life, so the player quickly feels how dangerous a polluted river can be.

Implementation

I organized the code using several classes, there’s a Fish class for the player, a RiverObject class for every piece of food and garbage, a Bubble class for the background decoration, and a Game class that basically controls everything. The Game class has three states: a home screen, the playing screen, and a game over screen. While playing, the player steers the fish with the arrow keys and has three lives (shown as red circles) and a health bar that slowly drains. Eating shrimp, small fish or algae restores health and gives points, while colliding with plastic, a bottle or a can costs one life. Instead of writing a separate class for each kind of food or garbage, every type is stored as data (its size, the points it gives and the health it restores). Sound effects play when the fish eats food, eats garbage and dies. Another feature implemented was a high-score system using the browser’s localStorage, so the high score is still there the next time the game opens. A New High Score message appears when the player beats it. Images were generated using META AI and I used Claude AI to help me understand certain problems and the materials shared in class better. It helped me learn which tools or approaches would be useful for the what I wanted to do. The materials shared in class were also very helpful. Claude was also used to generate sound effects garbage collision.

Code I am Proud of

One part I am proud of is how the game gets harder. At first the game felt boring and easy to play, so I decided to make it harder as the player’s score increases. The game calculates a difficulty level from the score (one level for every 25 points, up to a maximum of 7).

// Difficulty level: goes up by 1 every 25 points (max 7)
getLevel() {
  return min(floor(this.score / 25), 7);
}

That level is then added to the speed of every new object that is created:

let newObject = new RiverObject(
  width + 20,
  random(100, height - 50),
  objectType,
  random(2, 4) + this.getLevel() * 2,  // faster at higher levels
  category,
  this.images[objectType.type]
);

this.objects.push(newObject);

This allows the game to become progressively more difficult without requiring me to manually define a different speed for every level. Instead, the speed is calculated automatically whenever a new object is created. It also makes the difficulty system easier to adjust. The same level also shortens the delay between spawns, so the river stays busy even though objects cross the screen faster.

I am also proud of the health bar that I created which changes colour.

// How full the bar is (between 0 and 1)
    let ratio = constrain(this.health / MAX_HEALTH, 0, 1);

    // Green when healthy, yellow when low, red (flashing) when almost empty
    let barColor;

    if (ratio > 0.5) {
      barColor = color(70, 200, 90);
    } else if (ratio > 0.25) {
      barColor = color(240, 200, 50);
    } else {
      barColor = color(230, 60, 50);
      // Flash lighter and darker 4 times a second
      if (floor(millis() / 250) % 2 === 0) {
        barColor = color(255, 130, 120);
      }
    }

The colour of the bar changes from green to yellow and then red as the fish loses health. When its health becomes critically low, the bar starts flashing to create a sense of urgency. I implemented this using the constrain() function to keep the health ratio between 0 and 1, conditional statements to determine the colour, and millis() to create the flashing effect every 250 milliseconds. I am proud of this feature because it provides clear visual feedback, allowing players to quickly recognize the fish’s condition and react before it runs out of health.

Reflection

The hardest part was balancing the difficulty. My first version only made the objects faster as the score went up, but then the player often saw just one object on the screen at a time. New objects were still appearing every 1.5 seconds, while each one crossed the screen much faster than before. I fixed this by also reducing the spawn delay as the level increases (with a minimum of 0.3 seconds) and by capping the level at 7 so the game does not become impossible. It was also challenging to decide how the game should end. I first thought of running the game for a fixed time then the users could compare their scores, but then I decided to have a high score system so I added two ways in which the game ends. One when the health bar goes down and another is when the fish has collided with 3 trash items

If I was to improve this game in the future, I would add more variety to the gameplay. For example, I could introduce different river environments, additional types of pollution, or special objects that temporarily help the fish. The game would also be more interesting if the users could enter their username before playing and at the home screen the top 3 high scores with its username would be shown. This would make the game feel more competitive, as everyone would want to be on the leader board. Another improvement would be to include a short educational message or fact about freshwater pollution at the end of each game, helping players to understand real-world environmental issues. Overall, one of the most valuable things I learned from this project was the importance of organizing code using classes and methods. Separating the fish, river objects, bubbles, and overall game logic made the program much easier to manage.

Midterm Progress

Project Concept and Design

For my midterm project, I have planned to create a game where the player controls a fish swimming through a river. The main goal of the game is to survive for as long as possible. While swimming through the river, the fish will encounter different food objects and garbage objects. The player needs to eat the food to keep the fish healthy while avoiding the garbage.

The game is also intended to communicate a message about pollution in freshwater environments. Pollution in rivers can seriously affect the aquatic animals living there. By making this the main idea of the game, I want the player to experience this problem through the gameplay rather than simply being told about it.

The player will control the fish using the up and down arrow keys. The fish will have three lives, and eating garbage will cause the player to lose a life. Once all three lives are lost, the game will end. I also plan to add a health system where the fish’s health continuously decreases if it does not eat food. A health bar will show the player how much health the fish has remaining. I am also thinking to using left and right arrow keys to make the fish go front and back if the game feels really static.

Progress So Far

So far, I have created the basic game window and the river environment using p5.js. I have also added a fish as an ellipse that the player can control using the keyboard. I added moving water lines and bubbles to make the river feel more active rather than having a completely static background.

I have also started working on the objects that will appear in the river. At the moment, I am using simple circles as placeholders instead of actual images. There are three types of food: shrimp, small fish, and algae. There are also three types of garbage: plastic, bottles, and cans. Each object has a different size and color so that I can easily tell them apart while testing the game.

Another important part I have worked on is spawning and collision detection. The objects are currently spawned from the right side of the screen and move towards the left, similar to how objects would flow through the river. When an object reaches the fish, the program checks whether the two objects have collided. I have used the distance between the fish and the object to determine whether they are close enough to count as a collision.

let fish;
let objects = [];

let lastSpawnTime = 0;
let spawnInterval = 1500;

let foodTypes = [
  {type: "shrimp", color: [255, 160, 50], size: 15},
  {type: "small fish", color: [255, 220, 80], size: 22},
  {type: "algae", color: [80, 210, 100], size: 30}
];

let garbageTypes = [
  {type: "plastic", color: [255, 255, 255], size: 18},
  {type: "bottle", color: [0, 0, 0], size: 25},
  {type: "can", color: [255, 50, 50], size: 32}
];
function setup() {
  createCanvas(700, 500);

  // Create the fish
  fish = {x: 200, y: height / 2, size: 40, speed: 4};
}

function draw() {
if (millis() - lastSpawnTime > spawnInterval) {
  spawnObject();
  lastSpawnTime = millis();
  }

  drawObjects();
  
  // Draw the fish
  drawFish();
}
// Function for drawing the fish
function drawFish() {
  fill(255, 180, 50);
  ellipse(fish.x,fish.y,fish.size * 1.5,fish.size);
}

function spawnObject() {
  let objectType;
  if (random(1) < 0.5) {
    objectType = random(foodTypes);
  } else {
    objectType = random(garbageTypes);
  }
  
  let object = {x: width + 20, y: random(80,380), size:objectType.size, color: objectType.color, type: objectType.type, speed:random(2, 4)};

  objects.push(object);
}

// Function for drawing objects
function drawObjects() {
  for (let i = objects.length - 1; i >= 0; i--) {
    let object = objects[i];

    // Move object from right to left
    object.x -= object.speed;
    // Set the object's color
    fill(
      object.color[0],
      object.color[1],
      object.color[2]
    );
    // Draw the object
    circle(object.x,object.y,object.size);

    // Remove object when it leaves the screen
    if (object.x < -object.size) {
      objects.splice(i, 1);
       }
    if (checkCollision(fish, object)) {
      objects.splice(i, 1);
      }
   
  }
}
// Function for checking collision
function checkCollision(fish, object) {
  let distanceBetween = dist(fish.x,fish.y,object.x,object.y);
  return distanceBetween < fish.size / 2 + object.size / 2;
}

 

The Most Uncertain Part

One of the parts of the project that I was most uncertain about was collision detection. I knew that the game would depend heavily on detecting when the fish eats food or garbage, but I was not sure how I would implement this in p5.js. I decided to work on this part early because it is an important part of the game’s main interaction.

I implemented a collision detection function that uses the distance between the fish and each object. If the distance is smaller than the combined sizes of the fish and object, the program considers them to have collided. Testing this early has reduced some of the risk because I now have a working foundation for the main gameplay mechanic.

Another part I am uncertain about is how I will make the game become harder as the player progresses. I want the game to start relatively easy and gradually become more difficult so that the player has to react faster and pay more attention as they continue playing. One idea I plan to try is changing the probability of spawning food and garbage as time passes. At the beginning, there could be a more balanced chance of getting food or garbage. As more time passes, I plan to increase the probability of garbage spawning while decreasing the probability of food spawning. This would make it harder for the player to maintain the fish’s health and avoid losing lives.

Next Steps

My next focus will be designing the home screen and the game-over screen so that the game feels more complete. I also plan to replace the simple colored circles with images for the fish, food, and garbage objects. I would like to add sounds as well, such as sounds for eating food, hitting garbage, and losing a life.

After that, I will continue developing the health and life systems. The final game will have three lives, a health bar, a scoring system, and increasing difficulty as the game continues. I also want to make the objects more visually interesting while keeping the controls simple enough for the player to understand easily.

Overall, I have now moved from planning the idea and have started building the core mechanics of the game. Having the fish movement, object spawning, and collision detection working gives me a basic foundation that I can build the rest of the game around.

Week 5 – Reading Response

Some ways in which I think computer vision differs from human vision are through how quickly we are able to understand what we see. When I look at an image, I can usually understand or identify what I am looking at almost immediately. I can recognize a person, understand their actions, and interpret the situation without consciously thinking about individual pixels. However, computers don’t naturally understand the meaning of an image. Computers have to analyze information such as changes in pixels, brightness, color, and movement. I found this interesting because it shows that computers do not actually “see” in the same way that humans do. Human vision allows us to interpret not only what is physically present in an image, but also the meaning and context behind it, whereas computer vision depends on how we teach the computer to interpret the visual information it receives.

To help a computer see and track what we are interested in, we need to give it specific information that it can identify. The reading discusses techniques such as frame differencing, background subtraction, and brightness thresholding, which allow a computer to detect things like movement or objects that stand out from their surroundings. Improving computer vision is not always about making the software more complicated. We can also change the physical environment for the computer so that the things we want to track becomes easy for the computer to detect. This made me think about computer vision as a combination of programming and design, where we are not only telling the computer what to look for but also creating the right conditions for it to find it.

Moreover, I think computer vision’s ability to track people creates both interesting possibilities and concerns for interactive art. Tracking allows an artwork to respond to a person’s movements and makes the experience feel more personal and interactive. At the same time, I think there is a clear difference between someone choosing to interact with an artwork and being tracked without fully realizing it. The reading’s discussion of surveillance made me think about how the same technology that makes an artwork interactive can also make people feel observed. Because of this, I think artists need to think carefully about how they use tracking and whether participants understand what the system is observing.

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.