bouncingBallsWithTrails = phases =>
p5(sketch => {
const height = 100;
const radius = 20;
const toObject = n =>
typeof n === 'number' || n.hasOwnProperty("value") ? { phase: n } : n;
const circles = phases.map(objOrValue => ({
period: 10,
phase: 0,
...toObject(objOrValue)
}));
let pg;
let pmillis;
const resolve = value =>
value.hasOwnProperty("value") ? value.value : value;
sketch.setup = () => {
sketch.createCanvas(width, height);
sketch.angleMode(sketch.DEGREES);
sketch.colorMode(sketch.HSB);
sketch.noStroke();
pg = sketch.createGraphics(width, height);
pg.background(255);
pg.colorMode(sketch.HSB);
pg.noStroke();
circles.forEach((obj, i) => {
obj.hue =
obj.hue || circles.length === 1
? 240
: sketch.map(i, 0, circles.length - 1, 0, 240);
});
pmillis = sketch.millis();
};
sketch.draw = () => {
const scroll = sketch.max(
-1,
sketch.round((sketch.millis() - pmillis) / (1000 / 30))
);
pmillis = sketch.millis();
pg.image(pg, -scroll, 0);
sketch.image(pg, 0, 0);
for (const { period, phase, hue, x } of circles) {
const x = width - radius;
const y = sketch.map(
sketch.sin(sketch.millis() / period + resolve(phase)),
-1,
1,
radius,
height - radius
);
pg.fill(hue, 100, 100, .005);
pg.circle(x, y, radius);
pg.fill(hue, 100, 100, .005);
pg.circle(x, y, radius * .8);
sketch.fill(hue, 100, 100);
sketch.circle(x, y, radius);
}
};
})