Motion: Collision

Handle basic circle-circle collisions and simple response.

Example 1: Pair Collision Swap

Code

let a = { x: 120, y: 200, vx: 2.2, vy: 1.5, r: 30 };
let b = { x: 280, y: 220, vx: -2.4, vy: -1.2, r: 36 };

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(250);
  move(a); move(b);

  const d = dist(a.x, a.y, b.x, b.y);
  if (d < a.r + b.r) {
    [a.vx, b.vx] = [b.vx, a.vx];
    [a.vy, b.vy] = [b.vy, a.vy];
  }

  fill(255, 45, 140, 180); circle(a.x, a.y, a.r * 2);
  fill(20, 30, 40, 170); circle(b.x, b.y, b.r * 2);
}

function move(o) {
  o.x += o.vx; o.y += o.vy;
  if (o.x < o.r || o.x > width - o.r) o.vx *= -1;
  if (o.y < o.r || o.y > height - o.r) o.vy *= -1;
}

Try this: Try masses by scaling velocity swap amount with radius.

Open sketch in new tab

Example 2: Multi Ball Separation

Code

let balls = [];

function setup() {
  createCanvas(400, 400);
  for (let i = 0; i < 10; i++) {
    balls.push({
      x: random(40, 360), y: random(40, 360),
      vx: random(-2, 2), vy: random(-2, 2), r: 16
    });
  }
}

function draw() {
  background(252);
  for (const b of balls) {
    b.x += b.vx; b.y += b.vy;
    if (b.x < b.r || b.x > width - b.r) b.vx *= -1;
    if (b.y < b.r || b.y > height - b.r) b.vy *= -1;
  }

  for (let i = 0; i < balls.length; i++) {
    for (let j = i + 1; j < balls.length; j++) {
      const bi = balls[i], bj = balls[j];
      let dx = bj.x - bi.x, dy = bj.y - bi.y;
      let d = sqrt(dx * dx + dy * dy) || 0.001;
      let minD = bi.r + bj.r;
      if (d < minD) {
        let push = (minD - d) * 0.5;
        dx /= d; dy /= d;
        bi.x -= dx * push; bi.y -= dy * push;
        bj.x += dx * push; bj.y += dy * push;
      }
    }
  }

  noStroke();
  fill(255, 45, 140, 180);
  for (const b of balls) circle(b.x, b.y, b.r * 2);
}

Try this: Increase count and reduce size to make dense swarms.

Open sketch in new tab

Resources