Week 3 — Reading Reflect Interactivity

I thought the way Crawford wrote this paper was really interesting because it was structure in relaxed and reflect-based mannerism to describe what interactivity means. To Crawford, his definition of interactivity was a spectrum of based on the principle of two parties listening, thinking, and speaking. Initially, I was a bit taken aback by his definition especially when he brought up the examples of books and dancing, but towards the end of his article I came to an understanding and agreement with his argument. I feel interactivity should invoke an experience for the individual and the program itself should react to what the user has input, whether it be through speak or physical action.

When reading his paper, it reminded of modern popup art instillation where individuals could walk through an exhibition and the art itself was what the user created through pressing button or generated through movements. I feel like interactivity has definitely come a long way and to me it seems like artists are starting to take notice and incorporate it into their design. Also, through his structure of writing, it almost felt intentional because he wanted the article to be interactivity by suggesting the reader to contact him by email and leaving a personal touch with the reader.

As such, I feel a strong interactive system has the ability to connect with the user and make them feel something emotion when they are experiencing the project. At the same time the use is also able to control the environment around them and change how they perceptive the project. In my project, I hope to improve the degree of user interactions by hopefully having a “wow” factor when the person first sees my project, and after that experience, they’re able to explore more and have the ability to interact with the system.

Week 3 — Water Lily Pond OOP

SHORT DESCRIPTION: 

In week 3 of intro to IM, we were introduced to the concept of functions, arrays, and object-oriented programming. For my project. I decided to generate a lily pad pond with unique set of flowers, then for each object they would bounce off the walls or bound off of each other. I create two object instance class, one for the lily pads and one for the flowers whose locations are dependent on the lily pads.

Design Concept 

Last week, I had created an abstract water lily pond, and you can call me uncreative, but I just REALLY, REALLY wanted to create an aesthetically looking water lily pond. With last week’s assignment, the art had changed rapidly giving a sense of discomfort and urgency, and I wanted this week’s project to have a slower and relax feeling. Especially for me studying away in Abu Dhabi, I feel like my life has been so chaotic with settling into a new environment, experiencing new cultures and lifestyle, and adjusting into the new academic routine has been overwhelming.

As such, I am glad I choose to do a water lily pond because it kept my grounded and allowed me to relax. While I am happy with the end result, I do wish I could have added more elements into my project (rain, ripples, fish, etc) and made it more interactive. However, due to the time constraints of my schedule, I did the best I could and added as much detail with shading and colors to the elements I currently have on canvas.

Coding Processes

I began my project by referencing Ball Class program we had gone over in class since the shape of my lily pads would also be circular and stay within the boundaries of the screen. Functions with collisions were initially the most confusing part for me, and taking the time to digest the logic ultimately allowed me to then implement a function that checked for object collision – which is shown below.  The function below would use the distance formula to calculate the distance between the center of one object to the center of another object. Then if the distance was less than the sum of the objects’ radius, that meant there was an overlap, and the objects must then change direction. To change the direction, I simply just exchange the x-y speeds between the two objects, so they would then move in the opposite direction.

checkLilyCollision(otherLily) {
   // compute the distance between the current lily with the other lily 
   let distance = dist(this.lilyX, this.lilyY, otherLily.lilyX, otherLily.lilyY);
   
   // if the distances between two lilys are less than the sum of the radius 
   if (distance < this.radius + otherLily.radius){
     let tempSpeedX = this.lilySpeedX;
     let tempSpeedY = this.lilySpeedY; 
     
     // exchange direction and speed of the colliding lilies 
     this.lilySpeedX = otherLily.lilySpeedX; 
     this.lilySpeedY = otherLily.lilySpeedY;
     otherLily.lilySpeedX = tempSpeedX;
     otherLily.lilySpeedY = tempSpeedY; 
   }
 }

Additionally, I had also started by played around with the arc() function, in order to achieve the tiny slit for the lily pad. Below was a code sketch of the degrees which I wanted my lily pads to look.  From there, I dove deep into randomization the attributes of the lily pad class. Most properties such as speed, rotation, location, initial angle, etc were randomized using the random() or Math.random() function because I wanted each execution of the program to create a different and unique portrait.

