Midterm Project

Golden Goal

Click here for Game Tutorial

press “f” for fullscreen mode

Project Concept
For my midterm project, I created a football penalty game called Golden Goal. I chose this concept because I love football and used to play a game called Penalty Shootout Multi League when I was younger. I wanted to create my own simpler version while adding some ideas that make it more personal, interactive, and challenging.

The player first reads the instructions and chooses between France, Italy, England, Germany, and Brazil. The character’s uniform changes depending on the selected team. The player then has five penalty attempts and only five seconds to take each shot. The goalkeeper moves from side to side and becomes faster after every attempt. On the fifth attempt, a golden target appears inside the goal. Hitting it gives the player two points instead of one. At the end, the player level will appear after he played, it will be star player, good player, or bad player, depending on how they score.

Inspiration Game

 

How the Project Works & What I Am Proud Of

The game uses different screen numbers to control which part of the experience is displayed. Screen 0 shows the instructions, screen 1 shows team selection, screen 2 is the game, screen 3 shows the result of a shot, and screen 4 shows the final score. Conditional statements check the current screen number and display the correct part of the game. This helped me keep the different sections organized inside one sketch.

function draw() {
  if (screenNumber == 0) {
    displayInstructions();
  }
  else if (screenNumber == 1) {
    displayTeamSelection();
  }
  else if (screenNumber == 2) {
    displayGame();
  }
  else if (screenNumber == 3) {
    displayShotResult();
  }
  else {
    displayFinalScreen();
  }
}

I am especially proud of the golden target because it is my own addition to the normal penalty-game idea. It only appears during the final attempt. The code uses dist() to check the distance between the ball and the target. If the distance is less than 50, the player receives two points.

else if (
  (attemptNumber == 5) &&
  (dist(ball.x, ball.y, goldenX, goldenY) < 50)
) {
  score = score + 2;
  resultMessage = "GOLDEN GOAL! +2 POINTS";

  goalSound.stop();
  goalSound.play();
}

I also used Object-Oriented Programming by creating a separate Ball class inside Ball.js. The class stores information about the ball and contains functions for moving, displaying, shooting, and resetting it. Separating the ball code from the main sketch made the program more organized. I also added sound effects for kicking the ball, scoring, and clicking interface buttons. The player can press F to enter or leave fullscreen mode.

Another important feature is the restart system. After all five attempts, the player can select “Play Again” without pressing the p5.js Play button. The restart function returns the important variables to their original values and takes the user back to team selection.

function restartGame() {
  score = 0;
  attemptNumber = 1;
  shotTimer = 300;

  keeperX = width / 2;
  keeperSpeed = 7;

  selectedTeam = "";
  resultMessage = "";

  ball.startX = width / 2;
  ball.startY = height - 95;
  ball.x = ball.startX;
  ball.y = ball.startY;
  ball.moving = false;
  ball.reset();

  chooseGoldenTarget();

  screenNumber = 1;
}

Problems and Areas for Improvement

One problem I experienced was organizing the game for like the different screen modes. Some text and game elements were not positioned correctly when the browser size changed. I improved this by using windowWidth, windowHeight, width, and height, along with a windowResized() function, and applied this also to every screen function as well to make every screen adjusted with the screen mode. I also had difficulties resetting the ball and attempt number when the player selected “Play Again.” This taught me that restarting a game requires resetting every variable and object that changed during the previous session.

I also had some problems with sound. Some sounds were delayed, while background sounds made the sketch take too long to load. I decided to remove the menu and crowd sounds and keep only the sounds that were important to the interaction. Also, for example, the mouse click sound was very delayed, it played 3 seconds after the click, so I asked AI what was the problem, and it told me it would be better to use a .wav file for the sound better than .mp3 for faster sound loading. If I continued developing the project, I would improve the shooting animation and create more realistic movements for the player and goalkeeper. I would also like to add different difficulty levels, more team designs, and a system where the player can control the direction and power of the shot separately.

References

My main reference was the class slides, especially the lessons about functions, arrays, Object-Oriented Programming, conditionals, images, text, sound, and mouse interaction. I also used the official p5.js Reference when I needed to check how specific p5.js functions worked. My visual and gameplay inspiration was Penalty Shootout Multi League, from Friv. However, I created my own drawings, team-selection system, five-second timer, increasing goalkeeper speed, and golden target challenge.

