week3 – attractors and movers

Concept:

The concept for this project was to be able to create a recognizable pattern while also using movers and attractors. I was inspired by the flower-dotted patterns as well as Dan Gries’s work. In this project, I try to integrate what we learned in class to recreate such a pattern. However, I decided to add more forces that can disturb the pattern as if it’s almost a shadow.

Highlight of some code:

For this project, I decided to build upon the practice we had in class. I initially wrote a code similar to what we did in class and then watched the nature of the code video and added elements to that. I played around with the names to see what patterns I got. After that, I decided to create some turbulence by creating a bouncing effect when the balls reached the borders of the canvas and by creating gravity between some of the particles. I had so many issues with debugging the code because I was experimenting with it mostly to create a pattern I liked. I think the most challenging part was making the different bodies work relatively in response to one another while also creating interesting shapes as they moved around the canvas. 

These images are different iterations at different stages of my code until I reach the desired result.

class Mover {
  constructor(x, y, m) {
    this.pos = createVector(x, y);
    this.vel = p5.Vector.random2D();
     // this.vel.mult(5);
    //     the acceleration will change when forces act on it
    this.acc = createVector(0, 0);
    this.mass = m;//this store mass m of mover []
    this.r = sqrt(this.mass) * 0.15; //r=sqr m * a constant this is for the radious 
  }

  applyForce(force) {
    let f = p5.Vector.div(force, this.mass);
    this.acc.add(f); //add the forces to acceleration 
  }
//   attract to one another gravity btw diff objects
  TwoAttract(mover) {
    //this.pos-mover=vector(from mover to another mover)
    let force = p5.Vector.sub(this.pos, mover.pos); // 
    let distanceSq = constrain(force.magSq(), 1000, 10000); //limit btwn 1000 and 10000
    let G = 0.2; //gravatational constant 
    let strength = (G * (this.mass * mover.mass)) / distanceSq; //f=G*(m1m2)/d'2 law of gravity 
    force.setMag(strength); //set the force and mag as calculated 
    mover.applyForce(force); //apply calculated to mover 
  }

  update() {
    this.vel.add(this.acc);
    this.pos.add(this.vel);
    this.acc.set(0, 0);
    
        // Boundary checks 
    if (this.pos.x > width) {
      this.pos.x = width;
      this.vel.x *= -1; // Reverse horizontal velocity when hitting right edge
    } else if (this.pos.x < 0) {
      this.pos.x = 0;
      this.vel.x *= -0.1; // Reverse horizontal velocity when hitting left edge
    }
    
    if (this.pos.y > height) {
      this.pos.y = height;
      this.vel.y *= -0.2; // Reverse vertical velocity when hitting bottom edge
    } else if (this.pos.y < 0) {
      this.pos.y = 0;
      this.vel.y *= -0.2; // Reverse vertical velocity when hitting top edge
    }
    // Reset acceleration to 0 after each frame
    this.acc.mult(0);
    
    
  }
  RandomColors(){
  //     colors function
   
   let R = random(90, 100); // r is a random number between 0 - 255
   let G = random(100, 120); // g is a random number betwen 100 - 200
   let B = random(150, 200); // b is a random number between 0 - 100
  return color(R,G,B);
}

  show() {
     strokeWeight(0);
    fill(this.RandomColors());
    ellipse(this.pos.x, this.pos.y, this.r * 2);
  }
}
//class to attract objects to the attractor to show how gravity is btwn 2 objects the attractor and the objects 
class Attractor {
  constructor(x, y, m) {
    this.pos = createVector(x, y);
    this.mass = m;
    this.r = sqrt(this.mass) *115;
  }

  attract(mover) {
    let force = p5.Vector.sub(this.pos, mover.pos);
    let distanceSq = constrain(force.magSq(), 1000, 1500);
    let G = 4;
    let strength = (G * (this.mass * mover.mass)) / distanceSq;
    force.setMag(strength);
    mover.applyForce(force);
  }

  show() {
  
  }
}
let movers = [];
let twoattract;
let attractor;

function setup() {
  createCanvas(600, 600);
  //movers attracted to attracor
  for (let i = 0; i < 6; i++) {
    let x = random(width / 2);
    let y = random(height / 2);
    let m = random(50, 100);
    movers[i] = new Mover(x, y, m);
  }
  attractor = new Attractor(width / 2.5, height / 2, 100);

  background(0);
}

function draw() {
  //3 movers attracted to each other
  for (let t = 0; t < 4; t++) {
    movers[t].update();
    movers[t].show();
    //attractor applies force to each other
    attractor.attract(movers[t]);

    for (let u = 0; u < 6; u++) {
      for (let other of movers) {
        if (t !== u) {
          movers[t].TwoAttract(movers[u]);
        }
      }
    }
  }

  attractor.show();
}

 

