Week #11 – Creative Bankruptcy

The concept

As the titles indicates, this sketch is about being creatively bankrupt. Why creatively bankrupt, might you ask? This mental state involves a constant black and white noise (as those seen in TV when there is no signal). It is a state in which no ideas flow, where ideas are not as good as you thought. Frustrating to say the least. Nevertheless, creative bankruptcy itself can be expressed as art.

Anybody remember rubbing your hand across the TV screen static? : r/nostalgia
Figure 1. CRT filled with static noise.

With this concept in mind, I wanted to do something similar with cellular automata. Therefore, I present you my newest sketch: “Creative Bankruptcy”

Controls:

Mouse Click: Start music.
Moving mouse while pressed: Rotate through the X, Y and Z axis.
Z key: Start from the beginning with a new rule value (new pattern).
X key: Stop generating scan lines
C key: Clear background.

Full-screen version: Creative Bankruptcy

Brief explanation of the code

The code work in the following manner:

1. Since we are working with cellular automata, a system needs to be in place in order to work. The vision I was seeking for required for me to create an array that hosts multiple classes for every cellular automata. So, the idea is to store multiple classes inside the array and then use the custom function of prepare() with each one of them.

//Prepare celular spawners.
//Parameters for spawning a celular spawner: (ruleValue, w, y, direction).
cells.push(new CelularSpawner(int(random(255)), 5, 0, 0));
cells.push(new CelularSpawner(int(random(255)), 5, 0, 0));
cells.push(new CelularSpawner(int(random(255)), 5, 0, 0));
cells.push(new CelularSpawner(int(random(255)), 5, 0, 0));

//Prepare the celular automata spawners.
for (let i = 0; i < cells.length; i++) {
  cells[i].prepare();
}

The function prepare() prepares the cellular automata spawner by analyzing the total width of the canvas and then filling each cell by the establish width in the parameters to properly fill it out and follow the pattern with calculateState(a, b, c):

prepare() {
  this.ruleSet = this.ruleValue.toString(2).padStart(8, "0");

  let total = width / this.w;
  for (let i = 0; i < total; i++) {
    this.cells[i] = 0;
  }
  this.cells[floor(total / 2)] = 1;
}
calculateState(a, b, c) {
  let ruleset_length = this.ruleSet.length;

  let neighborhood = "" + a + b + c;
  let value = ruleset_length - 1 - parseInt(neighborhood, 2);
  return parseInt(this.ruleSet[value]);
}

2. For reasons I will explain later, I decided to use WEBGL to generate a different effect on the canvas. This is due to the fact that, since the canvas was seeking to transmit a feeling of watching it on CRT, the shader support was limited to only WEBGL. Despite shaders not being used for this sketch, the rotation of it to generate different patterns was left with the function orbitControl(1,1,1).

3. Being inspired by “Following Uncertainty”, I decided to implement, again, audio spectrum visualizer. Although, this one is represented through an image that increases its sizes accordingly through a plane.

The creative bankruptcy behind it (A self reflection and what I could be proud of)

This section is more of a self-reflection on why this assignment was so hard for me, despite my other sketches being more complex. It seems that, at the end of the semester, the burnout catches up. It is frustrating since I had many ideas that I wanted to explore in this sketch:

      1. Boxes with physics done by matter.js that each location is generated by the patterns of cellular automata.
      2. A CRT like canvas done with the use of shaders.
      3. An image being filled by the patterns generated by cellular automata.
      4. An album like done with four sections divided in the screen that are filled by cellular automata.

All of these ideas (kind of) eventually arrived into one. Despite having artistic qualities, it is still not as creative as I wanted it to be. It is frustrating to not being able to implement new ideas due to the aforementioned creative bankruptcy. But as everything in life, we will not get the results we want in one try, and in my case, I should have tried more in other to get a more proper system going on.

For the final project, I will revise all of my previous ideas into something interesting. All of this knowledge I have accumulated into the class will not go unused.

Used sources:

1. Aesela. “𝒀𝒗𝒆𝒔 𝑻𝒖𝒎𝒐𝒓 • 𝑳𝒊𝒎𝒆𝒓𝒆𝒏𝒄𝒆 • 𝑨𝒏𝒈𝒆𝒍𝒊𝒄 𝑽𝒆𝒓𝒔𝒊𝒐𝒏.” YouTube, 24 Apr. 2022, www.youtube.com/watch?v=FfQoshkVChk. Accessed 22 Nov. 2024.

2. “Animated GIFs by Kjhollen -P5.Js Web Editor.” P5js.org, 2024, editor.p5js.org/kjhollen/sketches/S1bVzeF8Z. Accessed 22 Nov. 2024.

3. “CreateImage.” P5js.org, 2024, p5js.org/reference/p5/createImage/. Accessed 22 Nov. 2024.

4. “ShaderToy CRT by Keithohara -P5.Js Web Editor.” P5js.org, 2024, editor.p5js.org/keithohara/sketches/xGU1a8ty-. Accessed 22 Nov. 2024.

5. Tenor.com, 2024, media.tenor.com/88dnH_mHRLAAAAAM/static-tv-static.gif. Accessed 22 Nov. 2024.

