p5.js system

Analog Algorithm

A rule-based drawing where dice values control line length, direction and repetition.

Back
View full p5.js code
let numPlayers = 4;
let maxCycles = 5;
let stepSize = 32;
let players = [];

let totalRestarts = 0;
let maxRestarts = 5;
let isWaiting = false;
let waitStartTime = 0;
let restartButton;

function setup() {
  const canvas = createCanvas(600, 600);
  canvas.parent('sketchHolder');

  restartButton = select('#restartSketch');
  if (restartButton) {
    restartButton.mousePressed(() => {
      totalRestarts = 0;
      loop();
      initDrawing();
    });
  }

  initDrawing();
}

function initDrawing() {
  background(220);
  stroke(0);
  strokeWeight(2);
  players = [];
  isWaiting = false;

  let centerX = width / 2;
  let centerY = height / 2;
  let offset = 70;

  let startPositions = [
    { x: centerX - offset, y: centerY - offset },
    { x: centerX + offset, y: centerY - offset },
    { x: centerX + offset, y: centerY + offset },
    { x: centerX - offset, y: centerY + offset }
  ];

  for (let i = 0; i < numPlayers; i++) {
    players.push({
      startX: startPositions[i].x,
      startY: startPositions[i].y,
      x: startPositions[i].x,
      y: startPositions[i].y,
      currentStep: 0,
      currentCycle: 0,
      delay: i * 5,
      finished: false
    });
  }
}

function draw() {
  if (!isWaiting) {
    for (let p of players) {
      if (!p.finished && frameCount > p.delay && frameCount % 6 === 0) {
        let dice = floor(random(1, 7));
        let dist = dice * stepSize;
        let prevX = p.x;
        let prevY = p.y;

        if (p.currentStep === 0) p.y -= dist;
        else if (p.currentStep === 1) p.x += dist;
        else if (p.currentStep === 2) p.y += dist;
        else if (p.currentStep === 3) p.x -= dist;

        p.x = constrain(p.x, 0, width);
        p.y = constrain(p.y, 0, height);

        line(prevX, prevY, p.x, p.y);
        p.currentStep++;

        if (p.currentStep > 3) {
          p.currentStep = 0;
          p.currentCycle++;
          p.x = p.startX;
          p.y = p.startY;

          if (p.currentCycle >= maxCycles) p.finished = true;
        }
      }
    }

    if (players.every(p => p.finished)) {
      isWaiting = true;
      waitStartTime = millis();
      totalRestarts++;
    }
  } else {
    if (totalRestarts < maxRestarts) {
      if (millis() - waitStartTime > 5000) {
        initDrawing();
      }
    } else {
      noLoop();
    }
  }
}