Week 3: Smooth Lights

Concept and Inspiration

For this week, as I was looking forward to make use of arrays and object oriented programming, I wanted to draw lights that smoothly turn on and off. My idea has inspiration  from disco lights that blink turning on and off. An image of such an arrangement of lights can be seen here below:

The alternation of black and white colour are intended to create an illusion of lights turning on and off.

Implementation

To implement my idea, I created two classes one for the boxes and one for the circles. I had functions to draw the boxes and circles in each class and created the objects in the setup function and saved the locations of each in an array. In the draw function I used the arrays to draw the boxes in the canvas.

My sketch

My final sketch can be seen here below:
<

My code

Continue reading “Week 3: Smooth Lights”

Floating balloons

Concept

The inspiration for using balloons in this project came from a Chelsea football match I watched on Saturday, September 14. During the game, my team struggled to score until a substitute player finally found the net. In his celebration, he blew up a balloon, which sparked the idea to create a project centered around balloons. I wanted to capture that moment of excitement and celebration by translating it into an interactive experience where each balloon expands and changes color when clicked. My goal was to apply the programming concepts I’ve learned so far to build something creative and playful using balloons.

Christopher Nkunku, the chelsea Player who scored the only goal of the game and did his iconic balloon celebration.

 

Implementation

The project is built using p5.js and applies Object-Oriented Programming (OOP) to create interactive floating balloons. A `Balloon` class is defined, with properties like position, size, color, and growth rate. Each balloon floats upwards and resets when it reaches the top of the canvas. On each mouse click, the clicked balloon changes color and expands by a set amount.

The `setup()` function initializes an array of balloons with random attributes, while the `draw()` function continuously updates and displays the balloons. The `mousePressed()` function checks for clicks and triggers balloon growth and color changes. This structure efficiently demonstrates object interaction, animation, and user engagement with OOP principles.

Highlight

One aspect of the code that I enjoyed implementing was the incremental growth of balloons on each mouse click. Instead of making the balloon instantly expand to a large size, I wanted to ensure each click resulted in a smooth, controlled increase. To achieve this, I implemented the grow() and clicked() methods within the Balloon class. This is the code that shows the highlight: 

  // Incrementally expand the balloon when clicked
  grow() {
    this.balloonSize += this.growthAmount;  // Increase size by a fixed amount per click
  }

  // Check if the balloon is clicked
  isClicked(px, py) {
    let d = dist(px, py, this.x, this.y);  // Distance from mouse to balloon center
    return d < this.balloonSize / 2;  // Check if mouse is inside the balloon
  }

  // Change color and grow when clicked
  clicked() {
    this.color = color(random(255), random(255), random(255));  // New random color
    this.grow();  // Incremental growth with each click
  }
}

 

Embedded Sketch 

 

Future Reflections and Ideas for Future Work

Looking ahead, there are several ways I could improve and expand upon this project. One idea is to implement a balloon popping mechanic, where balloons could “pop” after reaching a certain size, adding another layer of interaction and completion. This could involve sound effects to make the interaction even more satisfying and immersive for the user.

Additionally, I could introduce different behaviors for each balloon, such as varying floating speeds or randomized directions, to make the scene feel more dynamic. Another potential improvement would be to add more complex user interactions, like dragging balloons or having them respond to other inputs such as keyboard presses.

Finally, I’d like to explore using advanced animations to create a more gamified experience. These ideas could help make the project more engaging and add more variety for the user.

Week 3: Rainbow Wind Chimes

Concept

When trying to decide what I wanted to do for this assignment, I found Chris Crawford’s definition of interactivity coming to mind. In previous assignments, I think I was too focused on one or two aspects of interactivity that made my piece feel like it was lacking something, despite me being finished. So in getting started with this one, I took to the internet for some general brainstorming on what interactive art could be. After a quick Google search, I came across the following image: 

This ribbon installation by Benoit Pailley caught my attention and became the main inspiration for my piece. In addition, either in class or through clicking through other people’s  work I saw a cool blending trail element  and definitely wanted to incorporate that feature into my own project.

Lastly, as I began to see the project develop further I was reminded of wind chimes (mostly because of their rectangular shape) and their movement in the fading out of colors so decided to go with that as my overall theme. I briefly considered making all the rectangles hues of green to represent the flow of nature but felt that that was a bit too far of a reach and was more comfortable with the brighter, louder colors for this one. I thought the bright colors on contrast with the black and white background was a nice juxtaposition with the soothing nature with which the objects are moving.

Components 

