Midterm Progress

Concept

For my midterm project, I initially considered creating an interactive experience centered around pet care in some way. While I wanted to explore the emotional connections and responsibilities that come with caring for a living creature, I thought this idea seemed kind of predictable. To add a touch of humor and absurdity, I decided to create an interactive experience where the user will cares for a pet rock (named Rocky) by feeding, playing and interacting with him to maintain his mood over a short period of time (1-2 minutes). The concept explores how minimalistic interactions, like feeding or playing, affect a virtual pet’s state of well-being.

While I still haven’t fully decided on the specifics, the user will have a few options to care for Rocky (feeding and playing for instance). Each interaction will influence the rock’s mood, with the goal of keeping him as happy as possible. For example, feeding might involve choosing from different food types, each of which impacts his mood differently while playing might involve a mini game where Rocky must avoid obstacles.

Code Design and Interactivity

In terms of coding, I’ve broken the project into several key components (I will probably be adding more later as different functionalities arise):

  1. Rocky : A class that handles the rock’s mood and his appearance on screen.
  2. Mood Meter: This reflects Rocky’s mood visually, giving feedback to the player.
  3. Buttons for Actions: Three buttons allow the user to trigger different actions (such as feeding and other care actions).
  4. Playing the Mini Game: This involves collision detection where Rocky avoids obstacles.

The game will end after the specified number of minutes, and Rocky’s final mood will be displayed.

What I’m Uncertain Of

The most challenging and uncertain part of this project is implementing the mini-game where Rocky plays by avoiding obstacles. Collision detection and ensuring the game flows smoothly without lag were concerns. To minimize these risks, I will start by prototyping the mini-game early. I will implement a basic version where Rocky moves up and down, avoiding obstacles that scroll from right to left. This will help me better understand how I can handle object collisions and movement dynamics. I also need to fine-tune ideas regarding the options available to the user to take care of Rocky.

Next Steps

Moving forward, I will continue implementing the basic features of the game, refining the interaction design, adding sound effects for feedback, and enhancing the overall user experience. I also plan to improve Rocky’s animations and ensure the game has a restart function. Overall, I’m pretty excited to see how this project turns out :))

Week 5 – Reading Reflection

After reading Computer Vision for Artists and Designers, I found myself reflecting on how this technology has made its way from industrial and military applications to creative fields like interactive art. One of the points that struck me is how accessible computer vision techniques have become, allowing artists and designers to explore new creative possibilities. It made me think about the similarities and differences between how humans and computers perceive the world. While human vision is complex, combining perception, intuition, and context, computers break down visual input into patterns, often missing the nuances that we take for granted. For example, when we see someone waving, we instantly understand the context — whether it’s a friendly greeting or an attempt to get attention, using cues like their expression and the setting. In contrast, computer vision algorithms like frame differencing detect only the motion of the hand, missing the gesture’s meaning. This shows us how computers rely on measurable inputs, while human vision combines objective information with subjective interpretation.

When it comes to helping computers track what we’re interested in, I think optimizing the physical environment plays a crucial role. The article discusses techniques like proper lighting and camera placement, which seem necessary for improving accuracy. These considerations remind me that even though we can program computers to “see,” there’s still a lot of fine-tuning involved to get the desired results. The tools mentioned, such as Processing and Max/MSP/Jitter, also seem promising for artists who may not have deep programming knowledge but want to experiment with computer vision.

I believe computer vision’s ability to track and surveil raises important questions about its use in interactive art. It offers exciting possibilities, such as creating responsive environments or immersive installations. However, it also introduces concerns about privacy and surveillance, especially when this technology is used outside artistic contexts. In interactive art, it can feel playful and creative, but the same technology in everyday spaces could feel invasive. This duality makes me wonder if we need to establish boundaries around how this technology is used, both for art and for broader societal purposes.

Assigment 4 – Words and Wizardry

Inspiration

