Week 3 Reading Reflection – Megan

After reading this chapter I realized that a strongly interactive system is really like having a good conversation. Both sides have to listen think and speak well for it to feel alive. If one side fails it just becomes boring or frustrating. So for a system to be truly interactive it has to respond to the user in a way that feels meaningful not just random or automatic. I liked how Crawford explains that interaction is not the same as reaction like with a fridge or a movie you can only watch but you don’t actually talk to it. That made me think about my p5 sketches because sometimes I make things move or change when the mouse touches them but it feels kind of one-sided. I realized that to make them more interactive I could have the objects respond in different ways depending on how you interact with them like changing speed direction color or even start a little animation that is unique for each action. I also liked thinking about giving each object its own “voice” like the dice in my project could react differently to the same input so it feels more alive and less predictable. I want to experiment more with letting the user affect not just the movement but the behavior and appearance over time so it feels like the sketch is listening and thinking a little bit before it reacts. Overall reading this made me want to make my sketches feel more like a real conversation between me and the code rather than just me controlling it.

Week 3 -Object Oriented Programming Megan

Concept:

The concept of this project comes from cacho, a traditional Bolivian dice game. The game is played by putting five dice inside a small leather cup, and you try to roll combinations like a poker hand, for example House, Full, etc. This game caught my attention because all the dice are identical, so I thought I could use them as objects for this project in object-oriented programming.

click it!

Process:

For the process, I first started with a photo of the cubilete, the cup, and the dice inside to be able to draw it in p5.js. I used my iPad to make a sketch highlighting the geometric shapes I needed and how I had to rotate them at different angles. At first, I used translate to set the origin at zero, zero, but later I switched to WEBGL because the dice are 3D geometric shapes.

For the rotations, I set the canvas to use Degrees so I could control exactly how much each shape rotated. That is how I made the base drawing. Then came the dice, which was the most difficult part. I started with 2D using rect, and I wanted them to rotate, so I created a move function inside the Dice class and used rotate so that every time a dice completes a full rotation, it moves forward.

Then I realized 2D did not really give the impression of a real dice, so I switched to 3D and used box from the p5.js 3D examples. For some reason, the box was deforming, its sides would stretch or cut off, so I had to apply rectMode(CENTER), which I was already using for 2D. After trying several methods, this was the only one that kept the cubes from deforming, probably because a box is made of rectangles, and if they are centered, they do not distort.

Next, I wanted to put numbers on the dice, but that turned out to be very complicated. When I tried, the dice faces blinked and did not display properly. The solution I found was to color the different faces with various shades of white and gray to make them look more realistic. I also made sure each dice had a random starting position so they did not all start at the same place.

Another very important part of the process was setting boundaries for the dice. At first, when I got a square to move, it went off the canvas, so I looked at examples from p5.js on how to use the command constrain on balls and adapted that idea. I set random limits so each dice would stop at different places on the table, giving the scene more realism like when you through dice. A key detail was making sure the dice stop rotating once they reach their limits because when I first tried it the dices would keep going on circles once they stopped moving forward.

Full code:

let dice1;
let dice2;
let dice3;
let dice4;
let dice5;

function setup() {
  createCanvas(600, 600, WEBGL);
  colorMode(HSB);
  //Random starting points
  dice1 = new Dice(random(-50, 30), random(-200, 30));
  dice2 = new Dice(random(-50, 30), random(-200, 30));
  dice3 = new Dice(random(-50, 30), random(-200, 30));
  dice4 = new Dice(random(-50, 30), random(-200, 30));
  dice5 = new Dice(random(-50, 30), random(-200, 30));
}

function draw() {
  background("#deb887");
  angleMode(DEGREES);
  
//Table
  push();
  rotate(48);
  fill("black");
  rect(-320, -250, 800, 800);
  pop();
  
  push();
  rotate(20);
  fill("black");
  rect(-210, -310, 500, 200);
  pop();
  
// Cubilete
   //Outside
  fill(30, 85, 30);
  noStroke();
  quad(-193,-286, -250, -130, -100, 40, 40, -230);
  push();
  rotate(14);
  fill(30, 85, 30);
  ellipse(-253, -145, 102, 172);
  pop();
  //Inside
  push();
  rotate(19);
  fill(120, 100, 15);
  stroke(30, 85, 38);
  strokeWeight(15);
  ellipse(-50, -77, 220, 292);
  pop();
  
  //Dice
  dice1.move()
  dice1.show()
  dice2.move()
  dice2.show()
  dice3.move()
  dice3.show()
  dice4.move()
  dice4.show()
  dice5.move()
  dice5.show()
}