Embedded sketch:

Reflection and Future Work:

I am happy with the result of this project; however, I think there is room for improvement.  I think the forces acting on the objects and the attraction more coherent with one another to make them feel a little more pattern would create even more pleasing results. Further, I want to experiment with other shapes rather than circles maybe lines or triangles that would potential;;y create other patterns as they move.

Resources:

https://www.researchgate.net/publication/258499541_Classification_of_symmetry_groups_for_planar_n-body_choreographies

https://dangries.com/rectangleworld/demos/nBody/

https://github.com/nature-of-code/noc-book-2/tree/main/content/examples/01_vectors/example_1_9_motion_101_velocity_and_random_acceleration

https://thecodingtrain.com/tracks/the-nature-of-code-2/noc/2-forces/6-mutual-attraction

Week 2 – Rain

Your concept:

Rain always brings me peace; therefore, for this project, I created a scene of rainfall to reflect the feeling I get when it rains. I had some ideas before I settled into this one, such as sunset and sunrise, moving waves, and birds. However, replicating rainfall spoke to me the most. 

I began this assignment by reviewing the materials for this week and watching inspirational videos of things that move. Then, I read a little about the physics behind rainfall, its average acceleration relative to its size, and velocity. I had to do some conversions and basic math to make it logical on a computer screen. For the scene, I used a PNG image for the mountains, a gradient for the sky, rain audio, and some stars to enhance the theme.

Highlight of code:

I tried to make my code neat and clean for this project by creating a different class file and functions whenever possible. The most challenging part of this project was figuring out logical numbers for the line length, acceleration, and velocity so that the rain looks similar to real life. I also had some trouble figuring out how to make sure the lines were straight and not move in any other direction, so I also experimented with it.

class RainDrop {
  constructor(x, y) {
    this.position = createVector(x, y);
    // make the numbers more logical when it comes to rain in pixcels
    this.velocity = createVector(0, random(0.6, 0.9));
    this.acceleration = createVector(0.001, 0.9);
    this.length = random(10, 20);
    this.Colorstrength = random(20, 255); //form od depth
  }
  show() {
    stroke(200, this.Colorstrength);
    //     subtracting x from the length to create a vertical line if i dont it looks weird
    line(
      this.position.x,
      this.position.y,
      this.position.x,
      this.position.y - this.length
    );
  }

  update() {
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);
  }
}

 

Embedded sketch:

Future work:

While this project satisfies what I have learned so far, in the future, I want to add other factors that affect the acceleration of a raindrop, like the force of air and its density. I also want to add more depth so that the sketch resembles real life and to enhance the experience. Furthermore, I want to loop the sound and create a button for the user to have the power to play and stop the audio.

Resources:

https://hypertextbook.com/facts/2007/EvanKaplan.shtml#:~:text=When%20a%20raindrop%20falls%20to,as%20would%20any%20falling%20body.

https://hypertextbook.com/facts/2007/EvanKaplan.shtml#:~:text=When%20a%20raindrop%20falls%20to,as%20would%20any%20falling%20body.

https://p5js.org/reference/p5.Element/show/

https://p5js.org/reference/p5/lerpColor/

 

Self-Avoiding Walker _ Week 1

Concept:

In the first week of classes, I decided to make a self-avoiding walker with randomized RGB colors for the background, lines, and points of the walker and Gaussian random point size. I took this assignment to review my prior knowledge of P5Js and build upon it.  For the point, I made sure I used noise to randomize the color to make it more organic, playfull, and aesthetically pleasing.

Highlight of some code:

To successfully make this project, I had to research a little about self-avoiding walkers, and I came across the Coding Trian video where he transforms the random walker we made in class into a self-avoiding one. For my code, I followed the same logic as he did but I also added my own into it. I also explored noise and Gaussian random a lot in this assignment. I also decided to add some text indicating that the pattern has stopped so that the user can reload the code if they want another pattern.

 

// global variable to store the data in the left right up and dawn, each objects stores an element of direction
let allDirections = [
  { dx: 1, dy: 0 }, //right
  { dx: -1, dy: 0 }, //left
  { dx: 0, dy: 1 }, //dawn
  { dx: 0, dy: -1 }, //up
];

let x;
let y;

// randomize the color of stokes
let Clr = 0;

let grid;
let spacing = 20;
let cols, rows; //variables for the colombs and rows to store info

//
function GridArray(cols, rows) {
  let arr = new Array(cols);
  for (let i = 0; i < arr.length; i++) {
    arr[i] = new Array(rows);
  }
  return arr;
}