Anyone who knows me also knows that I’m a huge fan of the Harry Potter series and I decided to use that as the base idea for this project involving text and data.  In whatever way I could, I wanted to recreate some sense of wonder and enchantment that I feel like I’m a part of every time I read one of the books or watch one of the movies. In the series, things often move and react in magical ways, and that gave me the idea to animate words and make them interactive, almost like they have a life of their own. Instead of having static text on the screen, I imagined how fun it would be if the words could scatter, repel, and float, just like magic.

Concept

The idea I finally arrived at involved a colorful word collage filled with randomly chosen and placed words from Harry Potter vocabulary (resulting in a different look/arrangement every time the code runs). When the user hovers near a word, it gets “pushed” away as if repelled by a magical force.  When the screen is clicked, these words disintegrate, breaking down into smaller particles, as though they’re dissolving or being pulled apart by magic. The disintegration adds an additional layer of visual intrigue, similar to a magical spell or force at work. Once the words have completely broken down, the particles fall to the bottom of the screen and disappear. In their place, a meaningful Harry Potter quote appears on the screen. This quote stays visible for 6 seconds, offering the viewer a moment to absorb the message, before the entire cycle then resets, creating a loop that gives the  experience a continuous flow.

Implementation

This is how the project turned out!

These are some of the most important parts of the code that I am proud of :))

1. Placing Words on the canvas

The first part of the project was figuring out how to place the words on the screen randomly. I wrote a function called placeWords() that tries to put each word at a random location. If the word overlaps with another, it shrinks until it fits. This way, each time the page is loaded, the words appear in different spots, making each experience unique.

// Function to place words randomly on the canvas
function placeWords() {
  placedWords = [];
  for (let i = 0; i < words.length; i++) {
    let word = words[i];
    let fontSize = 60;
    let success = false;
    
    // Trying to place the word until successful or until the font size is too small
    while (!success && fontSize >= 10) {
      let x = random(width);
      let y = random(height);
      let angle = random(1) > 0.5 ? 0 : HALF_PI;
      
      // Checking if the word can be placed at the given position, size, and angle without overlapping
      if (canPlaceWord(word, x, y, fontSize, angle)) {
        placedWords.push(createWord(word, x, y, fontSize, angle));
        success = true;
      } else {
        fontSize -= 2;
      }
    }
  }
}
2. Animating Words

Next, I wanted the words to move away from the mouse, like they were being pushed by an invisible force. I used the mouse’s position to calculate the distance between the mouse and each word. If the mouse gets too close, the word moves away. If it moves far enough, the word slowly returns to its original spot.

