127 lines, no comments ยท 3,324 tokens, written in 44 seconds for $0.085


  1  let cols, rows, sp;
  2  let field = [];
  3  let t = 0;
  4  let bg;
  5  let levels = 13;
  6  let cA, cB, cC;
  7  
  8  function setup() {
  9    createCanvas(windowWidth, windowHeight);
 10    colorMode(RGB, 255);
 11    setupGrid();
 12    makeBackdrop();
 13    cA = color(255, 228, 170);
 14    cB = color(255, 110, 130);
 15    cC = color(90, 190, 255);
 16    strokeCap(ROUND);
 17  }
 18  
 19  function setupGrid() {
 20    sp = max(8, min(width, height) / 72);
 21    cols = ceil(width / sp) + 1;
 22    rows = ceil(height / sp) + 1;
 23    field = new Array(cols + 1);
 24    for (let i = 0; i <= cols; i++) field[i] = new Float32Array(rows + 1);
 25  }
 26  
 27  function makeBackdrop() {
 28    bg = createGraphics(width, height);
 29    for (let y = 0; y < height; y++) {
 30      const k = y / height;
 31      bg.stroke(lerpColor(color(8, 12, 28), color(26, 14, 34), k));
 32      bg.line(0, y, width, y);
 33    }
 34    bg.noStroke();
 35    for (let r = 420; r > 0; r -= 6) {
 36      bg.fill(255, 150, 120, 2.2);
 37      bg.ellipse(width * 0.72, height * 0.26, r * 1.6, r * 1.6);
 38    }
 39  }
 40  
 41  function windowResized() {
 42    resizeCanvas(windowWidth, windowHeight);
 43    setupGrid();
 44    makeBackdrop();
 45  }
 46  
 47  function mousePressed() {
 48    noiseSeed(floor(random(100000)));
 49  }
 50  
 51  function computeField() {
 52    const ns = 0.0042 * sp;
 53    const mx = mouseX, my = mouseY;
 54    const rad = min(width, height) * 0.22;
 55    const inside = mouseX > 0 && mouseY > 0 && mouseX < width && mouseY < height;
 56    for (let i = 0; i <= cols; i++) {
 57      for (let j = 0; j <= rows; j++) {
 58        let v = noise(i * ns, j * ns, t);
 59        v += 0.35 * noise(i * ns * 2.6 + 50, j * ns * 2.6, t * 1.7) - 0.17;
 60        if (inside) {
 61          const dx = i * sp - mx, dy = j * sp - my;
 62          const d2 = (dx * dx + dy * dy) / (rad * rad);
 63          v += 0.3 * Math.exp(-d2);
 64        }
 65        field[i][j] = v;
 66      }
 67    }
 68  }
 69  
 70  function lv(level) {
 71    const k = level / (levels - 1);
 72    return k < 0.5 ? lerpColor(cA, cB, k * 2) : lerpColor(cB, cC, (k - 0.5) * 2);
 73  }
 74  
 75  function draw() {
 76    image(bg, 0, 0);
 77    computeField();
 78  
 79    for (let L = 0; L < levels; L++) {
 80      const th = map(L, 0, levels - 1, 0.30, 0.72);
 81      const col = lv(L);
 82      const wob = 0.5 + 0.5 * sin(t * 2.2 + L * 0.5);
 83  
 84      stroke(red(col), green(col), blue(col), 26);
 85      strokeWeight(5.5);
 86      contour(th);
 87  
 88      stroke(red(col), green(col), blue(col), 120 + 100 * wob);
 89      strokeWeight(1.25);
 90      contour(th);
 91    }
 92  
 93    t += 0.0032;
 94  }
 95  
 96  function contour(th) {
 97    for (let i = 0; i < cols; i++) {
 98      const x0 = i * sp, x1 = x0 + sp;
 99      for (let j = 0; j < rows; j++) {
100        const y0 = j * sp, y1 = y0 + sp;
101        const a = field[i][j], b = field[i + 1][j], c = field[i + 1][j + 1], d = field[i][j + 1];
102        let state = 0;
103        if (a > th) state += 8;
104        if (b > th) state += 4;
105        if (c > th) state += 2;
106        if (d > th) state += 1;
107        if (state === 0 || state === 15) continue;
108  
109        const tx = x0 + sp * ((th - a) / (b - a));
110        const ry = y0 + sp * ((th - b) / (c - b));
111        const bx = x0 + sp * ((th - d) / (c - d));
112        const ly = y0 + sp * ((th - a) / (d - a));
113  
114        switch (state) {
115          case 1: case 14: line(x0, ly, bx, y1); break;
116          case 2: case 13: line(bx, y1, x1, ry); break;
117          case 3: case 12: line(x0, ly, x1, ry); break;
118          case 4: case 11: line(tx, y0, x1, ry); break;
119          case 6: case 9: line(tx, y0, bx, y1); break;
120          case 7: case 8: line(x0, ly, tx, y0); break;
121          case 5: line(x0, ly, tx, y0); line(bx, y1, x1, ry); break;
122          case 10: line(tx, y0, x1, ry); line(x0, ly, bx, y1); break;
123        }
124      }
125    }
126  }
127