I used AI as a support tool during the development process. Whenever I received an error that I did not understand, I gave the error message to AI and explained what my game was supposed to do. AI helped explain the meaning of errors and identify which part of the code was causing them. I also sometimes provided AI with the material and examples covered in class and asked which taught function would be most suitable for a particular feature that I wanted to do. I used this to understand my choices instead of introducing unrelated libraries or techniques. I reviewed and tested the suggestions inside the p5.js editor, made changes based on the results, and continued adjusting the game until the interactions worked as I wanted.

Week 5 – Midterm Project Progress

Golden Goal

My Concept

For my midterm project, I decided to make a football penalty game because football is something I really like. My main inspiration came from a game I used to play in my childhood called Penalty Shootout Multi League from Friv. I liked how the game allowed the player to take penalties against a goalkeeper, so I wanted to develop my own simpler version using p5.js and the programming concepts we learned in class throughout the last 5 weeks.

I did not want to exactly recreate the original game, so I added some of my own ideas to make it more challenging and interactive. The player has five attempts, and they only have five seconds to take each shot. If the player does not shoot before the timer finishes, the attempt is lost. The goalkeeper also moves quickly from left to right, which makes choosing where and when to shoot more difficult.

My other own addition is the “golden chance.” On the fifth and final attempt, a golden target appears inside the goal. If the player hits this target, they receive two points instead of the normal one point. I wanted the final attempt to feel different and more important than the earlier attempts.

User Interaction

The experience starts with an instruction screen that explains the rules. The game waits for the player to click before it begins. During each attempt, the player clicks on the position where they want to shoot the football. The ball then moves from the player toward the selected position while a kicking sound plays. The player must think about the goalkeeper’s position and shoot before the five-second timer ends. A normal goal gives one point, hitting the goalkeeper results in a save, and clicking outside the goal results in a miss. During the last attempt, the player can aim for the golden target to receive two points.

After all five attempts, the game displays the player’s final score. The player can click again to start a new session without refreshing or restarting the sketch.

Code Progress

So far, I have created the instruction screen, main game screen, and final score screen. I used a variable called screenNumber with conditional statements to decide which screen should be displayed. The values 0, 1, and 2 represent the instructions, game, and final score.

I also created a separate file called Ball.js for my Ball class. The class stores the ball’s position, destination, speed, and whether it is currently moving. Its functions allow the ball to shoot, move, display its image, and return to its starting position.

I used an uploaded transparent football image for the ball and added an MP3 sound that plays whenever the player shoots. The football field, goal, goalkeeper, and player are currently made with basic p5.js shapes. The goalkeeper moves left and right using a speed variable and conditional statements that change its direction.

For the positions of the game objects, I used width, height, width / 2, and height / 2, which helps keep the game properly positioned when the size of the browser changes.

Most Uncertain Part

The most uncertain part for me was making several parts work together at the correct time. The ball must move toward the mouse position, the goalkeeper must continue moving, the timer must decrease, and the game must decide whether the shot was a goal, save, miss, or golden goal.

To reduce this risk, I started testing these important parts early. I used the dist() function to check the distance between the ball and goalkeeper and between the ball and golden target. I also tested the timer by starting it at 300 because draw()normally runs about 60 times per second, making 300 frames around five seconds.

Separating the ball into its own class also helped me organize the program. Instead of putting all the ball code inside the main sketch, I can control it using functions such as:

ball.shoot(mouseX, mouseY); 
ball.move(); 
ball.display(); 
ball.reset();

These tests helped me make sure that the main idea of the game is possible before spending more time improving its appearance.

Plans Before the Final Draft

Before the final draft, I would like to improve the designs of the player and goalkeeper so that they look more like football characters. Right now, they are intentionally simple and made from basic shapes because I first wanted to make sure the gameplay worked. With more time, I would like to add more detail and improve the kicking movement.

I also want to add more sounds. Right now, I have a kicking sound, but I would like to add background stadium and fan noise. If the player scores, the fans could cheer, and if the player misses or the goalkeeper saves the shot, the fans could whistle. This would make the result of each shot clearer and make the game feel more interactive.

I would also like to keep adding creative ideas as they come to me. For example, I could improve the instruction and final screens, change the visual appearance of the golden target, and possibly add different difficulty levels. I think the more creative details and reactions I add, the more interactive and enjoyable the final game will become.

Week 5 – Reading Reflection