// Drawing "Hogwarts" word (stationary)
    drawWord(hogwartsWord);
    
    // Drawing all other placed words with repel effect
    for (let word of placedWords) {
      // Calculating the horizontal/vertical distance between the mouse and the current word's position
      let dx = mouseX - word.currentX;
      let dy = mouseY - word.currentY;
      let distance = sqrt(dx*dx + dy*dy); // calculating the total Euclidean distance between the mouse and the word using Pythagoras' theorem
      let maxDistance = 100;
      let repelStrength = 35; //strength of repelling force
      
      // If the word is within the repel range (closer than maxDistance)
      if (distance < maxDistance) {
        // Calculating the repelling force proportional to the distance (closer = stronger force)
        let force = (1 - distance / maxDistance) * repelStrength;
         // Applying the repelling force to the word's horizontal/vertical position, pushing it away from the mouse
        word.currentX -= dx / distance * force;
        word.currentY -= dy / distance * force;
      } else {
        // If the word is outside the repel range, gradually moving it back to its original position using linear interpolation
        word.currentX = lerp(word.currentX, word.x, 0.1);
        word.currentY = lerp(word.currentY, word.y, 0.1);
      }

 

3. Disintegrating Words

Finally, I wanted the words to break apart and float away, like a spell was cast on them. To do this, I turned each word into a set of particles that would fly off the screen when triggered. I mapped each word’s size to a number of particles and gave them random velocities to make the effect look more natural. This disintegration is accompanied by a famous Harry Potter quote (loaded from a file quotes.txt ) being displayed on the screen.

function disintegrateWords() {
  // Converting each word into particles
  for (let word of [hogwartsWord, ...placedWords]) {
    // Calculating the number of particles to generate based on the word's font size
    // Larger font sizes produce more particles (between 5 and 50 particles)
    let particleCount = map(word.fontSize, 10, 120, 5, 50);
    for (let i = 0; i < particleCount; i++) {
      // Pushing a new particle object into the particles array with initial properties
      particles.push({
        x: word.currentX,
        y: word.currentY,
        vx: random(-2, 2),
        vy: random(-5, -1),
        size: random(6, 10),
        color: word.color
      });
    }
  }
  
  // Clearing the words
  placedWords = [];

  // Selecting and display a random quote
  currentQuote = random(quotes);
  // Splitting the quote into lines of about 40 characters each
  currentQuote = splitQuoteIntoLines(currentQuote, 40);
  quoteStartTime = millis();
  quoteEndTime = quoteStartTime + quoteDisplayDuration;
}

Reflections and Further Improvements

One thing I’d like to improve is the collision detection when placing words. Right now, the words sometimes get placed in awkward spots if they shrink too much. I’d like to refine the placement system so the words always look balanced on the screen. It might be a good idea to have words be more crowded around the centered word (Hogwarts) and then spreading out gradually. Also, I think adding more magical effects, like words changing color or spinning, would enhance the overall experience.

This project helped me better understand how interactive elements can transform a simple idea into something engaging and dynamic. I look forward to adding even more magical effects to this canvas in the future!

References

https://www.bloomsbury.com/uk/discover/harry-potter/fun-facts/harry-potter-glossary/

Week 4 – Reading Reflection

Don Norman’s The Psychopathology of Everyday Things really opened my eyes to how much bad design affects our daily lives. His discussion of doors reminded me of my experience at NYUAD. I used to end up intuitively pulling doors with vertical long handles and pushing those with horizontal bars, and it wasn’t until a few weeks after I arrived that a friend pointed out there were no push or pull signs. I hadn’t even realized I was making these distinctions based on the design alone. It’s funny how my brain just figured it out without needing instructions, which shows how good design can guide us without us being fully aware of it. Norman’s ideas made me realize that so many products we use every day could be vastly improved if designers paid more attention to human-centered design. It is not just about creating something that works, but about creating something that’s easy to understand and use without frustration. I also found it interesting how he called out the way we often end up memorizing how to use devices rather than actually understanding them. I end up doing this fairly often, especially with kitchen appliances or electronics that have overly complicated settings.

One thing that really struck me was how affordances and signifiers play such a crucial role in how we interact with objects. This is something I hadn’t thought about in such specific terms before, but now it makes perfect sense. When I encounter a badly designed interface or physical object, it is often because the designer didn’t consider how obvious the next step would be for the user. This made me think of apps or websites where I’ve been completely lost—sometimes even a simple swipe or button press isn’t clear. A specific thing that drives me crazy is the lack of intuitive design in most remote controls. They often have so many buttons with unclear labels, and I find myself guessing which one does what. I think this could be improved by better mapping, where the placement and labeling of buttons are more aligned with common usage patterns, similar to Norman’s example of how good mapping improves ease of use in car seat adjustments.

Norman’s principles could be applied to interactive media by ensuring clear affordances and signifiers when designing digital interfaces. For instance, in a web application, making interactive elements like buttons stand out visually and providing immediate feedback when clicked would improve the user experience. Interactive media can benefit so much from human-centered design because it directly affects the user experience. After reading Norman’s work, I’m now even more aware of how essential it is to design not just for function, but for human behavior and understanding.

 

Assignment 3 – Celestial Drift

Inspiration

For this project, the task was to create a generative art piece. I decided I wanted to create something that captured the beauty of natural randomness, yet felt interactive and personal. I really love stargazing so this idea was immediately accompanied by a desire to incorporate stars (in a night sky setting) in some way. I thought it would be interesting to also use the stars to make randomly generated constellations. Initially, most of my ideas were all over the place and ended up progressing along with different stages of project.

Concept

After combining all of these concepts and also trying to add an element of interactivity, I arrived at a more cohesive idea. This piece essentially generates stars that slowly drift across the canvas and form constellations by connecting with nearby stars. These connections fade as the stars move farther apart, creating an ever-changing night sky. By clicking on the canvas, users can add new stars, and hovering the mouse near existing stars creates connections with the mouse pointer, making the viewer an active part of the art. I tried to replicate a portion of the night sky by creating a background gradient, which shifts from dark blue to a purplish hue.

Implementation

Here’s what it looks like!

The core of the project focuses on the generative placement and connection of stars, while other features such as mouse interactions and background gradients enhance the experience.

Most of the functionality of the code resides in the Star() class. I also initially created a global variable numStars which controls the initial number of stars that appear on the canvas (currently set to 70). However, more stars can be added when the user clicks on the screen.

Here are important aspects of the code that I’m proud of :))

