createCanvas(sk_w, sk_h);
pa = create2DArray(width, height);
const sx = randomGaussian(width / 2, 50);
const sy = randomGaussian(height / 2, 50);
const NUM = ~~random(2, 5);
const STA = random(TWO_PI);
for (let i = 0; i < NUM; i++) {
const clr = color(random(200), random(100), random(300));
const ang = STA + i*TWO_PI/NUM + random(-0.3, 0.3)
walkers.push(new Walker(sx, sy, ang, clr, i));
x2 = ~~(random(sk_m, sk_w - sk_m));
y2 = ~~(random(sk_m, sk_h - sk_m));
while (isFinished == false && iterations-- > 0) {
for (let i = walkers.length-1; i >= 0; i--) {
if (!walkers[i].update(stp)) {
if (isFinished == true) {
console.log(`ended: S to save svg, LMB to restart`);
function create2DArray(rows, cols) {
return Array.from({ length: rows }, () => Array(cols).fill(0));
function mousePressed() {
if (mouseButton !== RIGHT && mouseButton !== CENTER && mouseX >=0 && mouseX < width && mouseY >= 0 && mouseY < height) {
if (key === 's' || key === 'S') {
let svgStr = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">\n`;
walkers = walkers.sort((a, b) => a.grp - b.grp);
for (const street of walkers) {
if (street.grp != lastGrp) {
if (lastGrp !== -1) svgStr += `</g>\n`;
svgStr += `<g fill="none" stroke="black" stroke-width="1">\n`;
svgStr += ` <line x1="${nf(street.start.x,0,3)}" y1="${nf(street.start.y,0,3)}" x2="${nf(street.pos.x,0,3)}" y2="${nf(street.pos.y,0,3)}" />\n`;
save(svgStr.split("\n"), "epi_city.svg.txt");