The reading changed how I think about the difference between computer vision and human vision. Humans can recognize a person or object even when the lighting, angle, or background changes, because we understand context. A computer sees pixels and must follow programmed rules, so it can easily become confused. I think I can say that I have experienced this when my phone’s face recognition failed when in poor lighting even though another person could recognize me immediately. We can help computers track what interests us by using stable lighting, a plain background, strong contrast, colored markers, brightness thresholding, frame differencing, or background subtraction. I agree with the author that improving the physical environment can sometimes be easier than writing more complicated code. This made me realize that designing a computer-vision project involves arranging the camera, lighting, and space as well as the programming itself.

I also think the author is slightly biased toward the positive and creative possibilities of computer vision because he is an artist and practitioner in this field. Although surveillance concerns are mentioned, I feel the reading could discuss privacy and consent more strongly. Tracking can make interactive art exciting because people can use their bodies instead of a mouse or keyboard, but the same technology can record people who did not agree to participate. This could make an artwork feel uncomfortable instead of interactive. If I used computer vision, I would clearly tell participants what the camera tracks and avoid saving their video.

Week 4 Reading Reflection

Before this reading, I always blamed myself when I could not understand how to use an everyday object. But after reading, Norman changed this view by showing that confusion is often evidence of poor design rather than user failure. Something that sometimes drives me crazy is a self-checkout machine that suddenly stops and displays an unclear error. It often tells me to place an item in the bagging area even though the item is already there, but it does not explain what I should do next. I would improve it by using clearer instructions, showing the exact item causing the problem, and providing an obvious button to ask for help. I think Norman may be slightly biased because he strongly favors usability and sometimes treats simple appearance as a cause of confusion. However, I think his examples support his argument that appearance should not hide function.

I can apply Norman’s principles to interactive media by making every possible action discoverable. In my p5.js sketches, clickable text should look clickable, instructions should appear before the user needs them, and every click should create immediate and understandable feedback. Controls should also have clear mapping, which means their position and appearance should relate naturally to what they change. For example, in the latest assignment I made,  clicking the “new result” option should visibly just replace the current football match result instead of producing an unexplained or unexpected change. At the end, the reading made me wonder how designers can keep an interface visually clean and clear while still providing enough signifiers and instructions, especially for a first-time user.

Week 4 – Assignment

Text Generator – Matches Results

My Concept

For this assignment, I decided to make a generative football results screen. Football is something I admire, so I wanted to connect the assignment to something personal instead of generating random poems or unrelated sentences.

The sketch displays a match result, the two teams, and the competition or in other words, the country league. When the user clicks the canvas, a different result appears. The green background represents a football pitch, while the yellow and white text make the information clear and easy to read. The results are sample results stored in my CSV file, not live results from the internet.

My Highlight Code

The part of the code I am most proud of is where the program randomly selects one match and separates its information:

  singleMatch = splitTokens(
matches[int(random(matches.length))],",");

random(matches.length) chooses a random position from the matches array. int() changes it into a whole number that can be used as an array index. The selected CSV row is then separated at every comma using splitTokens(). This allows me to access the teams, scores, and competition separately.

I also used:

function mouseClicked() {
  loop();
}

This allows draw() to run again after a click and display another match result.

My Embedded Sketch

You can click the sketch to display another result.

How This Was Made

I created a file called matches.csv. Every row contains the first team, its score, the second team, its score, and the competition/league. I loaded this file with loadStrings(), which stores its rows inside an array.

I assigned an index number to each category, such as TEAM1, SCORE1, and COMPETITION. After selecting and splitting a random row, I used these index numbers to retrieve the correct information.

I used loadFont() to load the Geo.ttf font that I chose and uploaded to the p5.js editor. I then used text(), textSize(), and fill() to design the results screen. Finally, noLoop() stops the results from changing automatically, while loop() allows a new result to appear after a mouse click.

I made this assignment fully based on the Week 4 class slides, and specifically the functions shown in each slide and the sketch examples given in the slides to see how everything works and use examples for ideas. Particularly, the generative poetry examples. I adapted the structure of such examples to display my football matches results texts.

Reflection

The biggest challenge was understanding how one CSV row becomes an array after using splitTokens(). At first, the index numbers were slightly confusing, but labeling them as TEAM1, SCORE1, TEAM2, SCORE2, and COMPETITION made the code easier to follow.