1. Generating Stars and Constellations

The star generation begins by randomly placing stars across the canvas. Each star drifts slowly, giving the impression of a calm, subtly changing night sky. The stars are connected by lines if they are within a specific distance from each other, creating constellations. These lines fade with increasing distance between the stars they connect and disappear completely once they cross a certain threshold. The distance threshold is adjustable (maxDistance), allowing for varying constellations as stars drift closer or further from one another.

/ Connecting stars that are within a certain distance
  connect(stars) {
    for (let i = 0; i < stars.length; i++) {
      let d = dist(this.x, this.y, stars[i].x, stars[i].y);
      if (d < maxDistance) {
        stroke(255, 255, 255, map(d, 0, maxDistance, 255, 0)); // making line fade as distance increases
        line(this.x, this.y, stars[i].x, stars[i].y);
      }
    }
  }

2. User Interaction

User interaction is a key feature of the project. Clicking anywhere on the canvas creates a new star at the mouse’s location.

// Adding a new star at the mouse position when the mouse is clicked
function mousePressed() {
  let size = random(2, 5); // the star created has a randomized size
  stars.push(new Star(mouseX, mouseY, size)); // creating a new star at the mouse position (with given size)
}

In addition to adding stars, the mouse also exerts an influence on the stars already in place. When the mouse hovers near a star, stronger and thicker connections are drawn between the star and the mouse, creating a sense of gravitational pull. This connection changes based on the distance between the mouse and the stars, offering a layered sense of interactivity.

// Connecting stars according to mouse position
  mouseConnect() {
    let mouseDist = dist(this.x, this.y, mouseX, mouseY);
    
    // If the star is within the influence of the mouse, create more prominent connections
    if (mouseDist < mouseInfluenceDistance) {
      stroke(233, 217, 255, map(mouseDist, 0, mouseInfluenceDistance, 255, 50)); // Stronger lines with mouse
      strokeWeight(map(mouseDist, 0, mouseInfluenceDistance, 2, 0.5)); // Thicker lines near the mouse
      line(this.x, this.y, mouseX, mouseY); // Draw line to the mouse position
    }
  }

3. Gradient Background

The background gradient is crucial to creating a more realistic cosmic atmosphere. A vertical gradient transitions from a deep, dark blue at the top to a lighter, purplish hue at the bottom, simulating the natural gradient of a night sky fading into early dawn. This gradient creates a contrast to the white stars and their connections, making the work feel more immersive. In creating this gradient, I learnt how to use lerpColor(), which allowed me to smoothly blend two colors based on a transition value. By mapping the vertical position of each line to a gradient value, I was able to simulate the soft shift from night to early morning. The setGradient() function essentially draws horizontal lines from the top to the bottom of the canvas (slightly changing the color each time to create a smooth gradient).

