2 min read

Take Two

Haiku + Code

with a second take
dance with the first – tethered mass
orbiting encores
let take1, take2; //each action
let colorOfAction, gesso; //contrasted with color from canvas
let m;

function setup() {
  //placed on the easle of you
  createCanvas((m = 0.95 * min(windowWidth, windowHeight)), m);
  noStroke();
  startBodies(); //everything begins - an intitial state of now
}
function draw() {
  //a center is found
  let centerX = (take1.x + take2.x) / 2;
  let centerY = (take1.y + take2.y) / 2;
  //and your focus is placed
  translate(width / 2 - centerX, height / 2 - centerY);
  //and then painted over time
  for (let i = 0; i < 500; i++) {
    let x = random(-width / 2, width / 2) + centerX;
    let y = random(-height / 2, height / 2) + centerY;
    let d1 = dist(x, y, take1.x, take1.y);
    let d2 = dist(x, y, take2.x, take2.y);
    if (d1 <= take1.m && d2 <= take2.m) {
      fill(gesso);
    } else if (d1 <= take1.m || d2 <= take2.m) {
      fill(colorOfAction);
    } else {
      fill(gesso);
    }
    circle(x, y, random(1, 8));
  }
  //and the state of you changes with each moment in time
  updateBodies();
}

function updateBodies() {
  let dx = take2.x - take1.x;
  let dy = take2.y - take1.y;
  let distance = dist(take2.x, take2.y, take1.x, take1.y);

  if (distance < 1) return;

  let force = (10 * (take1.m * take2.m)) / (distance * distance);
  let ux = dx / distance;
  let uy = dy / distance;

  take1.vx += (force * ux) / take1.m;
  take1.vy += (force * uy) / take1.m;
  take2.vx -= (force * ux) / take2.m;
  take2.vy -= (force * uy) / take2.m;

  take1.x += take1.vx;
  take1.y += take1.vy;
  take2.x += take2.vx;
  take2.y += take2.vy;
}

function startBodies() {
  colorOfAction = color(
    random(140, 205),
    random(160, 245),
    random(200, 255),
    120
  );
  gesso = color(255, 255, 255, 120);

  take1 = { x: -m / 5, y: 0, vx: 0, vy: 0, m: random(20, 80) };
  take2 = { x: m / 5, y: 0, vx: 0, vy: 0, m: random(20, 80) };

  let r = (2 * m) / 5;
  let totalMass = take1.m + take2.m;
  let v1 = sqrt((10 * take2.m * take2.m) / (totalMass * r));
  let v2 = sqrt((10 * take1.m * take1.m) / (totalMass * r));

  let ellipticalFactor = random(0.85, 1.15);
  take1.vy = v1 * ellipticalFactor;
  take2.vy = -v2 * ellipticalFactor;

  let horizontalPerturbation = random(-0.1, 0.1);
  take1.vx = horizontalPerturbation;
  take2.vx = -horizontalPerturbation;
}

function mousePressed() {
  startBodies();
}

This post is a submission to the Indie Web Camp Carnival - "Take Two" for June 2025.

Want to become a better programmer? Join the Recurse Center!

Sophia

Mathematics educator and creative coder exploring the beauty of mathematical concepts through interactive visualizations and playful learning.

Mathematics

Education

Creative Coding