I also needed to make sure that the CSV and font filenames matched the filenames written in the code. If one letter was different, the file would not load. Whenever I had a problem, I returned to the week 4 slides because they explained the process step by step and in a very detailed way.

I am happy that I connected the assignment to football. In the future, I would like to learn how to load real match results automatically instead of entering sample results manually.

Reading Reflection – Week 3

Before this reading, I thought anything that reacted when I touched or clicked it was automatically interactive. Crawford’s example of the refrigerator light made me reconsider that idea. I agree that a strong interactive system should do more than give one automatic response. It should understand the user’s input, process it in a meaningful way, and give a useful response. Video games support his argument because they react differently depending on a player’s choices, while a movie continues in the same way no matter what the viewer says or does. However, I think Crawford is slightly biased because his definition is very strict. Even simple interactions can still be enjoyable or helpful, especially for beginners or children.

For me, a strongly interactive system should respond quickly, provide clear feedback, and make the user feel that their choices matter. The response should also change depending on what the user does instead of repeating the same result every time. In my future sketches, I could improve interaction by using the mouse and keyboard to let users control objects, change colors, create new shapes, or remove items from an array. I could also make objects react differently depending on where the user clicks. The reading made me wonder whether a simple response can become strongly interactive if it leads to many different choices over time.

Week 3 Assignment

Overall Concept

For this assignment, I wanted to create a generative artwork based on colorful bubbles floating around in a dark space. I chose bubbles because they are easy to recognize, but they can still create an interesting image when there are many of them moving together. I wanted the final artwork to feel calm, colorful, and slightly playful rather than looking like a game or a completely still picture.

Every time the sketch begins, the bubbles appear with random positions, sizes, colors, and speeds. Because these values are random, the arrangement is never exactly the same. Some bubbles are large and move slowly, while others are smaller and move more quickly. The random colors also create different combinations each time the program starts. I used a dark blue background to make the brighter colors more visible.

I used Object-Oriented Programming because every bubble needs the same basic information and actions. The Bubble class works as a template that stores each bubble’s position, speed, size, and color. It also contains methods that allow each bubble to move, bounce, and display itself. I then stored all the bubble objects inside one array and used loops to control them. This made it possible to create many bubbles without writing separate code for every one.

Sketch Code

let bubbles = [];

function setup() {
  createCanvas(600, 400);

  // create 100 bubble objects
  for (let i = 0; i < 100; i++) {

    let newBubble = new Bubble(
      random(50, 550),
      random(50, 350),
      random(-3, 3),
      random(-3, 3),
      random(30, 80),
      random(255),
      random(255),
      random(255)) ;

    bubbles.push(newBubble);
  }
}

function draw() {
  background(20, 20, 50);

  // make every bubble move, bounce, and display 
  for (let i = 0; i < 100; i++) {
    bubbles[i].move();
    bubbles[i].bounce();
    bubbles[i].display();
  }
}

class Bubble {

  constructor(x, y, xSpeed, ySpeed, bubbleSize, redValue, greenValue, blueValue) {
    this.x = x;
    this.y = y;

    this.xSpeed = xSpeed;
    this.ySpeed = ySpeed;

    this.bubbleSize = bubbleSize;

    this.redValue = redValue;
    this.greenValue = greenValue;
    this.blueValue = blueValue;
  }

  // move the bubbles
  move() {
    this.x = this.x + this.xSpeed;
    this.y = this.y + this.ySpeed;
  }

  // change direction when the bubbles reaches an edge
  bounce() {
    if ((this.x > width) || (this.x < 0)) {
      this.xSpeed = this.xSpeed * -1;
    }

    if ((this.y > height) || (this.y < 0)) {
      this.ySpeed = this.ySpeed * -1;
    }
  }

  // draw the bubbles
  display() {
    noStroke();

    fill(
      this.redValue,
      this.greenValue,
      this.blueValue,
      150
    );

    circle(this.x, this.y, this.bubbleSize);
  }
}

My main idea was to combine control with randomness. I controlled the canvas, movement, and general appearance, but then the individual colors, sizes, positions, and speeds were chosen randomly. This makes the artwork organised while still allowing each version to look different.

 

Embedded Sketch

Problems I Ran Into

One problem I noticed was that some bubbles moved very slowly while others moved much faster. This happened because their speeds were chosen randomly. At first, I thought something was wrong with the slower bubbles, but then I understood that they had received a speed close to zero.