6. The Coding Train. “Coding Challenge 179: Elementary Cellular Automata.” YouTube, 9 Jan. 2024, www.youtube.com/watch?v=Ggxt06qSAe4.

Week #10 – Sound of Triangle

Concept

I will be honest, I did not have that much of ideas for this week assignment… For some reason. Nevertheless, while experimenting with Matter.js I found myself with some interesting behaviors, such as gravity manipulation and collisions. Since I had a bit of interest in adding sound into my projects, I wondered how could I deliver something with at least a bit of creativity and interaction.

Sadly, most of the ideas that came into my mind were time-consuming, and thus, would be impossible to complete on time. Still, one was possible: A triangle which produces sound via the collision of circles.

Embedded sketch

Note: You can click on the Canva to spawn more circles.

Full-screen version: Go to the Full-screen version

Brief explanation of the code

The code itself is simple thanks to the use of Matter.js. That means that all the collision and interaction between bodies are managed by the library. Now, what is happening in this code is the following:

First, a set of circle bodies will be spawned and then attracted to the static circle in the middle:

//Draw circles.
for (let i = 0; i < circles.length; i++) {
  //Attract to attractor and then display.
  let force = attractor.attract(circles[i]);
  circles[i].applyForce(force);
  circles[i].show();
  //Check if there is any geometry outside the canvas.
  if (circles[i].isOffScreen()) {
    circles[i].removeFromWorld();
    circles.splice(i, 1);
    i--; //This fixes the flickering in the code.
  }
}

Secondly, while they are being pulled to the attractor, the circle bodies can move erratically around it due to the force applied. During this erratic movement, they can hit one of the three boundaries forming a triangle, or other circles. So, on hit, they will trigger an event in which a sound will reproduce (only when a boundary is hit) as well as change the color:

Collisions function:

//Done with help of the following material: https://nature-of-code-2nd-edition.netlify.app/physics-libraries/#collision-events
function handleCollisions(event) {
  for (let pair of event.pairs) {
    let bodyA = pair.bodyA;
    let bodyB = pair.bodyB;

    //Retrieve the particles associated with the colliding bodies via the plugin.
    let particleA = bodyA.plugin.particle;
    let particleB = bodyB.plugin.particle;

    if (particleA instanceof Circle && particleB instanceof Circle) {
      particleA.change();
      particleB.change();
    }

    if (particleA instanceof Boundary && particleB instanceof Circle) {
      particleA.change();
      particleB.change();
      bell.play();
    }
  }
}

change() function of boundary.js:

change() {
  this.col = color(random(100, 255));
}

circle() function of circle.js:

change() {
  this.col = color(random(100, 255));
  this.r = random(0, 10);
}

There is also some code that helps with optimization, such as in the case that the circles go out boundaries, as well as cleaning the array appropriately:

//Check if there is any geometry outside the canvas.
if (circles[i].isOffScreen()) {
  circles[i].removeFromWorld();
  circles.splice(i, 1);
  i--; //This fixes the flickering in the code.
}

Reflection and ideas for future work or improvements

I feel that this task end up being uninspiring. While simplistic and stylish in his own way, there are other interactions I would wish to implement. Such interactions include more “artistic” expressions once the circles hit the boundaries, or a more intricate physics simulation where the boundaries could be dynamically moved according to time (as in rotating in a 360 degree manner). I am confident that some ideas will be implemented in future projects, but at the moment, let’s conclude that this is still a phase of learning how to use Matter.js.

Used resources

a. “6. Physics Libraries.” Netlify.app, 2014, nature-of-code-2nd-edition.netlify.app/physics-libraries/#collision-events. Accessed 12 Nov. 2024.

b. “6.1 Matter.js – Introduction.” Thecodingtrain.com, thecodingtrain.com/tracks/the-nature-of-code-2/noc/6-physics-libraries/1-matterjs-introduction.

c. “6.2 Matter.js – Introduction, Continued.” Thecodingtrain.com, 2016, thecodingtrain.com/tracks/the-nature-of-code-2/noc/6-physics-libraries/2-matterjs-introduction-continued. Accessed 12 Nov. 2024.

d. “6.9 Matter.js Attraction by Natureofcode -P5.Js Web Editor.” P5js.org, 2024, editor.p5js.org/natureofcode/sketches/16sblEvax. Accessed 12 Nov. 2024.

e. “Freesound – BELL 0101.Wav by Zgump.” Freesound.org, 2024, freesound.org/people/zgump/sounds/83538/. Accessed 12 Nov. 2024.

Week #9 – Following uncertainty

Concept

I had a curious inspiration while I was going in a bus to campus. I was staring at the window, looking silently at the night, and this silent appreciation was then followed by the next music suggestion in my music app: DIIV – Taker.

It was a weirdly melancholic song, the type of beat I like: melancholic, but not to excessive levels to induce sadness, but rather, a peace calmness. And this is the type of feeling I got from listening to this music, calmness. Thus, for this week assignment, I wanted to share what I felt with a music visualization using flock systems.

Embedded sketch

Note: If the p5.js version is slow, it is suggested to try either this version or make a copy of the GitHub’s repo and run it locally on the computer.