// Creating a vertical gradient
function setGradient(x, y, w, h, c1, c2) {
  for (let i = y; i <= y + h; i++) {
    let inter = map(i, y, y + h, 0, 1); 
    let c = lerpColor(c1, c2, inter); // when inter is 0,  the colour is c1 and when inter is 1, the colour is c2 (for any other value it is a mix of c1 and c2)
    stroke(c);
    line(x, i, x + w, i); // drawing a line across the width of the gradient area
  }
}

Reflections and Further Improvements

This assignment gave me the chance to play around with randomness and interactivity in a simple yet engaging way. I enjoyed seeing how small things like mouse movement and clicks could bring the stars to life and create an immersive atmosphere. The project feels peaceful yet active, and I’m happy with how the core mechanics came together.

Looking ahead, I’d like to add more depth to the stars—maybe a twinkling effect or layered constellations with different star types. It could also be interesting to introduce sound, where each star interaction triggers a soft note, giving the project an audio element. Another idea is to have the background gradient shift gradually over time, mimicking the change from night to dawn for added realism. I could maybe also experiment with adding other celestial bodies like planets and nebulae.

Overall, I am pretty proud of how this turned out and look forward to making more advanced projects :))

Week 3 – Reading Reflection

Whenever I have a conversation with somebody not studying Interactive Media, I’ve never been able to explain the term “interactive” in a way that does justice to what it really means. It almost got me thinking that maybe there is no good definition, but rather just an understanding you develop once you’ve been exposed to the field. In this regard, reading “The Art of Interactive Design” by Chris Crawford was an eye-opening experience. I really liked how he broke down interactivity into three parts (listening, thinking and speaking), while also giving the example of a good human conversation to make sense of this meaning.

Crawford’s emphasis on degrees of interactivity, rather than just “interactive” or “not interactive,” really gave me a lot to think about. It reminded me of past projects where I thought I had created something highly interactive, only to watch users quickly lose interest. Now I’m wondering if I unintentionally created the equivalent of a “refrigerator light game” – technically interactive, but lacking depth. This reading also gave me ideas for improving my p5.js sketches, like using better algorithms to create more dynamic responses to user actions. But it also leaves me with the question: How much “thinking” does a system need to do before it feels truly interactive to users? Can we ever create digital interactions that match the richness of human conversation? In the end, can a system be truly interactive if it lacks purpose or understanding of the interaction, or is the perception of interaction by the user enough? These are questions I’ll be thinking about as I approach my next project, aiming to create something that goes beyond simple input-output and engages users in a more meaningful way.

Assignment 2 – Interactive Mandala

Inspiration

For this assignment, the task was to make a simple work of art using loops. My first thought was that  I wanted to make something that resulted in a visually appealing pattern of some sort (with an element of interactivity as well). As I was brainstorming ideas, I scrolled through my Pinterest boards and came across various dot mandala designs. The intricate patterns and vibrant colours of these mandalas instantly caught my eye, inspiring me to create a digital version that would capture the same sense of symmetry and beauty. I wanted to explore this concept – an effect where symmetrical shapes radiate out from a center point, creating an interesting pattern.

Concept

The core concept behind my project is to also incorporate a kaleidoscope-like pattern that keeps rotating, creating a mesmerizing visual effect. I aimed to use symmetrical shapes (circles) and a gradient of colors to mimic the aesthetic of traditional mandala designs. To add an interactive element, I decided to map the number of segments to the horizontal position of the mouse, allowing viewers to alter the complexity of the pattern by simply moving their cursor. This interaction not only makes the art more engaging but also gives viewers control over the visual complexity, making each interaction unique.

Implementation

Here’s the final product!

I started by setting up a square canvas with a black background to make the colours stand out. The origin was moved to the center of the canvas to simplify the rotation and placement of symmetrical shapes. I used two nested loop to create the series of symmetrical shapes (circles in this case) radiating from the center. Each shape is rotated by an equal angle to maintain symmetry. The number of these symmetrical segments is dynamically adjusted based on the mouseX variable, adding interactivity.

Something I explored on my own was how to use the rotate function and incorporated it for two purposes in the artwork:

  • To rotate the entire canvas continuously over time, creating the overall animation effect of the whole mandala rotating.