function waterLily() {
   fill('rgb(42,140,42)'); // color of the lilypad
   arc(100, 100, 80, 80, 0, 11 * PI/6); 
 } 

Admittivity, I had a problem with overlapping lily pads with each execution of the program and had to rely on Chatgpt to help me resolve the issue. They had suggested to test over 1000 attempts and test if a new instance lily pad object would overlap with an existing lily pad object. I did change and delete a few lines of code Chatgbt provided, but below is what I ended up in my code.

function generateLily(){
  for (let i = 1; i < numLily + 1; i+= 1){
    let validPosition = false;
    let attempts = 0;
    while (attempts < maxAttempts && !(validPosition)){
      ...

      if (isLilyPositionValid(newLilyObject)){
        gLilyArr.push(newLilyObject);
        validPosition = true;
      }
      
      attempts += 1;
    }
  }
}

function isLilyPositionValid(newLilyObject){
  let initalSpacing = random(3,9)  
  // for each existing lily within the lily array 
  for (let existingLily of gLilyArr) {
    let distance = dist(newLilyObject.lilyX, newLilyObject.lilyY, existingLily.lilyX, existingLily.lilyY);
    if (distance < newLilyObject.radius + existingLily.radius + initalSpacing) {
      return false; // Overlap detected
    }
  }
  return true; // No overlap detected
}

When I completed my lily pads, I moved onto the flowers, which were my favorite and proudest section of my program. I created another class for my flowers for it be at the center of the lily pads to have a random number of petals, rotation, and combination of color. I used push() and pop() functions that I learned from my first assignment to save and reset the state of the canvas, alongside translation() which set the center of the flower to the center of the lily pad I was currently working on. I did have a problem with the layers stacking on top of each other and the color and degree of the layers changing each frame, but in the end, I was able to get it fixed by creating a unique array for the flower’s color, rotation, and layers.

Final Design

Below is the final program for this assignment. Overall, I am happy with the movement of the lily pads and how each of the flowers turned out. I liked how it is unique for each execution of the program, but it isn’t too overwhelming to the user. There were a lot of technical problems throughout the project, but the concept of a calm and pretty end project kept me motivated to continue working.


 

 

 

 

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.

Week 3 – Object Life Sim

final product

For this project, I would like to start by presenting the final product.

Instruction: To change the starting condition, edit the initial parameters in ‘sketch.js’

Description (This part of the text is summarized by GPT-4o from my other words and codes):

The simulation involves various instances, such as objects, foods, and sites, each with distinct behaviors. It emphasizes resource management (hunger), spatial awareness (movement and separation), and lifecycle dynamics (aging and reproduction), creating a dynamic system where objects interact with each other and their environment.

  1. Objects: These are the primary entities that move around the simulation. They have attributes like position, age, size, speed, hunger, and status (e.g., doodling, mating, eating, working). Objects can interact with other objects and food sources.
  2. Movement: Objects move based on their speed and direction. They can either follow a target (another object or food or site) or move randomly. If they encounter the edges of the simulation area, they reverse direction. They also avoid crowding by maintaining a separation distance from others.
  3. Hunger and Status: Objects experience hunger, which affects their status and behavior. When hungry, they look for food. If they consume food, their hunger decreases, and they may reproduce if conditions are favorable. Different statuses trigger different actions (e.g., eating, mating, working).
  4. Aging: Objects age over time, with their aging rate influenced by their status. For example, being full while mating speeds up aging while being hungry slows it down. If an object’s age exceeds its maximum, it dies.
  5. Reproduction: When certain conditions are met (like being sufficiently hungry), objects can reproduce. New objects are created with attributes based on the parent object.
  6. Interaction with Food and Sites: Objects can consume food to reduce hunger and may interact with sites to produce extra food on the canvas. Reaching food or sites changes their status and can trigger further actions.

concept

