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