Another small issue was that parts of the bubbles sometimes went outside the canvas before they bounced back. This happens because the program checks the center position of each bubble. I decided to keep it because the bubbles still return and continue moving. Chiefly, whenever I ran into a problem, I mainly went back to the Week 3 slides that cover functions, OOP & Arrays, because they explained each of these concept clearly and showed the process step by step.

Week 2 Reading Reflection

Before watching the talk, I thought randomness in art mostly meant that the artist was giving up control. The talk changed my thought because his examples showed that chance can operate within rules chosen by the artist. I found Richter’s idea of “planned” chance especially convincing. Reas’ own projects also support this because he sets limits for features such as position, size, and direction, while still allowing unexpected results. I think Reas is slightly biased toward randomness because it has been important in his own practice for many years, however, he also admits that he is skeptical of this kind of work, so his argument does not feel completely one-sided.

In my own work, I plan to use randomness for the positions or colors of repeated shapes. I would still control the canvas size, available colors, shape sizes, and the area where objects can appear. For me, the best balance would be around 25% randomness and 75% control. Total randomness might produce something confusing, while complete control could make every result predictable. A smaller amount of randomness could make each version different without losing my original idea. Therefore, the talk made me wonder how much randomness an artist should use before the artwork feels out of control.

Week 2 – Assignment (Animation, Conditionals, Loops)

My Concept
When I thought about making a good piece of art using a for loop, the first idea that came to my mind was a Pac-Man design map. Pac-Man maps contain many repeated dots, so I thought a loop would be a useful way to create something similar without drawing every dot separately. My goal was not to recreate the original game exactly. I wanted to make my own simple maze-chase artwork inspired by it. I used blue lines for the maze, repeated white dots, a yellow player, and a simple red enemy. The yellow character follows the mouse, which makes the artwork interactive.

 

Code Highlight
The code I am particularly proud of is the loop that creates the dots:

for (let x = 50; x <= 550; x += 40)
circle(x, 60, 8);
circle(x, 340, 8);

I am proud of this part because I did not need to write a separate circle() command for every dot. The variable x starts at 50 and increases by 40 every time the loop repeats. This places the dots across the canvas with equal spaces between them. I used another similar loop to create the row of dots in the middle:

for (let x = 50; x <= 550; x += 40)
circle(x, 200, 8);

function setup() {
  createCanvas(600, 400);
}

function draw() {
  background(0);

  // Maze walls
  stroke(0, 100, 255);
  strokeWeight(8);

  line(20, 20, 580, 20);
  line(20, 380, 580, 380);
  line(20, 20, 20, 380);
  line(580, 20, 580, 380);

  line(100, 100, 250, 100);
  line(350, 100, 500, 100);
  line(100, 300, 250, 300);
  line(350, 300, 500, 300);

  // the top and bottom dots
  noStroke();
  fill(255);

  for (let x = 50; x <= 550; x += 40) {
    circle(x, 60, 8);
    circle(x, 340, 8);
  }

  // another loop to draw dots through the middle
  for (let x = 50; x <= 550; x += 40) {
    circle(x, 200, 8);
  }

  // Player
  circle(mouseX, mouseY, 50);

  // Player's mouth
  fill(0);
  triangle(
    mouseX,
    mouseY,
    mouseX + 30,
    mouseY - 15,
    mouseX + 30,
    mouseY + 15
  );

  // The Enemy
  fill(255, 60, 80);
  circle(500, 250, 50);
  square(475, 250, 50);

  // Enemy eyes
  fill(255);
  circle(490, 245, 15);
  circle(510, 245, 15);

  fill(0);
  circle(490, 245, 6);
  circle(510, 245, 6);
}

Embedded Sketch

How Was This Made?

I first made a black background and used blue line() commands to create the outside border and the simple walls of the maze. I used for() loops to repeat the small white circles across the map. The player was made with a yellow circle() and a black triangle() for its mouth. I used mouseX and mouseY as its coordinates, allowing it to follow the mouse. I also used an “if” and “else” statement to change the player from yellow to orange when it moves from one side of the canvas to the other. The enemy was created from a red circle and square, with smaller circles for its eyes. I referred to the loop and conditional examples from our class materials, specifically from the class Power Points from Week 2. I also used the official p5.js reference to understand the basic drawing commands.

 

Reflection and Future Improvements