While there are certainly many inspirations, including Simmiland (a God-like card game), John Conway’s Game of Life, the path drawing project from Raes’ presentation, and P5 reference projects (bouncing balls, flocking behavior, Perlin noise, etc.), the idea first came to me as a reminder to think about the nature of simulation as well as how the routined life has alienated humans to be objects subjected to rules – hence the title “Object Life Sim.”

Figure 1: Simmiland (The playing God idea and the color scheme reference)

The paradox lies here, as the nature of simulation suggests that it is trying to imitate something superior, something intricate and more complex, it is so weird that if the life itself is already institutionalized, then what’s the point of simulating it? Isn’t it going to result in an Ouroboros? Yet, there’s an understated allure in simulating our surroundings and engaging with them at minimal cost, which has given rise to this very basic simulation of a life reduced to objects. Or, perhaps these are, in a way, the most crucial simulations?

Figure 2: Game of Life (Resource and reproduction reference)

Another motivation to do so – to play God for a moment – emerged during in our first class discussion. As we delved into the role of randomness in art, I held the belief that randomness could be an intrinsic element, present even in Mondrian’s analytical paintings or the precisely proportioned sculptures of ancient Greece. However, I was surprised by the idea of how possible it is for art to be random, brought up by a classmate. This prompted me to reconsider whether the prevalent randomness in today’s generative art detracts from its legitimacy as art. Then I came up with the analogy of the creation of the world – if the world was created by a deity with a singular act (akin to the First Cause) and then left to evolve independently, can it still be considered the deity’s creation?  Similarly, if the set of algorithms behind a piece is designed by human, and the initial set of parameters is decided by human, is it our creation? While my stance is affirmative, as I believe the eventually tangible ‘piece’ is not the art itself but separate from it or only plays a conduit and could be reached however we want, I would still like to pose this question for your contemplation.

CODE & Production SNIPPETS

Again, as it would be tedious to go through the structures and details in the code, I will only introduce some of the sources I used and some interesting parts of them from my perspective.

First, when it comes to reading the keyboard inputs with keyCode, it is very useful to have this website to know how the keys are linked to key codes. This enables me to set up different conditions by combining keyboard and mouse together to create the control logic:

function mouseClicked() {
  // Spawn new instances at the mouse location when clicked with different keys pressed
  if (keyCode === 79) { // If the last pressed button is 'O'
    initiateObject(mouseX, mouseY); 
  } else if (keyCode === 70) { // If the last pressed button is 'F'
    foodArray.push(new Foods(mouseX, mouseY, setMaxUtility)); 
  } else if (keyCode === 83) { // If the last pressed button is 'S'
    siteArray.push(new Sites(mouseX, mouseY, setMaxUtility));
  } else {
    // If the simulation hasn't started, initiate it and create initial objects
    if (simStart === false) {
      simStart = true; // Set the simulation start flag to true
      for (i = 0; i < initialObjectNum / 2; i ++) {
         // Spawn initial objects off-screen
        initiateObject(random([0 - initialSize / 2, windowWidth + initialSize / 2]), random(windowHeight));
        initiateObject(random(windowWidth), random([0 - initialSize / 2, windowHeight + initialSize / 2]));
      }
    } 
  }
}

Another useful source is the Unicode list for emojis (Yes, I learned to use emojis to draw stuff this time!) For example, I used it to set up random food emojis for my Foods class:

let foodIcon = ['\u{1F35E}', '\u{1F950}', '\u{1F956}', '\u{1FAD3}', '\u{1F968}', '\u{1F96F}', '\u{1F95E}', '\u{1F9C7}', '\u{1F9C0}', '\u{1F356}', '\u{1F357}', '\u{1F969}', '\u{1F953}', '\u{1F354}', '\u{1F35F}', '\u{1F355}', '\u{1F32D}', '\u{1F96A}', '\u{1F32E}', '\u{1F32F}']

class Foods {
  constructor(tempX, tempY, maxUtility, 
               tempSize = 10) {
    this.x = tempX;
    this.y = tempY;
    this.size = tempSize; // Set the initial size
    this.type = 'food';
    this.utility = random(0.5, maxUtility)
    this.status = null;
    this.icon = random(foodIcon)
  }
  
