function ease(p, g) { if (!g) { return 3*p*p - 2*p*p*p; } else { if (p < 0.5) return 0.5 * pow(2*p, g); else return 1 - 0.5 * pow(2*(1 - p), g); } } function c01(g) { return constrain(g, 0, 1); } function easeSin(q) { return lerp(sin(q), lerp(1, -1, ease(map(sin(q), 1, -1, 0, 1))), .25); } let x_shift = 0, y_shift = 0, do_y_offset = false; const N = 18; const spacing = 17, maxOffset = 26, maxDist = 242; const minDiam = 4, maxDiam = 7; const wavelength = 44; const loopLength = 40; const buffersPerFrame = 20; let halfSqrt3 = 0; let recording = false; function dots() { let x = 0, y = 0; let amplitude = 0, dist = 0, diam = 0; for (let i=-N; i<=N; i++) { for (let j=-N; j<=N; j++) { x = i*spacing; y = j*halfSqrt3*spacing; if (j%2 != 0) x += .5*spacing; dist = max([abs(y), abs(.5*y + halfSqrt3*x), abs(.5*y - halfSqrt3*x)]); if (dist < maxDist) { amplitude = c01(map(dist, 0, maxDist-spacing, 1, 0)); amplitude = 1-sq(1-amplitude); offsetx = maxOffset*easeSin(TWO_PI*x_shift - dist/wavelength)*amplitude; offsety = maxOffset*easeSin(TWO_PI*y_shift - dist/wavelength)*amplitude; x += offsetx; if (do_y_offset) { y += offsety; } diam = lerp(minDiam, maxDiam, amplitude); ellipse(x, y, diam, diam); } } } } function setup () { createCanvas(960, 480); smooth(8); rectMode(CENTER); fill(32); noStroke(); halfSqrt3 = 0.5*sqrt(3); } let gifRecorder = null; function mousePressed() { if(gifRecorder == null) { recording = true; gifRecorder = new p5recorder(loopLength, "hexripple.gif", 25, 0, buffersPerFrame); } } function draw () { let gutter = (width - height) / 2; if (!recording && mouseX > gutter && mouseX < (width - gutter) && mouseY > 30 && mouseY < (height-30)) { x_shift = (width-mouseX)*1.0/width; y_shift = (height-mouseY)*1.0/height; do_y_offset = true; } else { let frameMax = loopLength; if(recording) { frameMax = loopLength * buffersPerFrame; } let curFrame = frameCount % frameMax; x_shift = map(curFrame, 0, frameMax, 0, 1); y_shift = 0; do_y_offset = false; } push(); translate(width/2, height/2); background(0); fill(235, 0, 0); push(); translate(0, -.5); dots(); pop(); let f1 = get(); background(0); fill(0, 239, 0); push(); scale(1.005); dots(); pop(); let f2 = get(); background(0); fill(0, 0, 186); push(); translate(0, .5); scale(1.01); dots(); pop(); let f3 = get(); pop(); background(9, 8, 28); blend(f1, 0, 0, width, height, 0, 0, width, height, ADD); blend(f2, 0, 0, width, height, 0, 0, width, height, ADD); blend(f3, 0, 0, width, height, 0, 0, width, height, ADD); if(recording) { gifRecorder.addBuffer(); } } function keyTyped() { if (key == '!') { saveBlocksImages(); } }