background(0); // black background
  translate(width/2, height/2);  // moving origin to the center of the canvas (instead of top left corner)

  // Rotating the entire canvas to animate the mandala
  rotate(frameCount * 0.6);  // rotating by frameCount * 0.6 to make the animation and control speed (since frameCount increases with every iteration of the draw() function)
  • To manage the placement of individual symmetrical segments of the mandala.
// Mapping the mouseX position to the number of symmetrical segments (between 6 and 30)
  numShapes = int(map(mouseX, 0, width, 6, 30));
  // print(numShapes);

  let maxRadius = 250;  // max radius (distance from center of canvas till edge) for shapes

  // Loop to create symmetrical patterns
  for (let i = 0; i < numShapes; i++) {
    push(); // saving current drawing style settings and transformations
    rotate((360 / numShapes) * i);  // rotating each shape by equal angles

While working on this project, I also learned to use the map() function, which became necessary for adding dynamic and interactive elements. Initially, I found it challenging to map values between different ranges, but experimenting with map() helped me control aspects like the number of segments, shape sizes and color gradients. By mapping the mouse position to the number of segments, I could easily adjust the pattern’s complexity, and mapping distance to hue allowed for smooth color transitions.

Another thing I did differently was use the HSB (Hue, Saturation, Brightness) colour mode instead of traditional RGB values or HEX codes. This was mainly done to create the smooth gradient that changes as you go outwards in the mandala. By mapping the shapes’ distance from the center to the hue value, I achieved a transition in colour that adds to the overall visual appeal.

Reflections and Further Improvements

Working on this project taught me a great deal about the creative potential of code. It also deepened my understanding of how symmetry and rotation can turn simple elements into complex, visually appealing patterns. Beyond the technical skills, I discovered the importance of experimentation and iteration in the creative process, allowing me to refine my ideas to achieve the outcome I was looking for. For this project, I used circles to keep the design simple, but to achieve a more authentic mandala feel, I might want to incorporate other shapes of varying sizes in the future. This would add complexity and better mimic the intricate details often seen in traditional mandala designs. Overall, this project was a rewarding experience that broadened my perspective on combining art and coding.

Week 2 – Reading Reflection

I enjoyed Casey Reas’s talk more than I expected to, especially considering that this was the first time I had heard the idea of “randomness” and “chance” being used in an artistic context as compared to a math or probabilistic one. After I began to appreciate this notion of chance in art, I was struck by how even this is very subjective and can be used in countless ways.  One example of this is when Casey Reas talked about the concept of decision-making regarding the level of randomness incorporated into artwork. This means that artists sometimes also make conscious choices about how much of their work they leave to chance, creating “a delicate balance between order and chaos”. This also remined me of the quote by Gerhard Richter:

Above all, it’s never blind chance: it’s a chance that is always planned, but also always surprising. And I need it in order to carry on, in order to eradicate my mistakes, to destroy what I’ve worked out wrong, to introduce something different and disruptive. I’m often astonished to find how much better chance is than I am.

What I found extremely interesting about this idea was the intentionality behind randomness in art. It is about letting go of complete control but not entirely abandoning it, which can lead to unexpected, sometimes better outcomes than planned. This challenged my initial assumption that randomness in art is purely accidental and without thought. In the end, it made me contemplate: what exactly is the role of the artist? Is he still the creator of the work, or merely a medium that guides chance to reach the final piece? It also made me consider how we can use randomness not just to fill gaps but as a crucial tool for innovation and breaking away from mistakes.

One part of the talk that made it more interesting for me was the use of examples and actual works of art to illustrate this use of randomness. For instance, I found it very intriguing that something seemingly simple like the Table of Random Numbers could have such widespread use across several industries. I also liked the example of the piece “Fractal Invaders”. The idea of using a coin flip to generate art created very interesting results, but what was even more interesting was how symmetry and duplication suddenly sparks our imagination and makes us see figures in the art. It made me think that something that might initially seem highly structured or algorithmic can still engage the imagination in many ways. Overall, the talk made me rethink the creative potential of combining strict rules with the freedom of randomness, and helped me see that the “unexpected” is an important element in the artistic process.

Assignment 1 – Self-Portrait

I saw this assignment as an opportunity to get creative with p5.js and make something visually appealing using basic shapes, while also adding some elements of interactivity. I have had some experience with coding and I’m also really passionate about design, so overall, I really loved how this project made me think of new ideas and navigate the challenges that came up.

Main Idea

For this portrait, I wanted to create something that truly represents a part of me. As someone who absolutely loves books, I decided that a simple library setting (with a bookshelf) would perfectly capture this passion. Instead of going for a generic self-portrait, I focused on the details that define my personality, aiming to reflect my love for reading in both the visuals and interactivity of the piece.

Implementation

Creating the library scene involved several key steps, from drawing the bookshelves to the self-portrait itself. The books in the library are not just static; they come alive through interactivity, making the scene more engaging and fun. Every time you hover your mouse over a book, it bounces up and down, creating a playful effect. I’m particularly proud of the way the books bounce—implementing this took some effort, as it involved calculating the physics for a smooth jumping motion and resetting them back to their original positions. A fun surprise was discovering how, when you swipe the mouse across a row of books, it creates a wave effect, adding another layer of interaction.

Here’s a snippet of code that controls the bouncing of the books :))