  // Display the object on canvas
  display() {
    fill('#ffd7a0'); // Set the brightness of the object based on the age
    noStroke();
    circle(this.x, this.y, this.size * this.utility + 10);
    
    textSize(this.size * this.utility);
    textAlign(CENTER, CENTER);
    text(this.icon, this.x, this.y);
  }
  
}

Next, I’d like to show two pieces of the core functions for my Objects to move. The first one finds the closest target on the canvas of its kind, and the second one is the exact math to calculate the movements. It is rather easy to have the objects move directly towards a target (I only have to copy-paste a bit from my first portrait project), while including the collision algorithm and the strategies to maneuver around is something more difficult for sure.

  find(arrayToFind) {
    let closestPoint = null; // Placeholder for the closest point
    let minDistance = Infinity; // Start with a very large distance
    let distance; // Variable to store calculated distance
    let ix, iy; // Coordinates of items in the array

    // Function to calculate the distance between two points
    const calculateDistance = (x1, y1, x2, y2) => {
      return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); // Return Euclidean distance
    };

    // Iterate through the array of inquiry to find the closest object
    for (let item of arrayToFind) {
      
      ix = item.x; 
      iy = item.y;
      
      if ((ix === this.x) & (iy === this.y)) { 
        distance = Infinity; // Set distance to infinity if it's the same object
      } else {
        distance = calculateDistance(this.x, this.y, ix, iy); // Calculate distance to the item
      }
      
      // Update the closest point if the current distance is smaller
      if (distance < minDistance) {
        minDistance = distance; // Update minimum distance
        this.destObject = item; // Set the closest object as the destination
      }
    }
  }