// Function to restart dice when clicking
function mousePressed(){
  dice1 = new Dice(random(-50, 30), random(-200, 30));
  dice2 = new Dice(random(-50, 30), random(-200, 30));
  dice3 = new Dice(random(-50, 30), random(-200, 30));
  dice4 = new Dice(random(-50, 30), random(-200, 30));
  dice5 = new Dice(random(-50, 30), random(-200, 30));
}
class Dice{
  constructor(_x, _y){
    this.x= _x;
    this.y= _y;
    
    //So that dice can rotate
    this.angle=0
    
    //Random limit to make dice stop going forward at a certain place in the table 
    this.maxX = random(-10, 260);
    this.maxY = random(-10, 260);
    
    this.colors=["#FFFFFF", "#808080", "#D3D3D3", "#FFFDD0", "#F5F5F5", "#FAEBD7"]
    
    //To stop dice rotation
    this.stopped = false;
    
  }
  move(){
    //To make dice stop rotating when limit reached
    if (!this.stopped){
    
      //Movement forward
    this.x += 3
    this.y += 3
    
    //Limits for dice to not go past the table
    this.x = constrain(this.x, -10, this.maxX);
    this.y = constrain(this.y, -50, this.maxY);

    //If limit reached, stop rotation
    if (this.x >= this.maxX && this.y >= this.maxY) {
        this.stopped = true;
      }
    
    
    //To make them roll
    this.angle += 15; 
    this.angle %= 360;
     
    }
  }
  
 show(){
  push();
  translate(this.x, this.y);
  rotate(this.angle);
  rectMode(CENTER);

  noFill(); // Base box color
  box(65);   // 3D dice

  // Color each face with planes 
  let s = 65/2; // Half the size of the dice, used to position the planes at each face

  // Front face
  push();
  translate(0, 0, s); 
  fill("#FFFFFF");         
  plane(65, 65);       
  pop();

  // Back face
  push();
  translate(0, 0, -s); 
  rotateY(180);         
  fill("#808080");        
  plane(65, 65);        
  pop();

  // Right face
  push();
  translate(s, 0, 0);  
  rotateY(90);          
  fill("#D3D3D3");         
  plane(65, 65);
  pop();

  // Left face
  push();
  translate(-s, 0, 0); 
  rotateY(-90);         
  fill("#FFFDD0");       
  plane(65, 65);
  pop();

  // Top face
  push();
  translate(0, -s, 0); 
  rotateX(90);          
  fill("#F5F5F5");       
  plane(65, 65);
  pop();

  // Bottom face
  push();
  translate(0, s, 0);  
  rotateX(-90);         
  fill("#FAEBD7");       
  plane(65, 65);
  pop();

  pop(); 
  }
}

Code I am proud of:

I am especially proud of the code I wrote to set the boundaries for the dice. As I mentioned, it was really challenging to figure out how to make the dice stop moving and rotating once they reached their limit. Also, making sure the dice did not deform while rolling was tricky, and using rectMode(CENTER) solved that problem perfectly.

