bnb({
w, h,
numFrames: 60,
fps: 20,
record: true,
shutterAngle: 0,
samplesPerFrame: 8,
chromaticAberration: 1,
setup: (s, g) => {
class Pt{
constructor(x, y) {
this.pos = PVector(x, y)
this.dir = this.pos.clone().sub(PVector(w/2, h/2)).norm().mult(20)
this.offset = this.pos.clone().sub(PVector(w/2, h/2)).mag() / 400
}
display(s, t) {
const sinT = (s.sin((-t + this.offset) * s.TAU) * .5 + .5)
s.push()
s.translate(this.pos.x + s.random(-1, 1), this.pos.y + s.random(-1, 1))
const t2 = linearstep(t ** 4, .3, .8)
s.rotate(easings.easeQuadInOut(t2) * s.PI/3)
s.noStroke()
s.fill(255)
const r = 8 * 2 + sinT * 18 * 2
s.beginShape()
for(let i = 0; i < 6; i ++) {
const angle = s.TAU / 6 * i - s.PI/2
s.vertex(s.cos(angle) * r, s.sin(angle) * r)
}
s.endShape(s.CLOSE)
s.pop()
}
}
g.pts = []
const ny = (g.h / spacingH | 0) + 25
const marginY = (g.h - ny * spacingH) / 2
for(let j = 0; j < ny; j++) {
const y = marginY + j * spacingH
const nx = (g.w / spacingW | 0) + (j % 2 ? 26 : 25)
const marginX = (g.w - nx * spacingW)/2
for(let i = 0; i < nx; i++) {
g.pts.push(new Pt(marginX + i * spacingW, y))
}
}
},
draw: (s, t, g) => {
s.background(33)
s.drawingContext.globalCompositeOperation = 'xor'
g.pts.forEach(pt => pt.display(s, t))
}
})