Coding Assignment Week #3 – Screensaver Maybe?

INSPIRATION & CONCEPT

When we got this assignment to work with forces, I wanted to make a screen saver. There are many screensaver designs out there, but the one I coded was inspired by Sol Lewitt’s art piece Wall Drawings (see fig 1).

Lewitt just gave instructions to Boston museum for this art piece and this is what was made. I was very intrigued by this idea and wondered if this could be combined with our decoding nature class. What is these 50 points were not stationary, but moving with mutual forces of attraction between them? Let’s try it out!

TECHNICAL DESIGN

I started with coding just 5 points (50 seemed to be too much for my laptop to handle). These 5 were movers. For the behavior of the screensaver, I added 4 invisible attractors too, in a diamond shape in the center of the canvas. These simulate the moving of the whole design as a whole throughout the canvas. Then remember how a screen saver bounces off the edges? Hence I added the check edges function too.

I am grateful for Daniel Shiffman for his tutorial on Forces linked here . His code in the tutorial was taken as a starting point and built upon.

P5 SKETCH

CODE

// Thanks to:
// Mutual Attract // The Nature of Code
// https://www.youtube.com/watch?v=fML1KpvvQTc&list=PLRqwX-V7Uu6aFlwukCmDf0-1-uSR7mklK&index=18

let j = 0;

let movers = [];
let attractor = [];
let num_m = 5; // number of movers
let num_a = 4; // number of attractors

function setup() {
  createCanvas(600, 600);
  
  // frameRate(30);
  
  for (let i = 0; i < num_m; i++) {
    let m = random(10, 15);
    movers[i] = new Mover(225+50*i, 225+i*50, i*PI/2, -1*i*PI/2, m);
  }

  attractor[0] = new Mover(300, 200, 0, 5, 10);
  attractor[1] = new Mover(200, 300, 0, -5, 10);
  attractor[2] = new Mover(400, 300, -5, 0, 10);
  attractor[3] = new Mover(300, 400, 5, 0, 10);
  background(0);
}

function draw() {
  background(0, 20);

  for (let mover of movers) {
    for (let i = 0; i < num_a; i++) {
      attractor[i].attract(mover);
    }
    beginShape();
    for (let other of movers) {
      if (mover !== other) {
        mover.attract(other);
        // stroke(255);
        // color = p5.Vector.random2D();
        // stroke(int(color.x), int(color.y)%255+1, 0);
        // stroke(255-(j%256), 0, 255,j%256); // (j+55)%255
        stroke(255-(j%256), 255,j%256, j);
        // print(int(color.x*255));
        line(mover.pos.x, mover.pos.y, other.pos.x, other.pos.y);
        // vertex(other.pos.x, other.pos.y);
        // vertex(mover.pos.x, mover.pos.y);
        j++;
      }
    }
    endShape();
  }

  for (let mover of movers) {
    mover.update();
  }
}
class Mover {
  constructor(x, y, vx, vy, m) {
    this.pos = createVector(x, y);
    this.vel = createVector(vx, vy);
    this.acc = createVector(0, 0);
    this.mass = m;
    this.r = sqrt(this.mass) * 2;
  }

  applyForce(force) {
    let f = p5.Vector.div(force, this.mass);
    this.acc.add(f);
  }

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

  update() {
    this.vel.add(this.acc);
    this.pos.add(this.vel);
    this.acc.set(0, 0);
    this.checkEdges();
  }

  show() {
    stroke(255);
    fill(255, 100);
    ellipse(this.pos.x, this.pos.y, this.r * 2);
  }
  
  checkEdges() {
    translate(0, 0);
    if (this.pos.y + this.r >= height) {
      this.pos.y = height - this.r;
      this.vel.y *= -1;
    }
    if (this.pos.y - this.r <= 0) {
      this.pos.y = this.r;
      this.vel.y *= -1;
    }
    if (this.pos.x + this.r >= width) {
      this.pos.x = width - this.r;
      this.vel.x *= -1;
    }
    if (this.pos.x - this.r <= 0) {
      this.pos.x = this.r;
      this.vel.x *= -1;
    }
  }
}

WORKING VIDEO

FURTHER IMPROVEMENTS

With the same concept of screensaver designs, I could play along with the different properties of forces to create different designs and behaviors. I already did alter the mass, distance and G values for the desired result above, but there could be other things to factor in. I did not put in friction for a reason as I want it to be endless and not stop as it a screensaver, it keeps running in the background. However, drag force could be something to play around with to alter the speed of the design. Currently I am controlling the speed with the frameRate() property.

I also only made 5 points and not 50 because that was a lot of computation for my laptop. Maybe there is an efficient way of working with a large number of points which I could look into in the future.

Leave a Reply

Your email address will not be published. Required fields are marked *