This project helped me understand why loops are useful. Drawing every dot with a separate command would take a long time, but the loop made it shorter and easier to adjust. I also learned that changing the starting position, ending condition, or increment changes how many dots appear and how far apart they are. A challenge I would like to mention is when choosing the coordinates for the maze walls and making sure the dots stayed inside the canvas. I kept the maze simple because I just wanted to use the basic techniques that we covered in class. However, in the future I would like to make the player stay inside the maze walls instead of moving anywhere on the canvas. I could also make the enemy move, add more paths, or make the dots disappear when the player touches them. Chiefly I would like to make it a more realistic and applicable game and theme 

Week 1 – Self Portrait

My Concept
My concept was to create a simple self-portrait using the shapes and colors we learned in class. My self-portrait includes a face, hair, eyes, a nose, a mouth, ears, and a blue shirt. I also added a red cap as the interactive part of the portrait. The cap follows the mouse as the user moves it around the canvas.

I kept the design simple because I am still learning how coordinates, shapes, and colors work in p5.js.


A Code Highlight
The part of my code that I am particularly proud of is the moving cap:

// Cap
fill(170, 25, 25);
ellipse(mouseX + 65, mouseY + 25, 100, 25);

// Cap moves with the mouse
noStroke();
fill(200, 40, 40);
ellipse(mouseX, mouseY, 180, 80);

I am proud of this section because it makes my portrait interactive. Instead of giving the cap a fixed position, I used “mouseX” and “mouseY”. This causes the cap to follow the horizontal and vertical position of the mouse. I added numbers to the brim’s position so it stays connected to the main part of the cap.

function setup() {
  createCanvas(500, 500);
}

function draw() {
  background(180, 220, 255);

  // Shirt/Top
  noStroke();
  fill(60, 120, 200);
  square(150, 380, 200);

  // Ears
  fill(195, 140, 100);
  ellipse(145, 270, 40, 70);
  ellipse(355, 270, 40, 70);

  // Head
  fill(195, 140, 100);
  ellipse(250, 270, 200, 240);

  // Hair
// Hair
fill(50, 30, 20);
arc(250, 220, 190, 160, PI, TWO_PI);

  // Eyes
  fill(255);
  ellipse(210, 260, 42, 28);
  ellipse(290, 260, 42, 28);

  // Pupils
  fill(40);
  circle(210, 260, 14);
  circle(290, 260, 14);

  // Nose
  stroke(110, 70, 50);
  strokeWeight(3);
  line(250, 275, 240, 310);
  line(240, 310, 255, 310);

  // Mouth
  stroke(100, 30, 30);
  strokeWeight(4);
  line(225, 330, 250, 340);
  line(250, 340, 275, 330);

  // Cap 
  noStroke();
  fill(200, 40, 40);
  ellipse(mouseX, mouseY, 180, 80);

  // Cap that moves with mouse movement
  fill(170, 25, 25);
  ellipse(mouseX + 65, mouseY + 25, 100, 25);

  //  The mouse coordinates in the console
  print(mouseX + "," + mouseY);
}

 

Embedded Sketch
<>

How This Was Made:
I made this project in the p5.js Web Editor. I built the portrait by combining simple shapes, including square(), circle(), ellipse(), line(), and arc(). I used fill() to give the shapes different colors. I also used stroke(), noStroke(), and strokeWeight() to control the outlines.

The code inside setup() creates the canvas once. The code inside draw() runs repeatedly, which allows the cap to update its position whenever the mouse moves. Additionally, the order of the code is important because shapes drawn later appear in front of earlier shapes.

I used the official p5.js reference pages provided in class to check how the drawing commands work. Additionally I used the course week 1 power points as it gives a clear and broad explaination of all functions and codes I had to use to complete the portrait. Chiefly, every part of the portrait was drawn directly with p5.js shapes and colors.


Reflection and Future Improvements
This project helped me understand how basic shapes can be combined to create a recognizable person. I also learned that coordinates control where each shape appears and that the order of the code affects which shapes appear in front. The most difficult part was placing the facial features and hair correctly. I had to adjust their coordinates and sizes until they fit the head. Making the cap follow the mouse also helped me understand how mouseX and mouseY can make a sketch interactive. In the future, I could improve the portrait by adding more details to the hair, clothing, and background. I could also make the eyes follow the mouse or add more movement after learning additional p5.js commands.