Initially, my strategy after a collision was to let the objects nudge a bit randomly, which resulted in sticking in place with jerking behaviors. Then, I set up a strategy to let the objects escape in the opposite direction from the collision – an idea borrowed from bouncing balls. However, as in my simulation, moving toward the target is still a necessity after escaping; it resulted in the objects sticking in a line. So, I modified the strategy to slide around the collided objects, but it still didn’t work, leading to the objects rotating in place. At the end of the day, I worked through the algorithm of flocking behaviors mentioned in class and borrowed the separation to combine with my sliding behavior and put up the piece.

  move(arrayToFind) {
    this.find(arrayToFind); // Find the target object
    
    // Setup destination coordinates from the target object
    this.destX = this.destObject.x;
    this.destY = this.destObject.y;

    // Calculate the distance to the destination
    let dx = this.destX - this.x;
    let dy = this.destY - this.y;
    let distance = Math.sqrt(dx * dx + dy * dy);
    
    // Normalize the direction vector
    if (distance > 0) {
        this.directionX = dx / distance;
        this.directionY = dy / distance;
    } else {
        this.directionX = 0;
        this.directionY = 0;
    }

    // Calculate the next position
    let nextX = this.x + this.directionX * this.speed;
    let nextY = this.y + this.directionY * this.speed;
    
    // Check for collision with the destination object
    if (this.destObject) {
      let targetCombinedRadius = (this.size + this.destObject.size) / 2; // Adjust based on size
      let distToTarget = Math.sqrt((nextX - this.destObject.x) ** 2 + (nextY - this.destObject.y) ** 2);

      // If colliding with the target object, invoke reach
      if (distToTarget < targetCombinedRadius) {
        this.reach(); // Call reach() if colliding with the target
            
        // Slide away from the target
        let targetNormalX = (this.x - this.destObject.x) / distToTarget; // Normal vector
        let targetNormalY = (this.y - this.destObject.y) / distToTarget;

        // Calculate the sliding direction (perpendicular to the normal)
        let targetSlideX = -targetNormalY; // Rotate normal to find tangential direction
        let targetSlideY = targetNormalX;

        // Introduce a small random adjustment to sliding direction
        let targetRandomAdjustment = random(-0.1, 0.1); // Adjust as needed
        targetSlideX += targetRandomAdjustment;
        targetSlideY += targetRandomAdjustment;

        // Normalize the sliding direction
        let targetSlideDistance = Math.sqrt(targetSlideX * targetSlideX + targetSlideY * targetSlideY);
        if (targetSlideDistance > 0) {
            targetSlideX /= targetSlideDistance;
            targetSlideY /= targetSlideDistance;
        }

        // Move along the sliding direction away from the target
        this.x += targetSlideX * this.speed * 0.3; // Slide from the target
        this.y += targetSlideY * this.speed * 0.3;

        return; // Stop further movement after reaching
      }
    }
    
    // Maintain separation distance from other objects
    let separationDistance = this.size * 1.25; // Desired separation distance
    let separationForceX = 0;
    let separationForceY = 0;

    for (let other of objectArray) {
      // Skip if it's the same object or the target object
      if (other === this || other === this.destObject || other.status === 'mate') continue;

      // Calculate distance to the other object
      let distToOther = Math.sqrt((nextX - other.x) ** 2 + (nextY - other.y) ** 2);

      // If the distance is less than the desired separation distance, calculate a separation force
      if (distToOther < separationDistance) {
        let diffX = nextX - other.x;
        let diffY = nextY - other.y;
        
        // Normalize the difference vector
        if (distToOther > 0) {
            separationForceX += (diffX / distToOther) * (separationDistance - distToOther);
            separationForceY += (diffY / distToOther) * (separationDistance - distToOther);
        }

        // Sliding behavior
        let slideFactor = 0.3; // Adjust as needed for sliding strength
        let slideX = -diffY; // Perpendicular to the normal
        let slideY = diffX;

        // Normalize sliding direction
        let slideDistance = Math.sqrt(slideX * slideX + slideY * slideY);
        if (slideDistance > 0) {
            slideX /= slideDistance;
            slideY /= slideDistance;
        }

        // Apply sliding movement
        nextX += slideX * this.speed * slideFactor;
        nextY += slideY * this.speed * slideFactor;
      }
    }

    // Apply the separation force to the next position
    nextX += separationForceX;
    nextY += separationForceY;

    this.x = nextX;
    this.y = nextY;
    
    if (frameCount % 10 === 0) {
      // After updating the position
      this.positionHistory.push({ x: this.x, y: this.y });

      // Maintain the history size
      if (this.positionHistory.length > this.historyLimit) {
        this.positionHistory.shift(); // Remove the oldest position
      }
    }
    
  }

OBSERVATION

Lastly, now that the project is a simulation, I believe the observation of its behaviors matters a lot. While I do not have much time to fully explore the parameters and settings, here are a few general observations:

Figure 3: It is evident that the sites, as the source of food, have the most path towards and surrounded.

Figure 4: As the simulation goes on, the larger objects could start to hinder the movements of the others.

Figure 5: Towards the end of a simulation, no matter if the objects are in a healthy state, the behavior turns out to be more aimless as there is no incentive to interact.

Figure 6: The greater the average resource per area (in other words, the smaller canvas + the same amount of resource), the longer the simulation lasts.

Reading Reflection – Week #2

Casey Reas’ view on the role of randomness largely resonates with me – I have valued the loss of order in artworks before, but I have not thought in depth about the possibilities that this provides to creators from different backgrounds. Thinking about randomness generated by computer, I have always regarded it “pseudo-random”, knowing that there are still specific algorithms that guide the output. In this sense, the quote from “The digital computer as a creative medium” by Michael Noll was eye-opening to me: “… full exploitation of those unique talents for controlled randomness and detailed algorithms can result in an entirely new medium”This conclusion is not an obvious one, and this is what makes coding so fascinating to me – there are so many aspects under the control of the developer, that chance brings uniqueness to an outcome that could supposedly be predicted.

The interconnectedness of randomness and control is still confusing to me, and I believe that there should be a balance defined by everyone by themselves, not a universal one. In my works, I wish to include elements that go out of orderly more often, developing algorithms that follow a logic resulting in an unforeseen outcome, but do not become pure improvisations. Letting something go out of control is scary, but I have learned that uncertainty can bring beauty to the final result.