Although it made a big difference in the final outcome making  the object trail as they move was super simply. I simply added on a second parameter to background(0, 10)  so that the alpha transparency value would smooth out the color of the rectangle for every frame. I got this idea from Ethan Hermsey  on Stack Overflow.  For the foundation of the code (generating the rectangles and having them move) I referenced the code we reviewed in class, more specifically Ball Class 2. From there, I simply added an array og objects so that I could store all of the rectangles in one place, and change them by referencing for (let rectangle of rectangles) .

I added a few ‘interactive’ (not sure if they live up to Crawford’s definition) components for the user that are accessed through the mouse and keys. For starters, when the mouse is double clicked, all of the rectangles become shades of grey and depending on what key is pressed, the rectangles will flow from a different side of the canvas. Also, the spacebar changes the colors back from shades of grey to multi-colored and all the rectangles stop moving when you hold down on the mouse.

An Aspect I Am Proud Of

I am most proud of the interactivity in this assignment. Although once you get one side down, it is rather easy to apply it to the other three I ran into little problems (like dealing with keyCode() and keyPressed() that prolonged the process. Furthermore, I ended up undoing a couple of changes with these moving pieces that took me quite a while was rather proud of myself for doing so because although it made me feel like I wasted time, it was all in the name of the artistic process.

function doubleClicked(){
  //why does it change direction for bw but not back to color?
  whiteBack = true;
  for (let rect of rectangles) {
    rect.color = random(255); 
    rect.speedX *= -rect.speedX;
  }
} //color -> BW change direction (after first time?)
//bw -> no change
function keyPressed() {
  whiteBack = true;
  if (key === ' ') {
    for (let rect of rectangles) {
      rect.color = color(random(255), random(255), random(255));
      // rect.speedX *= -rect.speedX;
    }
  }

The code that I’ve embedded is not my entire keyPressed function but actually a piece of keyPressed() and the entirety of doubleClicked(). I chose these two because they were the first two functions I added to alter the rectangles movement and thus the most difficult for me to implement.

Final Product

Reflection

Overall, I am fairly satisfied with the outcome of this piece. It is by far the most aesthetic thing I’ve created for class so far and was an effective application of the concepts we learned. However, I feel like it lacked depth in terms of meaning and kind of just developed as something I’d enjoy visually.

Also, there are two odd bugs that I couldn’t figure out and would like to solve in the future. The first one being that after switching from black and white to color (or vice versa) there are streaks of the previous paths of the rectangles as if they were created in a background of a different color. From what I could tell, I set it so that the background would be the same throughout (either black or white) but when it is supposed to be white, it almost appears grey against the white-streak contrast. Finally, in some instances when the rectangles are returning back to their starting side (after bouncing on the opposite wall) they just fade away and I could not figure out why. I used the code from class  for the walls of the bouncing ball (if (this.y < 0 || this.y > height) ) for both x and y (when deemed necessary) to ensure they stayed within their boundaries but was unable to get it to work how I imagined.

All in all, I really am pleased with this piece and do actually want to fix these issues because once that is done, I do feel like the project will actually be complete.

 

Week 3 – Object-Oriented Programming

Concept: I wanted to create an interactive art piece while challenging myself code-wise. I settled on a little game of popping balloons. I used class to make the circles. I also randomized colors from a set of specific colors in an array. The interactive part of the art is when a circle is clicked, it disappears, giving the popping effect.

Code: I’m specifically proud of this line of code because I used the not condition to check whether to continue growing based on a mouse click.

grow() {
    if (!this.clicked) { // Only grow if not clicked
      this.radius += this.growthRate;
      if (this.radius > this.maxRadius) {
        this.radius = this.maxRadius; // Capping the radius
      }

Problems: A problem I faced was having the circles overlap the text, hiding it from sight. Another one was needing to refresh the sketch to repeat the art. I wish I could have implemented a way that when all balloons are popped, it regenerates them by itself.

 

Reading Reflection – Week 3

Crawford argues that big ideas are elusive and hard to capture in a sentence-long definition, and I agree. However, he then proceeds to do this and limit what can be considered interactive. He argues that books, movies, and performance art are not interactive, but I beg to differ. Consider a choose-your-own-adventure movie or book; is this not regarded as interactive? One could argue that Crawford’s book was published in the early 2000s, so he might not have heard of such media. Yet those interactive forms, specifically books, were famous in the 90s.

Another example that he fails to consider is stand-up comedy. The comic interacts with the audience, listening, thinking, and speaking, all of which Crawford states are part of an interactive piece. Add to that, many of the jokes in a set come from the ability of the comic to improvise based on the audience, further proving the point that performance art is interactive. Putting that aside, I agree with him that interactivity relies on good listening, thinking, and speaking. This could be applied to p5 by implementing real-time feedback mechanisms that respond to user input—for example, having the sketch change based on whether the mouse is pressed.

Week 3 Reading Reflection

Chris Crawford’s “The Art of Interactive Design” emphasizes the importance of interactivity as more than just a simple response to input. Crawford defines true interactivity as a system’s ability to listen, think, and respond, much like a conversation. This approach highlights the need for thoughtful engagement between the user and the system, ensuring that interactions feel dynamic and meaningful. Systems that effectively apply this model create ongoing exchanges, where both user and system influence each other, ultimately making the user feel actively involved and engaged in the process.

In improving the level of interactivity in my p5.js sketches, I aim to apply these concepts by going beyond simple triggers and creating a more thoughtful, adaptive experience. Instead of a one-time action from the user generating a single response, I want the system to react dynamically, changing multiple aspects of the sketch based on continuous input. For example, rather than a simple click to trigger an animation, the user’s actions could influence multiple variables like movement, color, and object behavior, creating a more engaging and evolving experience. Crawford’s “listening, thinking, and responding” approach can help me develop sketches that offer a richer interaction and make the user feel more connected to the experience.

Week 3 – Ripple Matrix

Overall Concept

The goal of my artwork was to create a trippy, mesmerizing experience by combining a grid background with a ripple effect triggered by mouse clicks. The ripples grow from the point of the click, creating an expanding circle that contrasts with the static electricity-like grid in the background. The artwork plays with randomness in both the grid’s colors and the ripple’s growth, making each frame visually unique. By using Object-Oriented Programming (OOP), I was able to structure the code cleanly and efficiently manage multiple ripple effects simultaneously.

Code Breakdown

  1. Object-Oriented Programming with the Rippler Class
    The ripple effect is generated using a class called Rippler. Each time the user clicks on the canvas, a new ripple is instantiated at the mouse position. The class allows each ripple to grow over time, giving the illusion of waves expanding across the grid.
  2. Arrays for Storing Objects
    I used an array to store all the Rippler objects so that multiple ripples can be drawn and expanded at once. This approach also allows for scalable complexity, as the number of ripple effects grows depending on user interaction.
  3. Grid Background Functionality
    I created a function, drawgridColors(), to generate a background grid. Each square in the grid is assigned a random color from a predefined set. The randomness, combined with the small size of each square, gives the grid a look similar to static electricity.

Favorite Part of the Project

My favorite part of this project was building the background and giving it a static electricity kind of look. Although it wasn’t too difficult, the way the grid feels alive with random colors constantly changing adds a nice touch. The following snippet was key to achieving this effect:

for (let i = 0; i < height / size; i++) {
  for (let j = 0; j < width / size; j++) {
    let colorIndex = int(random(possibleColors.length)); 
    let thisColor = possibleColors[colorIndex]; 
    fill(thisColor); 
    noStroke(); 
    rect(i * size, j * size, size, size); 
  }
}

I enjoyed how simple it was to achieve this effect by filling the grid squares with random colors, yet it visually complements the dynamic ripples on top.

Inspiration and Future Improvements

My inspiration for this artwork came from the desire to create something that would be visually captivating and somewhat hypnotic, giving a trippy experience for viewers. I wanted the ripples to feel as though they were interacting with the chaotic, staticky grid background.

For future improvements, I’d love to make the project more interactive. For instance, I could implement different types of ripple effects or allow the user to control the grid colors or the ripple speed through keyboard input. This would enhance the trippiness and interactivity of the piece.

Challenges and Problem-Solving

One challenge I ran into was ensuring the grid and the ripples didn’t conflict visually, especially since both involve overlapping elements. Adjusting the grid size and ripple speed helped balance the visuals.

Another issue was managing the frame rate. I needed the grid to update slowly while allowing the ripples to grow at a faster pace. By setting a lower FrameRate  and controlling the ripple speed manually in the Rippler class, I was able to solve this.

 

 

Week 3 – Starman’s Spaceship

CONCEPT:

The idea came to me when I was listening to one of my favourite songs — David Bowie’s Starman (2012 Remastered version of course). The song is essentially about an alien, stuck in space, trying to find a community. One of the lyrics particularly inspired me to create the final vision –”There’s a starman waiting in the sky”. In terms of the project, I then imagined the screen to display bright, twinkling stars as spaceships explore the universe. Initially, I thought to just include one spaceship, but then, upon deeper reflection, I thought it would be a nice challenge for me to understand how I can generate different spaceships without adding any sort of manual commands. The alien (Starman), is us all — we’re navigating through the domain that is our life, which is reflected by the different coloured spaceships, symbolising different aliens trying to fit in. Each spaceship, represented in different colours, symbolises various aliens striving to fit into the cosmos, reflecting our own journeys through life. The different backgrounds depicts the unique journey each alien has — the stars are automatically rearranged when the user clicks the screen, to explore the journey of another alien in a spaceship.

 

VISION:

It was quite a challenge for me to be able to exactly visualise what it is I want to execute. Therefore, I came up with a simple, initial sketch to sort of understand what is supposed to be on my canvas, and perhaps what is supposed to happen. The sketch showcases two things namely: the background, and the starships. In this drawing, I drew two spaceships because at the time I had thought of displaying multiple spaceships, stationary.  However, as I began to implement the vision, I came to understand that it would look plain and it would block  the focus of the piece: the twinkling stars.

IMPLEMENTATION:

I decided to not store the starships in an array, unlike with the stars, because it did not make sense to me. The spaceships would appear and disappear one click at a time, so there was no actual reason for it to be stored in any sort of way. 

I focused on creating the spaceship first, as I wanted to see if I could make them fly. I first began by creating the class, and then manually generating them, e.g. spaceship1.show(), spaceship2.show(), for testing purposes. The spaceship was mreo tricky than generating the background for me, as I sort of struggled to understand how I can make them generate the spaceship at a certain set of coordinates without it going beyond the boundaries of the canvas. However, I then came to the realization that I can change the parameters in the this.x, and this,y, value so that they appear within the boundary, as the parameters I had them at originally were (0,600)

regenerate() {
  
  // to make the space ships a bit unqiue
  this.w = random(70, 100); 
  this.h = random(50, 70);  
  // instantiates ship at random pos
  this.x = random(50, 500);
  this.y = random(50,500); 
  
  //unqiue colours
  this.color1 = color(random(255), random(255), random(255)); //top col
  this.color2 = color(random(255), random(255), random(255)); //bottom col
}

In terms of the stars, I believe I am quite proud of my code, especially as the result of the background is quite aesthetic. I decided to create an array, so that the stars are stored into it as they are spawned, so that it is easier for them to be displayed in the draw function. I am mostly happy with my twinkle function, as I had thought long and hard about how to make it seem like it is getting brighter or dimmer. However, at the time, I was also experimenting with the opacity of the stars ellipse, to see how bright they should appear on the canvas — which then led me to the realisation that I can quite literally increase or decrease the opacity to give it the desired visual effect.

 
twinkle() {
  this.opacityChange = random(5);
  this.opacity *= this.opacityChange;
  
  // check if opacity is set below
  if (this.opacity < 50) {
    this.opacity = 50;
    this.opacityChange *= this.opacity;      
  }
  
  // check if opacity goes above
  if (this.opacity > 255) {
    this.opacity = 255;
    this.opacityChange = this.opacity;

  }
}

    

REFLECTION: 

If I were given the opportunity to further this piece, perhaps I would add another level of interactivity to the spaceships. Maybe I would make them shoot different coloured beams in any direction I am pointing at, storing them into an array, implement sound, or even some sort of rotation to add another pop of visual activity.

Reading Reflection – Week 3

In my opinion, a strongly interactive system should effectively incorporate all three aspects the author mentions in The Art of Interactive Design: listening, thinking, and speaking. I think that video games are a good example of an interactive system, hence to illustrate these characteristics, I will use a recent game I played, It Takes Two.

Regarding listening, It Takes Two, like many storytelling games, implements this by “listening” to the user’s input. In other words, the game adapts its narrative based on what the participants choose or want to experience. It Takes Two tells the story of a couple on the verge of breaking up, who are brought back together by their daughter-a very relatable story that touches on the theme of family.

The second aspect is thinking, which, in my view, is not always the best metaphor for interactivity when applied to machines. The concept of thinking is vague, and we usually associate it exclusively with humans. Despite that, I interpret “thinking” as the system’s ability to process information, or the mechanisms the designer employs to create meaning. In games, I see thinking as the game mechanics. For example, It Takes Two requires tasks to be completed by two players, which demonstrates how the system accepts input and processes it.

The last aspect is speaking. It Takes Two uses the adventure through the couple’s old possessions to retell their past, implementing “speaking” by showing how the interaction unfolds. This aspect prompts the user to react to the machine.

When discussing interactive design, I think most people tend to focus on the speaking aspect-the demonstration-more than on the other two factors. However, for an interaction to be well-executed, all three aspects need to work in harmony. I often fall into the trap of focusing solely on demonstration. In future projects, I want to focus on incorporating more meaningful interaction mechanisms and exploring how they can better convey the story.

Assignment 3 – The Alternate Universe

Concept

Imagine a universe where two planets exist on the same orbit. For many years, I’ve been working on fictional stories, and I wanted to bring one of these concepts to life using p5.js for this assignment. The idea emerged a while ago, and although it was inspired by sci-fi media, I can’t say I’m directly mimicking anyone else’s work. The concept for this project is to make the two planets move 180 degrees apart, as if they are locked in orbit, to prevent them from crashing into each other (I’m aware that real planets don’t behave like this). This is how the project began. During the planning stage, I used Adobe Photoshop to composite some images, which helped me visualize how I would approach the project.

This is the image I used to plan out how I would like the final project to look like.

The Procedure

First, I began by creating functions to generate the stars. I didn’t want the stars to move, but they needed to be positioned randomly. The following code snippet demonstrates how I randomly generated the stars and created another function to store their positions.

// Function to generate stars and store their positions, size, and color
function generateStars(numStars) {
  for (let i = 0; i < numStars; i++) {
    let x = random(0, width);  // Random x position
    let y = random(0, height);  // Random y position
    let size = random(1, 3); // Random size
    
    // Colors for stars (magenta, blue, yellow, and white)
    let colr = [color('magenta'), color('blue'), color('yellow'), color(255)];
    
    // Store each star's position, size, and color
    starPositions.push({
      x: x,
      y: y,
      size: size,
      colr: random(colr)
    });
  }
}

// Function to draw stars from stored positions
function drawStars() {
  for (let i = 0; i < starPositions.length; i++) {
    let star = starPositions[i];
    
    stroke(star.colr);  // Set color for each star
    strokeWeight(star.size); // Set size for each star
    point(star.x, star.y);   // Draw the star
  }
}

In this project, I used various functions, including one to detect comet collisions with planets and another for collisions with the sun. The comets were created using a class and stored in a dynamic array, making memory management simpler compared to other programming languages. The project involved a lot of mathematical concepts, especially for the comet class, and I drew inspiration from p5.js projects and AI-assisted planning. I experimented through trial and error to execute certain parts.

Code I’m most proud of:

The code I’m most proud of is the Planet class, which brings the entire concept to life using trigonometry. By applying cosine and sine functions to measure angles, I was able to make the planets behave as intended. This idea came from Google searches. Here’s a snippet of my Planet class:

class Planet {
  constructor(size, colr, strokecolor) {
    this.size = size;
    this.colr = color(colr);  // Fill color
    this.strokecolor = strokecolor;  // Outline color
    this.x = 0;  // X position (calculated later)
    this.y = 0;  // Y position (calculated later)
    
  }

  // Update the planet's position based on the angle and radius
  update(angle, radius) {
    this.x = width / 2 + cos(angle) * radius;  // X position
    this.y = height / 2 + sin(angle) * radius; // Y position
  }

  // Show the planet
  show() {
    stroke(this.strokecolor);  // Outline color
    strokeWeight(2)
    fill(this.colr);  // Fill color
    ellipse(this.x, this.y, this.size);  // Draw the planet
  }
}

In my draw function, I used the following code, utilizing the principles of Object Oriented Programming to bring this idea to fruition.

// Update and draw the planets
 planet1.update(angle, radius);
 planet1.show();
 
 planet2.update(angle + PI, radius);  // The PI angle ensures planets are always opposite each other
 planet2.show();
 
 // Increment the angle for continuous rotation
 angle += 0.01;

 

The Final Project:

 

Reflection:

For this project, I was a bit ambitious when I first started. I prioritized realism over functionality to give the viewer a great experience. However, I learned that this wasn’t necessary and settled for a simpler approach using Object-Oriented Programming. After reading The Art of Interactive Design, I realized my final project lacked key elements of interactivity, like even a simple mouse click. In my defense, I removed interactivity because, in the storyline, humans don’t have the power to move objects in space. However, I would improve the project by adding music, moving stars, mouse-click-generated comets, and perhaps better visuals. I faced challenges in ensuring the planets always rotated 180 degrees apart, but after solving this, I was amazed at what code can achieve. I’m excited to see what it can do with more advanced graphics in the future. For now, this is it.