Week 1 — Self Portrait

1.   Sketch and Code


https://github.com/msbarakat/Week-1—Self-Portrait/blob/470da2fff0ad5bb62a80e6fb0e2998a861ac0dac/sketch.js

2.   Overview

For our first assignment, I developed a sketch that is a non-literal self-portrait. The project features a shark – my favourite animal – swimming through a deep-sea environment. The sketch incorporates procedural animation, gradient rendering, and state-based movement logic.

3.   Concept

My goal of this project was to communicate identity through something other than a human face. I chose a shark because it is my favourite animal. In fact, I own a vast collection of shark themed items in real life, so it felt like the most authentic representation of my personality.

4.   Process and Methods

My process began with translating shark anatomy into geometric shapes:

    • I broke the shark down into a main body (ellipse), a tail (triangles), and facial structure (lines and arcs).
function drawSharkSprite() {
  noStroke();
  fill(160); 
  
  // BODY
  ellipse(85, 60, 150, 50); 
  
  // TAIL
  let tailX = 145;   // Local variable
  triangle(tailX, 45, 185, 60, tailX, 75);  // Connection fin
  triangle(195, 95, 145, 45, 185, 60);      // Bottom tail lobe
  triangle(200, 30, 145, 75, 185, 60);      // Top tail lobe
  
  // FINS
  triangle(90, 15, 65, 40, 95, 40);
  
  // GILLS
  stroke(80); 
  strokeWeight(1);
  noFill();
  for(let i = 0; i < 3; i++) {
    let gx = 65 + (i * 5); // Spacing the gills
    arc(gx, 60, 10, 25, -HALF_PI, HALF_PI);
  }

  // --- HEAD DETAILS ---
  noStroke();
  // Teeth
  fill(255);
  for (let tx = 25; tx < 55; tx += 6) {
    let slantY = map(tx, 25, 55, 72, 65); 
    triangle(tx, slantY, tx + 6, slantY, tx + 3, slantY + 7);
  }
  
  // Slanted Eye
  stroke(0); 
  strokeWeight(3);
  line(25, 58, 35, 52); 
  
  // Slanted Mouth Line
  stroke(166, 58, 55); 
  strokeWeight(2);
  line(22, 72, 58, 65); 
}
    • I studied some p5.js functions to avoid static movement of the shark. Instead of the shark simply sliding across the screen, I used the sin() function to give it a bobbing effect.
// Apply bobbing motion using sin() to the Y translation
translate(shark.x, shark.y + sin(shark.yOff) * 10);
scale(2.0); 
drawSharkSprite();
5.   Technical Details
    • To create depth, I wrote a drawOcean() function that uses a for loop to iterate through the canvas height, and using the lerpColor() function transitions from a darker blue to a lighter blue.
    • For the bobbing motion of the shark, I had to make a sort of mathematical function to make it look like the shark is floating in the water. The y-axis position of the shark is updated in the updateShark() function, which makes it so that the values of the y-offset (animation timer) are altered accordingly to be used in the sine function.
function updateShark() {
  shark.x += shark.vx;
  shark.y += shark.vy;
  shark.yOff += 0.05;    // Increment animation timer

  // Boundary checks
  if (shark.x < 30 || shark.x > 220) shark.vx *= -1;
  if (shark.y < 40 || shark.y > 220) shark.vy *= -1;
}
    • To keep the shark within the visible “ocean” and prevent it from swimming off canvas, I implemented a kind of “bounce” motion with a collision system. Since the shark’s movement is controlled by a y and x velocity, its direction can be reversed by simply flipping the sign of the values if the shark passes a certain x or y value.
    • Rather than drawing each tooth and gill individually, I used loops to ensure that, if the shark’s position changes, the features remain aligned..
    • I used translate() and scale() within the draw() loop to allow the shark to move as a single unit without having to update the (x,y) coordinates for every single shape in the sprite.
6.   Reflection

This project was a significant learning curve in managing coordinates. Initially, my shark would fall apart when it moved because the fins weren’t “attached” to the body’s x and y variables. Learning to use translate() solved this by creating a new local coordinate system for the shark. Also, I had a lot of trouble with the “bounce” mechanism of the shark before properly understanding how the coordinates worked. I am proud of my final result, but I hope that in the future I will be able to complete the coding process quicker now that I’ve better grasped some of the built-in functions and coordinate system.