Reading Reflection – Week #3

As I searched for the definition of “interactivity,” I found two distinct meanings placed side by side: (1) the process of two people or things working together and influencing each other, and (2) the ability of a computer to respond to a user’s input. In The Art of Interactive Design, Chris Crawford claims that the term “interactivity” is commonly “misused and misunderstood” due to the prevalence of the second definition. He challenges this misinterpretation by outlining three essential criteria for true interaction: (1) listening, (2) thinking, and (3) speaking. Importantly, Crawford argues that all three principles must be equally present in both “actors” of the interaction, with no trade-offs. This helps to clearly differentiate between interaction and mere reaction (such as reading a book) or participation (like dancing to music), which, as I agree, are not truly interactive activities.

While I found the text enjoyable overall, some examples provided by Crawford were based solely on his personal assumptions (for instance, his discussion of performance art and the extent of interaction involved). This led me to reflect on a question posed at the beginning of the chapter that remained unanswered: what is the role of subjectivity in interactivity? How much of interaction depends on the perspective of the individual interactor?

From the text, I gathered that there is some subjectivity in interactivity, which Crawford acknowledges. However, he also emphasizes that an objective foundation for interactivity exists as well, rooted in the essential definition of interaction. I agree with this view and also concur that defining interactivity merely as “the ability to respond to input” is a misuse. Such a limited definition can constrain designers. Therefore, in my future artworks, I plan to implement Crawford’s “rule of three” when assessing the interactivity of my code.



Assignment 2: loops

Concept

I have decided to continue the ideation I have worked on in the first work – as such, the colour palette and the style of visual elements remain the same, but the story has developed.

The picture is almost surreal – the frame is filled with identical eyes staring at the viewer, but as soon as the user presses the mouse some eyes close and some start looking to the side. This motion captures the moment of secret surveillance – as soon as someone looses the focus, someone else becomes a spy. The spying eyes are careful – when sight of the others comes back, everything seems normal. The change of eye colour also indicates the differences between two.

Highlight of the code I am proud of

Using the mouseIsPressed() condition seemed a bit confusing to me at first, since I had to define what happens when the mouse is not pressed (therefore the original image) in the end, but I have managed to figure out the order.