Make sure to click on the Canva to start with the visualization!

Full-screen: Full-screen version

Brief explanation of the code

The flock system is divided on multiple parts, which are activated according to the time of the song; it is easily done with the value returned from the function song.currentTime(). Here is a quick example:

Let’s say that I want to generate the wave effect that appears at the beginning, for this, I create the following parameters inside a custom function called startPart(value):

The wave code is located in the second if condition (value == 2).

function startPart(value) {
  if (value == 1) {
    for (let boid of flock) {
      //Reset value.
      boid.velocity.mult(0);
      boid.maxForce = 0.0;
      //Avoid boids from going out from the borders of the screen.
      boid.transparency = 1;
      boid.acceleration.add(random(-2, 2), random(-0.5, 0.5));
      boid.update_values(1); //Updates the boundaries to the first phase values.
      part = 1;
    }
  }

  //THIS IS THE WAVE CODE
  if (value == 2) {
    for (let boid of flock) {
      //Reset value.
      boid.velocity.mult(0);

      //Assign maxForce
      boid.maxForce = 0.01;

      //Avoid boids from going out from the borders of the screen.
      boid.transparency = 10;
      boid.acceleration.add(random(1, 3), random(-1, 1));
      boid.update_values(2); //Updates the boundaries to the first phase values.
      part = 2;
    }
  }

And then, the specific part is called with the following custom function checkAudioTime() on the second 14 of the song:

function checkAudioTime() {
  if (round(audio.currentTime(), 0) == 6) {
    startPart(1);
  }

  if (round(audio.currentTime(), 0) == 14) {
    startPart(2);
  }

It is important to note that checkAudioTime()is called continuously under draw().

Highlight of some code that I am particularly proud of

I am mostly proud of the patterns I created for this visualization. In total, there are 11 variations which are divided between two flocking systems. I will not paste all the variations here, since it is almost 300 lines of code, but I will share three examples of it:

if (value == 9) {
  for (let boid of flock_outside) {
    //Reset value.
    boid.velocity.mult(0);

    //Assign maxForce
    boid.maxForce = 0.01;
    boid.maxSpeed = 1;
    boid.perception_radius = 50;

    //Avoid boids from going out from the borders of the screen.
    boid.transparency = 50;
    boid.acceleration.add(random(-1, 1), random(-1, 1));
    boid.update_values(6); //Updates the boundaries to the first phase values.
    part = 3;
  }
}

if (value == 10) {
  for (let boid of flock_outside) {
    //Reset value.
    boid.velocity.mult(0);
    boid.maxForce = 1;
    boid.transparency = 5;
    boid.acceleration.add(random(0), random(10));
  }

  for (let boid of flock) {
    //Reset value.
    boid.velocity.mult(0);
    boid.maxForce = 1;
    boid.transparency = 5;
    boid.acceleration.add(random(0), random(10));
  }
}

if (value == 11) {
  for (let boid of flock_outside) {
    //Reset value.
    boid.update_values(7);
  }

  for (let boid of flock) {
    //Reset value.
    boid.update_values(7);
  }
  part = 6;
}

Reflection and ideas for future work or improvements

I am mostly proud of this work. It is by far the assignment I have spent the most time on (or probably the second one). It was an enjoyable challenge, which I felt really curious about what kind of results I could get with the flocking systems. Although, I felt that some patterns in the visualization are rather simplistic and should have been reacting to the sound.

Not to imply that I did not try to implement more reactions that are based on the frequencies of the song, but after some attempts, it was best to disregard the idea since it would consume a lot of time.

Used resources

17.11: Sound Visualization: Frequency Analysis with FFT – p5.js Sound Tutorial

Coding Challenge 124: Flocking Simulation

DIIV // Taker (Official Audio)

Week #8 – Ants want to go to their home

Concept

For this assignment, I wanted to implement something rather simple, but entertaining to play with. So, to come with some ideas, I reflected upon the material given in class and had a sudden realization that the autonomous agents concepts and examples looked like how ants behave.

So with this realization in mind, I decided to code ants trying to reach their home, while they try to avoid the flashlights.

Embedded sketch

Link to full-screen version: Full-screen version of the sketch

Brief explanation of the code

The code possess three main characteristics:

      • Arrival
      • Evade
      • Randomized movement across the Canva with the help of a flowfield.

At the beginning of the program, an ant will spawn, which will make the final destination the nest. After the ant has moved a certain distance, another ant will spawn. Although, the ants can have some troubles getting into the nest if the flashlights are switched on, since they would have to avoid them. Likewise, to avoid a monotonous movement, the concept of flow fields (using Perlin Noise to help with the random generation) was added into the Canva to let ants move more naturally; their movements are more unpredictable.

Highlight of some code that I am particularly proud of

The hardest part, at least for this code, was to find a way to properly toggle ON and OFF the flashlights, as well as moving them across the Canva. While this seemed like an easy task at first, I forgot that sometimes coding can be hard for no reason. For example, the first flashlight would work, but the second not. Although, if you moved the second flashlight closer to the left side of the canvas, suddenly it worked!

It was confusing, but at the end, this was the code that worked:

First part of the logic (mouse is being pressed on a flashlight to move it):

 for (let i = 0; i < flashlights.length; i++) {
   flashlights[i].display();

   if(mouseIsPressed == true){
     if (
       mouseX > flashlights[i].position.x &&
       mouseX < flashlights[i].position.x + flashlights[i].r + 60 &&
       mouseY > flashlights[i].position.y &&
       mouseY < flashlights[i].position.y + flashlights[i].r + 180
     ) {
 
       //Check just in case if clicked element exists.
       let index = flashlights.indexOf(flashlights[i]);
       if (index > -1) {
         flashlights[index].position.x = mouseX-30;
         flashlights[index].position.y = mouseY-95;
       }
     }
   }
}

Second part of the logic (mouse is pressed over a flashlight to turn ON or OFF the light):

function mousePressed() {
    for (let i = 0; i < flashlights.length; i++) {
      if (
        mouseX > flashlights[i].position.x &&
        mouseX < flashlights[i].position.x + flashlights[i].r + 60 &&
        mouseY > flashlights[i].position.y &&
        mouseY < flashlights[i].position.y + flashlights[i].r + 180
      ) {
  
        //Check just in case if clicked element exists.
        let index = flashlights.indexOf(flashlights[i]);
        if (index > -1) {
          if (flashlights[index].state == 0) {
            flashlights[index].state = 1;
          } else if (flashlights[index].state == 1) {
            flashlights[index].state = 0;
          }
          flashlight_button_sound.play();
        }
      }
   }
}

Reflection and ideas for future work or improvements

I feel that there could be more original ideas and experimentation implemented in this program, since I feel that I only use class material in a very copy and paste fashion. Not to imply that I feel that I did not put effort into this assignment, rather, how I should have gone more outside the box.

Now, regarding the code itself, some improvements are:

      • Ants spawn in different points in the Y axis.
      • Ants avoid the flashlights in a more believable manner.
      • Flashlights can not be overlapped between each other.

Used resources

SOme extra Concepts:

a. https://stackoverflow.com/questions/5767325/how-can-i-remove-a-specific-item-from-an-array-in-javascript

Images:

a. https://www.shutterstock.com/search/dirt-ground-grass

b. https://www.freepik.com/premium-vector/large-worker-ant-top-view-vector-illustration-isolated-white-background_21352776.htm

c. https://media.istockphoto.com/id/1486076388/photo/anthill-top-view.jpg?s=612×612&w=0&k=20&c=rcpRqTgk4lHhqFg_qssf9Qoi4s_UshYTToeKmOH18bI=

Audio:

a. https://freesound.org/people/Sjonas88/sounds/538554/

b. https://freesound.org/people/baidonovan/sounds/187335/

c. https://freesound.org/people/naturesoundspa/sounds/163597/

Week #8 – Reflection on lecture by guest artists

While listening to the lecture, I found myself reflecting on how coding concepts can blend seamlessly with real life. By this I mean that, if we apply some real-life principles to our programs, and then demonstrate them with visual references, the result can be interesting.

One example mentioned in the lecture was the illusion of sand falling in a gradual, realistic way. This is only possible thanks to the knowledge accumulated over the years and a creative approach to projecting it using sand as the medium. This made me realize that coding is not just about solving logical problems; it is also about tackling creative ones.

Midterm Project – Generative Clock

Concept

This was a sketch that took some time to fully realize what my final concept was. First, I thought about being inspired by my sketch “2000s qwerty” and integrate key caps into the midterm with a clock. Although, when I finished a quick draft of it, I did not like the end result: It was very uninspired.

Figure 1. Initial sketch.

However, the clock functionality was giving promising results and more ideas.

After deleting the key caps out of the sketch, I started experimenting with the clock I made, trying to understand what kind of creative variations I could do with it. After some time of thinking, I decided that it was best to add certain functionalities to each hand, but at the same time, that each function somehow helps in filling the background to generate the silhouette of a clock. The end result can be seen in the following sketch.

Sketch

Note: By clicking on the canvas, it will generate a .svg file of what is currently seen on screen. Likewise, by pressing the space bar, the color scheme will toggle between either colorful (the default) or black and white.

Full-screen version: Fullscreen version of “Generative Clock v1.0”

The functionality

Since the idea of the midterm was to implement different concepts we have seen so far in class, I decided to add each one in a “natural” manner. The functionalities are the following:

      1. Vectors: Everything is composed by vectors.
      2. Clock hands using angles: These, according to the system’s time, will move accordingly as if it was a real analog clock. The way that the position of the hands is determined is by, first, catching the current time of the system, to then translate and map the vector values of each hand to an angle (with the help of theta).
      3. Physics: The sketch possesses gravity, acceleration, and attraction. For example, every time a second passes, a tiny particle will spawn in the X and Y coordinates of the millisecond hand. After than, they will get attracted to the seconds hand and fly around it using the aforementioned physics.
      4. Perlin Noise: The particles that fly around the seconds hand will have their colors changed using the Perlin noise, which grabs the current system time to move smoothly in the RGB values.
      5. Particles system: Each particle that loops around the seconds hand will get deleted after some time, to avoid consuming more resources of the computer.

Highlight of the code I am proud of

The hardest part of this code was translating the system time to the accurate position of the clock’s hand, since it needed precise values in order to be properly represented using angles:

//Move the hands in a circular motion, according to system time.
update(hours, minutes, seconds, milliseconds){


    // Convert polar to cartesian  (Taken from an example from class).
    this.position = p5.Vector.fromAngle(this.theta);
    this.position.mult(this.r);

    if (this.type_of_hand == "hours"){
        this.theta = map(hours, 0, 198, -51.8, 51.8);   //-51.8 seems to be the value to simulate a clock.

    } else if (this.type_of_hand == "minutes"){
        this.theta = map(minutes, 0, 1000, -51.8, 51.8);
    }

    else if (this.type_of_hand == "seconds"){
        this.theta = map(seconds, 0, 1000, -51.8, 51.8);
    }
    
    else if (this.type_of_hand == "milliseconds”){
        this.theta = map(milliseconds, 0, 15800, -51.8, 51.8);
    }
}

Images

Figure 2. Clock without the generative background.
Figure 3. Clock with the generative background in colorful mode.
Figure 4. Clock with generative background in black and white mode.

Pen Plotting

For the pen plotting in a A3 paper, I had to create a different version in order to be easily drawn, since the original version would create a .svg file that would take too much time to plot. This involved taking some artistic decisions, such as altering the pattern and physics to avoid creating many circles.

Figure 5. Generative Clock made with pen plotter.

Printed version

For the printed version, the  was used to develop the following:

Figure 6. Black and white version of the Generative Clock printed on a A3 paper.
Figure 7. Colorful version of the Generative Clock printed on a A3 paper.

Reflection and future improvements

I am happy with the progress so far for this midterm. The concepts that I applied from class (in my opinion) seem to integrate seamlessly with the concept of the project. Although, one thing that I would like to implement is a functionality for the hours hand, although it would seem a bit unnecessary since it will take too long to move. Likewise, I would like to implement another feature which could help the Canva appear more interesting visually, but I have yet to come with new ideas.

Used Sources

Week #5 – Midterm Report #1

Concept & Design

For the midterm, I had various ideas. Although, most of them were a variation from week 4’s assignment. The brainstorming process was one that took me time, since I was thinking to myself: “How do I blend everything that we have learned so far?”. And this is where a bit of a realization came to me.

In my last week assignment, I commented how I wanted to create like a “face”, composed by two eyes represented as a spiral of key caps. Although, the end result would have been weird. Still, with this idea, I continued brainstorming until I realized the following draft:

Quick sketch of an analog clock composed of key caps.
Figure 1. Quick sketch of an analog clock composed of key caps.

Basically, my idea is to create an analog clock, composed of multiple hands that indicate time, as well as being surrounded by key caps that will define most of the features and interactions for this generative art. So, once I arrived with the idea, it was time to develop it and determine the key features.

Key features

      1. Time accurate: The clock seen in the Canva is accurate to the time present in the computer.
      2. Sound: As seen in my week 4’s assignment, I will integrate sound into this project to complement the experience. It will be triggered once the keycaps touch any of the hands from the analog clock. While I am still thinking about this feature, what is clear is that it will be mainly composed of mechanical keyboard sounds.
      3. Physics: I have not yet defined how physics will play a mayor role in this sketch, but what I want to feature the most is key caps falling and disappearing with a proper particle system.
      4. Magnetism: Using the mouse as an attractor, I plan to make the key caps falling be collected with the mouse if it is pressed.
      5. Perlin noise for color: This is yet another feature I am thinking how it will be integrated, but it could be for all the entities in the canva. In other words, according to their position, the color will change smoothly.

Current Progress

Here is my current progress:

Frightening parts

At the moment, the most frightening parts are the interaction with the key caps and sound. This is due to the nature of this code: The key caps move too fast, and it will overlap the sounds.

Another frightening part, although it is already done, was the integration of the system’s time with the Canva. This was done using the JavaScript default class Date and its functions and adjusting the value of theta via the function map();

Here is the feature code of the moving hands, of the analog clock, which took me the most time:

update(hours, minutes, seconds, milliseconds){
        // Convert polar to cartesian  (Taken from an example from class).
        this.position = p5.Vector.fromAngle(this.theta);
        this.position.mult(this.r);

        if (this.type_of_hand == "hours"){
            this.theta = map(hours, 0, 390, -51.8, 51.8);   //-51.8 seems to be the value to simulate a clock.

        } else if (this.type_of_hand == "minutes"){
            this.theta = map(minutes, 0, 1000, -51.8, 51.8);
        }

        else if (this.type_of_hand == "seconds"){
            this.theta = map(seconds, 0, 1000, -51.8, 51.8);
        }
        
        else if (this.type_of_hand == "milliseconds"){
            this.theta = map(milliseconds, 0, 15800, -51.8, 51.8);
        }
    }

Finding the correct values to map each hand took a lot of time since, most attempts, resulted in the hands being desynchronized with the system’s time.

Reducing risks

To avoid delivering an uncompleted midterm project, I plan to do the following:

      • If a certain part of the code is too hard to develop, I will refer to the class material as well as the multiple examples in order to understand how something works.
      • If there are some unclear details in how to proceed, I should arrange office hours with the professor.
      • Spend between 1–2 hours a day developing the key features.

Future improvements

I would like to improve this sketch by doing the following:

      • Adding better aesthetics and with a more of a “generative” touch. Like, for example, if a key cap is touch then generate a series of letters around it following Perlin noise.
      • Add the mechanical keyboard sound.
      • Develop a background and not from an external source.
      • Define better what kind of interaction will the user have with the mouse.

Used sources

      1. How to get current time in JavaScript by geeksforgeeks

Week #4 – 2000s qwerty

Introduction

For this assignment, I tried to challenge myself a bit more by implementing a different concept. I spent some days thinking about what I could implement for this assignment, for example, I was thinking about making either an abstract pattern or a “musical face”. Although, one thought led to another, and I arrived at mechanical keyboards and the 2000s aesthetic!

Full-screen version: Full-screen version

The concept

Since in this week we saw the concepts of oscillation and, mainly, we had to be inspired by the artist Memo Akten, it was necessary to implement something similar. That means, almost synchronized movements via mathematical functions, and peaceful timed sounds.

As mentioned, I was thinking in implementing an abstract design, but I found myself more interested in creating a more cohesive canva. This cohesive design combines things I am fond of, which include 2000s aesthetics, nostalgia and computers.

Old key caps.
Figure 1. 2000s keyboard uploaded by an anonymous user on r/MechanicalKeyboards.

Highlight of the code I am proud of

The main challenge of this code was to implement the sound system. I am not very proud of some parts of the code of this system, since I had to implement quick fixes. Nevertheless, one of the key features of this is that, according to the letter specified, it will assign a certain value to start the audio for the key, since all the sound effects are integrated into a single file.

Since all the system of the audio is distributed in the class Keycap, I will share the corresponding code.

class Keycap{
    constructor(x,y,letter){
        this.sound = loadSound("files/sound.ogg"); //The only solution to avoid overlaps and sudden sound stops was to do this.
        this.position = createVector(x,y);
        this.w = 40;
        this.h = 40;
        this.letter = letter;
        this.soundstart = 0;  //This variable will keep a value to jump the sound to play the sound.
        this.sound_played = 0;
        this.sound_time = 0; ///Check by how much time the sound played.
    }

    //Displays and also determines which sound to play according to the key cap.
    display(){
        push();
        noStroke();

        fill(235, 235);
        rect(this.position.x-5,this.position.y-2,this.w+10,this.h+10);

        fill(224, 223);
        rect(this.position.x,this.position.y,this.w,this.h);


        strokeWeight(30);
        textSize(23);
        fill(0);

        switch (this.letter) {
            case "q":
                text("q",this.position.x+15,this.position.y+25);
                this.soundstart = 2.90;
                break;
        
            case "w":
                text("w",this.position.x+15,this.position.y+25);
                this.soundstart = 4.90;
                break;

            case "e":
                text("e",this.position.x+15,this.position.y+25);
                this.soundstart = 5.90;
                break;
            
            case "r":
                text("r",this.position.x+15,this.position.y+25);
                this.soundstart = 6.90;
                break;

            case "t":
                text("t",this.position.x+15,this.position.y+25);
                this.soundstart = 7.90;
                break;

            case "y":
                text("y",this.position.x+15,this.position.y+25);
                this.soundstart = 8.90;
                break;

            default:
                break;
        }
        pop();
    }

    keypressed(){

        //Highlight that the key was pressed.
        push();
        strokeWeight(10);
        fill(235, 235, 235);
        rect(this.position.x-5,this.position.y-2,this.w+10,this.h+10);
        fill(235, 235, 235);
        rect(this.position.x,this.position.y,this.w,this.h);
        textSize(15);
        fill(0);
        pop();
    
        ///Then play a sound according to the letter.
        this.play_sound();
    }
  
    play_sound(){
      if (this.sound_played == 0){
        this.sound.play();
        this.sound.jump(this.soundstart);
        this.sound_played = 1;
      } 
    }
  
    stop_sound(){
        this.sound.stop();
        this.sound_played = 0;
      }
  
}

In a very summarized version, what is happening is the following:

      • According to the letter specified when creating the class, and in the constructor, it will go through a switch() case to determine the start point of the audio.
      • Once one of the moving rectangles enters one of the key caps (or the range of it), will activate the function keypressed().
      • Once keypressed() is started, it changes the visual design of the key caps for a short moment, to then play the sound via the function play_sound().
      • Once the function is called, it determines if the audio is currently playing via the variable this.sound_played, and once it is determined that it has not started, it will play using the specific start point. Likewise, to avoid overlapping, the audio then assigns this.sound_played to 1.
      • Once the moving rectangle leaves the area of the key cap, it calls the function stop_sound().

Reflection

Compared to last assignments, I am happy with the end result. It feels that the ideas that I wanted to implement on my mind could become real. Nevertheless, I would say that for future assignments I would like to improve upon the code, since I feel it is a bit redundant this time, as well as not very optimized.

References

    1. 17.3: Timing, Jumps and Cues – p5.js Sound Tutorial
    2. CherryMX Black – ABS keycaps
    3. JavaScript Switch Statement
    4. Late-night Sim City 2000
    5. text()
    6. Where can I get a windows keycap that looks like this?

 

Week #3 – Magnetic Waves

Introduction

For this week, I initially planned to create marbles falling from a platform and landing on a magnetic field, where they would accumulate over time and collide with each other. At first, this idea seemed interesting to implement, but once I realized it was going to take more time than I originally planned, I had to scale down my ambition.

However, while trying to implement the original idea, I discovered an interesting behavior between three attractors. That’s when I decided to create the following sketch:

Note: You can interact by holding the left mouse button in the Canva.

The concept

As mentioned, the idea transitioned from a fun physics simulation with marbles and magnetic fields to a set of movers accumulating around randomly defined attractors.

There are 3 attractors in total, each with a random X and Y position determined by the width and range of the canvas. Additionally, the movers can collide with the borders of the scenario, and they also have friction as an extra feature.

Initially, the 3 attractors were fixed, as shown in the following full-screen sketch:  Test #1 of Assignment #3. However, this setup was not dynamic enough, and the movers never collided with the borders of the screen. Therefore, it was necessary to make the attractors’ position constantly random.

As an additional note, the colors of each mover are defined by Perlin noise.

Highlight of the code I am proud of

One segment of code I am most proud of is the following:

This part of the code is found in the file sketch.js, inside the draw() function.

if (attractors[0].g > 0){
        attractors[0].g -= 1;
        attractors[1].g += 1;
        
    } else if (attractors[1].g > 0){
        attractors[1].g -= 1;
        attractors[2].g += 1;
        

    } else if (attractors[2].g > 0){
        attractors[2].g -= 1;
        
      
    //Reset first value and the rest of positions of the attractors.
    } else {
        attractors[0].position.x = random(width);
        attractors[0].position.y = random(height);


        attractors[1].position.x = random(width);
        attractors[1].position.y = random(height);

        attractors[2].position.x = random(width);
        attractors[2].position.y = random(height);

        attractors[0].g = 70;
        attractors[2].g = 0;
    }
}

What this process does is, depending on the movers’ positions, increase the universal gravitational constant (G) of the next attractor while decreasing that of the current one, creating a smooth transition between attractors. When the final attractor is reached and its gravitational constant is reduced to 0, the process restarts by randomly assigning new positions to each attractor and redefining their gravitational constants to prevent any issues.

Reflection and ideas for future improvements

I initially thought it would take me more time to grasp the concepts. While there are interesting patterns I would love to create in the future with the movers and attractors, for now, I am glad I am understanding the concepts presented in class, which allows me to experiment with them. That said, here are some improvements I would like to explore in the future:

      • Experiment with parallel attractors and movers. In other words, have two sets of attractors and movers that can interact with each other, instead of a single group of movers interacting with two attractors at a time.
      • Use the collisions and gravity more creatively to add complexity to the designs.
      • Add more user interaction to manipulate the canvas, along with clear visual cues.

References

Most of the code that I used as a guide is from the following video (which is also provided in the weekly schedule):  Mutual Attraction by The Coding Train

Week #2 – Some birds and a tree

Introduction

To get inspired for this week assignment, I took a walk around the campus. I had many ideas in my mind about what I wanted to do; some of them were about trying to imitate the movement of ants or the light of the sun. Although, something caught my interested when I stumbled upon this view:

That is when I realized what I wanted to do.

The Concept

Once I observed this tree populated by many birds, I wanted to recreate both the movement of the leaves, of the tree, and the path the birds take to reach it. At first, I was intimidated to think about this, since it would be very hard to simulate a tree with moving leaves. Nevertheless, I was intrigued.

To reach a satisfactory conclusion for the project, first I had to make a quick sketch about what I wanted to do:

Mockup
Figure 1. Mock-up of the moving trees and how they are going to move according to region.

From what I analyzed in this sketch, I would have to do the following:

    • Simulate many leaves moving at the same time without lagging the computer.
    • Make a believable movement using velocity and acceleration.
    • Populate, randomly, each region and with a different pattern (that is, how they are going to generate according to the range specified).
    • Understand how the birds will interact after the leaves are populated.

Preparing the scenario

Compared to last week’s assignment, I felt that it was too abstract and needed a bit more of style in order to be more presentable. From this experience, I wanted to avoid what I did previously and improve upon it, thus, I wanted to develop a more “alive” canvas.

For this, I needed to create first the scenario that was in symphony with my then progress done:

Figure 2. Preparing the scenario.

Not only that, but in order to create this “alive” canvas, I also realized we would need audio. So, I extracted the audio from the video I recorded, edited it and then added it to the project:

Figure 3. Preparing the background audio.

The code

According to what we have seen in class at the moment, for this code it was essential to work with vectors. Essentially, the vectors were used for almost everything: The ranges where the leaves spawn, the leaves and the birds.

In order to understand how this is possible, here is a quick explanation of how it works in a sequential order:

    1. Regions are created, manually, with the help of createVector(x,y). These regions are stored in the class Leaves. The reasoning of creating regions is to simulate, as accurate a possible with the limitations of p5.js, the movement of the leaves without creating lag and with enough diversity to create the illusion.
    2. After the regions are set, the leaves now start to spawn in each region. There are a total of 5 different regions and, by default, 80 leaves by group. The leaves themselves are represented by green circles that walk through transparency with the help of the Perlin movement. Not only that, but the leaves move by accelerating forwards and backwards in their region.
    3. After the regions and leaves are spawned, the birds can start appearing. To avoid creating a lot of circles in the screen, I decided to only draw one black circle for the birds. They will appear one by one from either the left or right part of the screen. The bird will select a region, randomly, as the endpoint. As mentioned, the birds are represented as black circles that will appear as medium-sized and will be further decreasing to create the illusion of the bird going inside the tree. Once the size of the bird reaches 0, it will generate another bird.

Important note: In order to simulate all of this believably, I had to lock the frame rate to 10. Since if it left with a default of 60, it will look that the leaves and birds are moving at super speeds.

What I am mostly proud of

I am proud that I could simulate how leaves move (at least partially). This was the most challenging part of this work and the one that needed to be addressed first. I took some examples from the class in order to understand how to create this movement. Although, sometimes due to not understanding how it fully worked, the leaves would go out of the Canva, move weirdly, extremely fast and unnatural or just not show at all (because they were going so fast that our eyes could not perceive the moment it left the screen).

Here is a quick example of the code that I used for the movement of the leaves:

// ----- Move leaves according to region. -----

        for (let i=0; i<amount_of_leaves; i++){
            //Taken from the example taught in class.
            let dir = p5.Vector.sub(this.range1, this.p1_leaves[i]);

            dir.normalize();
            dir.mult(0.05);

            this.acceleration = dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(5);
            this.p1_leaves[i].add(this.velocity);
        }


        for (let i=0; i<amount_of_leaves; i++){
            //Taken from the example taught in class.
            let dir = p5.Vector.sub(this.range2, this.p2_leaves[i]);

            dir.normalize();
            dir.mult(0.05);

            this.acceleration = dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(5);
            this.p2_leaves[i].add(this.velocity);
        }

        
        for (let i=0; i<amount_of_leaves; i++){
            //Taken from the example taught in class.
            let dir = p5.Vector.sub(this.range3, this.p3_leaves[i]);

            dir.normalize();
            dir.mult(0.05);
 
            this.acceleration = dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(5);
            this.p3_leaves[i].add(this.velocity);
        }

Although, I am not very proud by the amount of for statements…

Similarly, for the movement of the birds the code was similar, but easier to understand since I knew how it worked:

fly(rng_number){
      //Decide if the bird on the left or right will flight. After that, decide on the final destination to then apply the motion.
        if (rng_number == 1){
            if (this.final_region_destination == 1){
                this.dir = p5.Vector.sub(leaves.range1, this.bird1);
            } else if (this.final_region_destination == 2){
                this.dir = p5.Vector.sub(leaves.range2, this.bird1);
            } else if (this.final_region_destination == 3){
                this.dir = p5.Vector.sub(leaves.range3, this.bird1);
            } else if (this.final_region_destination == 4){
                this.dir = p5.Vector.sub(leaves.range4, this.bird1);
            }
            
            this.dir.normalize();
            this.dir.mult(0.6);

            this.acceleration = this.dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(10);
            this.bird1.add(this.velocity);

            if (this.t <= 0){
                this.restart();
            }

        }

        else if (rng_number == 2){
            if (this.final_region_destination == 1){
                this.dir = p5.Vector.sub(leaves.range1, this.bird2);
            } else if (this.final_region_destination == 2){
                this.dir = p5.Vector.sub(leaves.range2, this.bird2);
            } else if (this.final_region_destination == 3){
                this.dir = p5.Vector.sub(leaves.range3, this.bird2);
            } else if (this.final_region_destination == 4){
                this.dir = p5.Vector.sub(leaves.range4, this.bird2);
            }
            
            this.dir.normalize();
            this.dir.mult(0.6);

            this.acceleration = this.dir;
            this.velocity.add(this.acceleration);
            this.velocity.limit(10);
            this.bird2.add(this.velocity);

            if (this.t <= 0){
                this.restart();
            }

        }

Again, not very proud with how copied and pasted it looks…

The Sketch

So, after all of this explanation, what is the final product? Well, there is the final sketch.

Note: The “white background effect” is intentional. Also, this Canva has background audio, no mouse interactions and a default of 10 frames per second.

Full-screen version: Go to the Full-screen version

Reflection and future improvements

I am mostly happy to how this assignment concluded. I feel that I learned new things about the programming world as well as how to interpret movements in nature. Although, there are some improvements I want to make for future works:

    • Even though this sounds nonsensical, I would like to avoid using too many in-class examples for my codes and challenged myself a bit more with what I can find out of the box.
    • Avoid that the circles accumulate all together if the Canva is left running for a few minutes.

Credits

Some references I used for help are the following:

FrameRate reference: https://p5js.org/reference/p5/frameRate/

Sound reference: http://p5js.org/reference/#/p5.SoundFile

 

And the external programs I used are:

To create the background: GIMP.

To prepare the audio: Audacity.