// Drawing books with jumping effect
  for (let i = 0; i < books.length; i++) {
    let book = books[i];

    // Checking if the mouse is hovering over book
    if (
      mouseX > book.x &&
      mouseX < book.x + book.width &&
      mouseY > book.y &&
      mouseY < book.y + book.height &&
      !book.isJumping
    ) {
      book.isJumping = true; // book starts jumping when hovered
      book.velocity = -5; // initial jump velocity
    }

    // Handling jumping animation
    if (book.isJumping) {
      book.y += book.velocity; // updating y position based on velocity
      book.velocity += 0.4; // applying gravity effect

      // checking if the book has fallen back to its original position on the shelf
      if (book.y >= book.originalY) {
        book.y = book.originalY; // resetting position to the shelf
        book.isJumping = false; // stop jumping
        book.velocity = 0; // resetting velocity
      }
    }

 

Another feature I implemented is the colour change of the book held by the girl in the portrait. When you click on any book in the library, the book’s colour changes to match the one clicked, and I think this really adds to the interactivity of the scene and somehow just makes it seem more of a representation of my personality.

This is the code that controls the book changing colour:

function mousePressed() {
  // Checking if a book is clicked
  for (let i = 0; i < books.length; i++) {
    let book = books[i];
    if (
      mouseX > book.x &&
      mouseX < book.x + book.width &&
      mouseY > book.y &&
      mouseY < book.y + book.height
    ) {
      // Changing the girl's book color to the clicked book's color
      girlBookColor = book.color;
    }
  }
}

 

One of the most challenging parts of the drawing was the hair, which required understanding how the bezierVertex() function works. I spent time experimenting with the curves to get the right look, and I’m happy with how the hair flows in the final version. I also focused on the randomization of book sizes, spacing and colours to create a more realistic and dynamic library scene. The varied spacing between the books was particularly important because it prevented the scene from looking too uniform and added to the realistic clutter you’d expect in a real library.

Reflections and Possible Improvements

I’m proud of how the self-portrait captures a unique part of me through both the visuals and interactions. The bouncing books, the randomization of elements and the changing book colours all work together to create a portrait that isn’t just about how I look, but about what I love. The process was a great learning experience, especially in terms of coding the animations and achieving a realistic look using basic p5.js knowledge.

Possible improvements include adding more interactive features, such as having the girl’s expression change when clicking on different books or adding a subtle glow effect around the hovered book to enhance the visual feedback. Also, optimizing the code for smoother animations, especially when multiple books are interacting simultaneously, would enhance user-experience. Overall, I really enjoyed this project and look forward to exploring more of my creative potential throughout the course.