function setup() {
  createCanvas(400, 400);
  //colums and raws for the 2d array
  cols = floor(width / spacing);
  rows = floor(height / spacing);
  x = cols / 2;
  y = rows / 2;
  //random Background color
  r = random(200, 160);
  g = random(200, 160);
  b = random(200, 160);
  background(r, g, b);
  //make an array to store the grid data in to save it and set it intially to false if it did not go there
  grid = GridArray(cols, rows);
  for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      grid[i][j] = false;
    }
  }
  //   set to true when walker has been there
  grid[x][y] = true;
}

//create a function to check validity to go to a specific spot
function isValid(i, j) {
  if (i < 0 || i >= cols || j < 0 || j >= rows) {
    return false;
  }
  return !grid[i][j];
}

function draw() {
  // make dot size based on random gaussian
  let w = randomGaussian(8, 4);
  strokeWeight(w);

  // make stroke color based on noise
  let n = noise(Clr);
  let n2 = noise(Clr + 80);
  let n3 = noise(Clr + 50);
  Clr += 0.75;
  let c1 = map(n, 0, 1, 0, 255);
  let c2 = map(n2, 0, 1, 0, 255);
  let c3 = map(n3, 0, 1, 0, 255);
  let c = color(c1, c2, 160 + c3);

  //plot the point
  stroke(c);
  point(x * spacing, y * spacing);

  //make array and put all directions in the array then check if its valid
  let options = [];
  for (let option of allDirections) {
    let newX = x + option.dx;
    let newY = y + option.dy;
    if (isValid(newX, newY)) {
      options.push(option);
    }
  }

  if (options.length > 0) {
    let step = random(options);

    strokeWeight(5);
    stroke(c);

    beginShape();
    //     line
    vertex(x * spacing, y * spacing);
    x += step.dx;
    y += step.dy;
    vertex(x * spacing, y * spacing);
    endShape();
    grid[x][y] = true;
  } else {
    console.log(`Walked this path!`);
    textSize(14);
    fill(255);
    text('OOPS... almost walked on myself',100,200)
    noLoop();
  }
}

One part of the code I am particularly proud of is making the color for the stroke. Here, I created 3 Perlin noise variables. Then, I incremented Clr by 0.75 to ensure a smooth and gradual transition in color. Then, I mapped the noise values to the color ones understood by P5. Finally, when I made the variable c for color, I  made sure that the blue color was more dominant by adding 160 to it.

Embedded sketch:

Reflection and ideas for future work or improvements:

I am really happy with the outcome. This assignment was an opportunity to review what I previously learned in P5Js and add new knowledge to it.  However, I think there is always room for improvement. For instance, I need to figure out how to restrict the walker within the canvas boundaries. Further, I want it to be a little more interactive. For instance, if the mouse is pressed or the space bar is clicked, I want the walker to re-load and then make another randomized walker and change colors.

Resources:

Wikipedia contributors. (2024, August 7). Self-avoiding walk. Wikipedia. https://en.wikipedia.org/wiki/Self-avoiding_walk

1.1 What is a Vector? (n.d.). https://thecodingtrain.com/tracks/the-nature-of-code-2/noc/1-vectors/1-what-is-a-vector

The Coding Train. (2021, June 10). Coding Challenge 162: Self-Avoiding Walk [Video]. YouTube. https://www.youtube.com/watch?v=m6-cm6GZ1iw

The Computational Beauty of Nature – Week 1

 

In The Computational Beuty of Nature, Flake transforms how I thought about nature and the world from an extremely complex perspective into a simpler one. In this chapter, Flake explores ways in which the world’s complexity can be simplified. From his definition of Reduction, I tried to understand how things work and behave. For instance, when coding something hard I began by thinking of the different elements it encompaces, and put it in simpler words. Through this reading, I realized that the world is like a puzzle. Small pieces of it come together to make something more complex. Additionally, in this book,  he argues that there is a significant importance in looking at the world through other different lenses, such as holism and parallelism.

“Choas shows us that even in deterministic systems, predictability is not guaranteed”.

Further, I liked his comparison between natural selection and algorithm because even though someone knows how specific algorithms work and the creator knows how natural selection works we, as users, often do not know. As a result, I think this creates a form of randomness, and he will explain further in chapter three about chaos where algorithmic systems can produce seemingly random outcomes.

Even though the chapter focuses on how to see the world it also briefly introduces the different chapters of the book where he draws a connection to the relationship between the various chapters in understanding one another and nature.
I think this chapter formulates a foundation for the book and how via computation one can understand the complexity of our world.