//Random limit to make dice stop going forward at a certain place in the table 
    this.maxX = random(-10, 260);
    this.maxY = random(-10, 260);
    
    
    //To stop dice rotation
    this.stopped = false;
    
  }
  move(){
    //To make dice stop rotating when limit reached
    if (!this.stopped){
    
      //Movement forward
    this.x += 3
    this.y += 3
    
    //Limits for dice to not go past the table
    this.x = constrain(this.x, -10, this.maxX);
    this.y = constrain(this.y, -50, this.maxY);

    //If limit reached, stop rotation
    if (this.x >= this.maxX && this.y >= this.maxY) {
        this.stopped = true;
      }
show(){
  push();
  translate(this.x, this.y);
  rotate(this.angle);
  rectMode(CENTER);

  noFill(); // Base box color
  box(65);   // 3D dice

Overall reflection:

The hardest part was definitely trying to put numbers on the dice, which I did not fully achieve. Maybe with more research on 3D objects, I could eventually make it exactly how I intended. But I really liked the final result, especially because it looks a lot like the cacho I play in real life. I also enjoyed working with objects because it made it easy to create multiple dice without repeating code, giving each one different positions and starting points that I could edit freely.

Overall, this project taught me a lot about working with 3D shapes and object-oriented programming. I learned that even small details, like the starting position, rotation, and boundaries, make a huge difference in making the animation feel realistic. I am happy with how I managed to combine my reference from real-life cacho, geometric thinking, and programming, and I feel more confident creating multiple interactive objects in p5.js for future projects.

Week 2 – Creative Reading Megan

Casey Reas Eyeo talk on chance operations

How are you planning to incorporate random elements into your work? Where do you feel is the optimum balance between total randomness and complete control?

Before answering this questions, I wanted to implement by myself the concepts the video was talking about. Randomness. One quote by Casey Reas really stayed with me: “change it by a little so that movement creates chaos in an ordered way.” And I think that perfectly represents what I was trying to do in my work. The things I changed to create this element of randomness were data, small pieces of data that might seem insignificant at first, but machines are built based on that, so even the smallest thousandth can make a difference.

This brings me to another quote from the video, about Dadaism: “Dada wished to replace the logical nonsense of the men of today with an illogical nonsense.” To what point is something considered logical? Computers are supposed to be based on pure logic. And yet, artists find ways to turn that logic into illogical sense. And yet, it still has meaning. It’s like deconstructing the logic embedded in the machine with the purpose of illogically creating something that has meaning behind it. Or the other way around, creating something without meaning by using the logic of the computer. Either way, I feel this can be applied to the artworks shown in the video.

A quote by Gerhard Richter captures this idea very well: “Above all, it’s never a blind chance; it’s a chance that is always planned but also always surprising.” These artists construct from chance as a base. It’s about bringing in disorder that has been curated with intention, in a way that even surprises the artist themselves. I think that finding this balance between total randomness and complete control is about using logic and repetition, patterns and algorithms that allow you to repeat a process, while the outcome is completely different, but the essence of it remains present.

Something that really caught my attention in the video was the idea of the million random digitized values and the 1,000 normal deviates. It honestly amazed me to think about the power, the expectation, and the importance that randomness has in our lives when we understand that art imitates or simulates the real world, and the real world is chaotic and not curated by anyone, but rather filled with randomness. Without a doubt, this video and this work opened my eyes and helped me understand even better the importance of chaos within order, and order within chaos.

Week 2 – Generative Art Megan

Concept

“The whole universe is based on rhythms. Everything happens in circles, in spirals.” — John Hartford

The idea of my artwork was that I wanted to create a spiral using the colors of the flower often called the “national Bolivian” flower, the kantuta. This flower is one of the most amazing ones, not only because of its vibrant colors, but also because it grows up to 3,800 meters above sea level, in its native land in the Andes. This flower has a lot of meaning for me, starting with its colors red, yellow, and green, which are those of the Bolivian flag, and also because it represents the nature and resilience of my home country.

Speaking of nature, I wanted to represent this flower through some kind of shape. Spirals are a shape that is found everywhere in nature and, for me at least, they are mesmerizing to look at and to understand. Inspired by the video we watched on randomness in digital art, I wanted to find an “organic” yet “random” way of showcasing the kantuta. The spiral has movement and flow without breaking its structure or bringing chaos. Moreover, it has such a unique presence, it almost calls the viewer to follow its path, and it feels like you’re watching something alive.

That’s why, and as I promised myself in the last exercise, I wanted to challenge myself, so I looked up many tutorials on how to create spirals in p5.js.

Run it and Click it!

Process

Most of my learning for this project came from these video tutorials on YouTube by Strive Math. First, I had to learn about transformations and translations in p5.js. It has to do with the coordinates in the canvas you’re creating. So, when you translate, you move the entire coordinate plane up, down, left, or right. And when you transform, you’re rotating the entire coordinate plane at an angle that you choose (you must select if the angle will be measured in degrees or radians first). It rotates clockwise if the number is positive and counterclockwise if it’s negative.

With transformations, you rotate the axis around the center point you chose when you did the translation. So, with this, I first learned how to draw a simple circle using these concepts. For example, if I translate the origin so it is right in the middle of the canvas, and I keep making this coordinate plane rotate clockwise while drawing a dot somewhere that is not the origin, the dot will keep moving with the coordinate plane and trace a circle when the coordinate plane completes a full 360° rotation.

This is how the code for that looks (this is no longer in code as such since it was just to practice and understand how it works):

function setup() {
  createCanvas(600, 600);
  angleMode(DEGREES)
}

let angle = 0

function draw() {
  translate(width/2, height/2)
  rotate(angle)
  angle++
  point(30,0)
}

The next step, was to think how this could turn into a spiral. Since the circle shape that I made is actually just a point following a path that is determined by the radius of the circle, if I increase the radius of the circle, and as the point moves more the radius also increases more, this will create a path of a spiral. Therefore now the code will look like this:

let angle = 0
let radius = 0

function draw() {
  translate(width/2, height/2)
  rotate(angle)
  angle+= 31
  radius+= 0.4
  strokeWeight(6)
  point(radius,0)

Now I can control the way the spiral looks by playing with the amount of degrees the angle of the coordinate plane is going to change every time and how wide will the radius of the circle increase be. A small issue with this was that the frame rate of how fast or how slow the points would appear will sometimes be too slow and I wanted to change that. Therefore, just like in the tutorial that i watched, I inserted a for loop to control the frame rate of everything, and for it to not change and save the sate of the canvas I used the ‘push’ and ‘pop’ commands so that the origin always stays in the center of the canvas and doesn’t move every time the for loop repeats.

As I said, I wanted to implement the concept of randomness, so I created random variables for the values of the angle and the radius to be able to make a different spiral every time you click on the screen. To make this happen, I added a mousePressed() function that resets the angle and radius to their initial values, generates new random values for the angle increment and radius increment, and clears the canvas:

function mousePressed() {
  angle = 0;               
  radius = 0;             
  angleValue= random(300, 3000); 
  radiusValue = random(0.009, 0.2);
  background("black");    
}

This way, every time the canvas is clicked, the spiral starts fresh with completely new random parameters, creating a unique pattern while keeping the interaction simple and intuitive. However, it took me a while to figure out this approach, because at first I tried using a boolean variable and a separate restart function in a more complicated way, and my code would get messy: sometimes the spiral wouldn’t appear, or new spirals would overlap with the old ones. Then I realized, why complicate things? I could just reset the main variables and redraw, and it worked perfectly.

Something I did very intentionally was set the limits of the random value of the angle to very big numbers and the numbers of the radius to very small decimals. I did this because I started playing around with those values and I realized the smaller the radius was the more dense the spiral looked and if the angle was a high number there was more chance of there being more ‘spiral lines’. I liked how this looked because it made the spiral look more like a piece of art. I also changed the background color to black so that the colors of the points would stand out more.

Code I am proud of

Then came the most important part: the color of the kantuta image. I uploaded the image to p5.js and made the spiral match the colors of the pixels by randomly selecting a pixel from the image and using its color for each point on the spiral.

let ix = floor(random(img.width))   
    let iy = floor(random(img.height))  
    let c = img.get(ix, iy)             
    stroke(c)

I’m really proud of this code because it wasn’t easy to get it right at first. I had to change the image I was using because the first one had too much black, which blended with the background and made the spiral almost invisible, and it also took too long to load. Then I realized that I needed to extract the colors pixel by pixel from the image, and I did this inspired by the p5.js example of pointillism, where each point takes the color of a random pixel from the image. This finally permited me to have a spiral that not only looked colorful and vibrant, but also represents the kantuta in a way that felt alive and organic, and I really liked it.

Final Code

//Image variables
let img;

//Image upload
function preload() {
  img = loadImage("kantuta.jpg");
}

//==============
//Setup
//==============
function setup() {
  createCanvas(600, 600);
  background("black")
  angleMode(DEGREES);
  frameRate(80);

  angleValue= random(300, 3000)
  radiusValue = random(0.009, 0.2)

  img.loadPixels(); // allow us to access image pixels
}

//Spiral variables
let angle = 0
let radius = 0

let angleValue
let radiusValue

//===================
//Drawing the spiral
//===================

function draw() {
  //To control the frame rate
  for (let i= 0; i<80; i++){
    
  push()//save the state of our canvas
  
  translate(width/2, height/2);
  rotate(angle);
  angle+= angleValue;
  radius+= radiusValue;
  strokeWeight(4);
    
  //Pick a color from the image
    let ix = floor(random(img.width))   
    let iy = floor(random(img.height))  
    let c = img.get(ix, iy)             
    stroke(c)                          
    
   point(radius,0);
  
  pop()//come back to the old state before 'push'
  }
}

// ===================
// Replay spiral on click
// ===================
function mousePressed() {
  angle = 0;               
  radius = 0;             
  angleValue= random(300, 3000); 
  radiusValue = random(0.009, 0.2);
  background("black");    
}

General Reflection

Overall, I think this project taught me a lot about patience, experimentation, and problem-solving. I also realized how important it is to simplify my approach: sometimes trying too many complicated solutions only slows you down, and the best results come from understanding the core idea and working with it directly.

I’m proud of how the final spiral turned out, not just technically but also conceptually. I feel like it feels alive, vibrant, and connected to something meaningful, which reflects the beauty of the kantuta and the creative process behind it. This project was the hands-on reminder of the video we saw that taught me that coding can be as expressive as painting or drawing, and that combining randomness, structure, and careful choices can create something truly mesmerizing.

Week 1 – Self Portrait by Megan Del Villar

Concept

I wanted to create a self portrait that genuinely reflects who I am. I love the color green, and for some reason sticking my tongue out has become a small habit of mine whenever I do not know what to say or when I am in an awkward situation. It works as my personal ice breaker. On top of that, I had never animated anything before and had never programmed in JavaScript. Because of this, I decided to challenge myself by animating the tongue in my self portrait.

Click on it!

Implementation

For the self portrait overall, I used basic geometric shapes such as ellipses and circles, mainly working with the stroke of ellipses. For the bangs and the eyelids, I was inspired by this self portrait example by fenfenrita that I found on p5.js. From that example, I learned that you can use only the stroke of an ellipse to create curved lines and that by adjusting the numerical values you can control how stretched or flattened the stroke looks. I experimented extensively with this technique for the eyelids and later applied it to the eyebrows, nose, and mouth.

For the bangs, that same example, combined with experimenting with PI, TWO_PI, and HALF_PI, helped me understand how ellipses and circles can be partially filled using angles. I adapted a similar code structure and adjusted the size, position, and colors to match my own portrait.

Since I have a background in graphic design, I am used to working with HSB color mode, so I changed the color mode at the beginning to keep the entire portrait consistent. For more specific colors, I searched for their hex codes online and used them directly. The rest of the code was taken from the p5.js library. For the animation, I used the mousePressed function and created a tongueOut function so that the tongue only appears when the self portrait is clicked.

Code I Am Proud Of

// Tongue animation
let tongueOut = false;

// Tongue out or in when clicked
if (tongueOut) {
  fill("#C76A6A");
  noStroke();
  arc(305, 372, 40, 55, 0, PI);
}

//Tounge animation
function mousePressed() {
  tongueOut = !tongueOut;

I am especially proud of how I managed to make the tongue animation work, because deciding how to implement it took a lot of trial and error. At first, I wanted the tongue to move along the x axis of the mouse as it moved across the screen. However, this required setting limits, otherwise the tongue would move outside the mouth area and even beyond the canvas. When I finally achieved this, I did not like the result because the movement was not very noticeable unless the mouse moved a lot.

After experimenting more, I explored other mouse related functions and realized that using mousePressed would allow the tongue to appear and disappear completely. This interaction felt much cleaner and more intentional, so I decided to implement it this way.

Reflection

Overall, I really enjoyed this project and learned a lot, especially considering it was my first time using a program like this and my first time discovering that it is possible to draw using code. I understood everything I was doing, and the more I played with numerical values and visual elements, the more connected I felt to my own drawing. For a future project, I would like to challenge myself even more by creating animation without using the mouse and by experimenting with different types of shapes.