The Boredom Deficit
About This Sketch
Particles drift through a Perlin noise field, forming and dissolving connections as they pass close to one another. The motion is slow, aimless-lookingβbut constantly generative. This is what the mind does when left alone: wanders, finds unexpected connections, produces ideas that focused attention cannot.
The sketch visualizes the argument in "The Boredom Deficit": that an idle mind is not an empty one. The connections between particles appear without effort, without direction. They couldn't be planned. They can only happen when the particles are free to drift.
Algorithm
55 particles drift across the canvas guided by a 2D Perlin noise field,
each following a smoothly evolving direction vector. When particles come
within 48 pixels of each other, they are connected by faint lines whose
opacity scales inversely with distance. A semi-transparent background rect
drawn each frame creates trailing paths.
The result resembles a mind wandering: particles move without apparent
purpose but form and dissolve meaningful connections as they pass near
each other β representing the associative, generative thinking that
happens during boredom and mind-wandering.
This sketch accompanies the blog post "The Boredom Deficit," which argues
that eliminating boredom eliminates the mental state where original ideas
and self-knowledge are formed.
Pseudocode
SETUP:
Initialize 55 particles at random positions
Each particle has: position, velocity, noise seed, size, speed
DRAW (every frame):
Get current theme colors
Draw semi-transparent background rect (creates trails)
Increment time counter
For each particle:
Sample 2D Perlin noise at (nx + time, ny + time) β angle
Smoothly interpolate velocity toward noise direction
Update position by velocity
Wrap position at canvas edges
For each pair of particles:
Compute distance
If distance < 48px:
Draw line with alpha = map(distance, 0, 48, 65, 0)
For each particle:
Draw filled circle at position
Draw caption text
Source Code
let sketch = function(p) {
let particles = [];
let time = 0;
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
for (let i = 0; i < 55; i++) {
particles.push({
x: p.random(400),
y: p.random(300),
vx: 0,
vy: 0,
nx: p.random(1000),
ny: p.random(1000 + i * 47),
size: p.random(2, 4.5),
speed: p.random(0.4, 0.85)
});
}
};
p.draw = function() {
const colors = getThemeColors();
p.noStroke();
p.fill(...colors.bg, 38);
p.rect(0, 0, 400, 300);
time += 0.008;
for (let particle of particles) {
let angle = p.noise(particle.nx + time * 0.45, particle.ny + time * 0.3) * p.TWO_PI * 2;
particle.vx = p.lerp(particle.vx, p.cos(angle) * particle.speed, 0.06);
particle.vy = p.lerp(particle.vy, p.sin(angle) * particle.speed, 0.06);
particle.x += particle.vx;
particle.y += particle.vy;
if (particle.x < -10) particle.x = 410;
if (particle.x > 410) particle.x = -10;
if (particle.y < -10) particle.y = 310;
if (particle.y > 310) particle.y = -10;
}
for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
let d = p.dist(particles[i].x, particles[i].y, particles[j].x, particles[j].y);
if (d < 48) {
let alpha = p.map(d, 0, 48, 65, 0);
p.stroke(...colors.accent1, alpha);
p.strokeWeight(0.5);
p.line(particles[i].x, particles[i].y, particles[j].x, particles[j].y);
}
}
}
for (let particle of particles) {
p.noStroke();
p.fill(...colors.accent2, 195);
p.circle(particle.x, particle.y, particle.size);
}
p.noStroke();
p.fill(...colors.accent1, 105);
p.textAlign(p.CENTER);
p.textSize(9);
p.text('an idle mind is not empty β it is working', 200, 293);
};
};