//pupils when eyes are closed
  noStroke()
  for (let x=0; x<=width; x+=200) {
    for (y=0; y<= height; y+=50) {
      if (mouseIsPressed){
        fill('#FFBB00');
        circle (x+90,y,25)
      }
      // pupils when eyes are open
      else{
        fill('#2D96BC')
        circle (x+100,y,25) 
      }
      fill('#2D96BC')
      circle (x, y, 25)
       }

Sketch

Reflection

Although the idea of the story behind the image was represented correctly, I believe that the “spying” process can be developed further in a more detailed way. For instance, different eyes can look into different directions, and the order of closing eyes can be randomised. More user interaction can be implemented – for example, the movement of the eye can be controlled only when the mouse presses on it.

Assignment 1: self-portrait

Concept

Thinking of ways to present myself using simple geometric forms, I was looking for reference and discovered works of Carolina Melis, who is famous for using generative art to create geometric portrait. It inspired me to think in a similar direction, making sketches of a symmetrical and minimalist image.

My first sketches 

The final portrait captures me looking at p5.js coding tutorials for the first time – I was slightly scared of starting to lear something new from scratch, but immediately started to visualise possible projects. The spinning star in my eye represents this hypnotising process of generating ideas.

Highlight of the code I am proud of

Learning how to rotate the shapes was the most difficult part for me. Since I have not done this before, I looked for tutorials which helped me to figure out how this function works and how it can be applied to different shapes. I had to improvise with the translation of the centre point for triangles, since the tutorial only explained how to do so with shapes, but after long calculations I have managed to do this – and I am very proud of the smooth outcome.

//left pupil-star animated
  push() ;
  translate(145, 190) ;
  
  rotate(angle) ;
  
  fill('#FFBB00')
  triangle(-12.5, 0, 12.5, 0, 0, 30)
  triangle(-12.5, 0, 12.5, 0, 0, -30)
  triangle(0, 12.5, 0, -12.5, 30, 0)
  triangle(0, 12.5, 0, -12.5, -30, 0)
  pop();
  
  angle += radians(1);

Sketch

Reflection

I hope to implement more complex animations and interactive elements into my future works. For this specific work, I could add a more detailed background or add other body parts to the lonely head – moving hands? running legs? Furthermore, many parts of this code are repetitive – I believe there is a way to make it more concise while maintaining the functionality. For now, I am satisfied with the minimalist style of the portrait, since this aspect was inspired by my references, but in the future I hope to learn how to create more complex shapes and even detailed 3D objects.

Week 3 – Reading Response

Based on Chris Crawford’s “The Art of Interactive Design,” a strongly interactive system should be responsive, intuitive, engaging, personalized, and provide meaningful feedback. It should react promptly to user input, be easy to understand and use, encourage active participation, adapt to individual preferences, and offer informative feedback.

To improve user interaction in my p5 sketches, I will incorporate dynamic elements, provide interactive controls, personalise experiences, provide meaningful feedback, and tell a story. By introducing elements that respond to user input, offering intuitive controls, allowing users to customize their experience, giving clear and informative feedback, and creating a narrative to guide the user’s experience, I can create more engaging and interactive p5 sketches.

Assignment #2: Sense of Time


Concept & Inspiration.

How do we understand time? How do we grasp its relativity, and how does time differ across the globe in each corner of the world?

These questions came to mind as I reflected on the nature of time. My inspiration came from a piece of artwork I encountered on Pinterest titled “Rhythm.” As I observed the moving rectangles in the artwork, they reminded me of the movement of a clock. But what do these many clocks represent? For me, they symbolized two key ideas: (1) the relativity of time, and (2) the global nature of time, with its 24 time zones that shape the rhythm of life around the world.

Additionally, I drew heavy inspiration from a talk by Casey Reas, which I reflected on in a recent writing assignment. His discussion on randomness and order heavily influenced the way in which I approached my work.

Highlights.

In my interpretation, the background of the piece represents a chaotic flurry of clock dials, moving at a faster pace than the clock hands themselves. This fast-paced, seemingly erratic animation of ellipses symbolizes the relativity of time—its ability to feel both slow and fleeting, elusive and constant. Through this hectic background, I aimed to convey how time can feel overwhelming, moving quickly yet still slipping away before we can fully grasp it.

One aspect I’m particularly proud of is the grid of 24 clock hands, which I arranged to move with a calculated precision. Each clock hand is offset by PI/6 radians, representing a one-hour difference in the 24 time zones of the world. Although the movement of the arrows may seem chaotic when viewed all at once, there’s an underlying pattern — each line is meticulously timed to reflect the rhythm of global time. I have also learnt how to implement such functions as push() and pop().

for (let lineX = 0; lineX < 4; lineX++) { 
  for (let lineY = 0; lineY < 6; lineY++) { 
    push(); 
    translate(100 + lineX * 120, 100 + lineY * 120); 

    let offset = (lineX * 6 + lineY) * PI / 6; 
    rotate(baseAngle + offset); 
    line(-50, 0, 50, 0); 
    pop();
  }
}

Reflection.

I loved working on this project, as it gave me opportunity to master the basic knowledge of loops (specifically, “nested loops” which I got particularly curious about during the class). Furthermore, I aimed to focus more on the idea and conception (relying on the talk by Casey Reas and “randomness in order”), and gave myself more time to understand what I want to achieve before sitting to code.

Probably, the only thing I could not figure out is how to properly indicate time in numerical aspect in my artwork. In the future, I would like to create more sophisticated animated shapes so the idea is conveyed clearly.

In essence, this piece is an exploration of time’s complexity — how it can be experienced in so many different ways, how slowly yet at lighting speed it can pass by, and how it is governed by a specific order we all live within.

Embedded Sketch.