xity.dev

a city of shapes, a shape of cities

procedural geometry

function hexagon(cx, cy, r) {
  const pts = [];
  for (let i = 0; i < 6; i++) {
    const angle = (Math.PI / 3) * i - Math.PI / 2;
    pts.push([
      cx + r * Math.cos(angle),
      cy + r * Math.sin(angle)
    ]);
  }
  return pts;
}

triangles in formation

"Every pixel is a decision. Most of them are wrong, and that's what makes the picture interesting."

scatter field

move your cursor to scatter the shapes

glitch displacement

function glitchSlice(ctx, y, h, offset) {
  const imgData = ctx.getImageData(0, y, w, h);
  ctx.clearRect(0, y, w, h);
  ctx.putImageData(imgData, offset, y);
  setTimeout(() => {
    ctx.clearRect(0, y, w, h);
    ctx.putImageData(imgData, 0, y);
  }, 120);
}
"Algorithms don't dream, but sometimes their output looks like one."

hexagonal pulse

sine bloom

for (let i = 0; i < 360; i += 6) {
  const rad = (i * Math.PI) / 180;
  const x = cx + Math.sin(rad * 3) * r;
  const y = cy + Math.cos(rad * 5) * r;
  drawHex(x, y, 8);
}

formation dance

shapes reform after scattering

"A city is just a masonry grid with people in the gaps. xity is the same, but with hexagons."

square glitch field

channel split

function channelSplit(ctx, shape) {
  ctx.globalAlpha = 0.6;
  ctx.fillStyle = '#9B8FFF';
  drawShape(ctx, shape, -3, -2);
  ctx.fillStyle = '#5EEDC7';
  drawShape(ctx, shape, 3, 2);
  ctx.fillStyle = '#FF6B7A';
  drawShape(ctx, shape, 0, -3);
  ctx.globalAlpha = 1;
}