The Authenticity Paradox
About This Sketch
A visual contrast between rigid authenticity (particles tethered to fixed identities) and fluid growth (particles free to explore and change). The left side shows how commitment to an "authentic self" constrains movement to tiny orbits around a fixed point. The right side demonstrates the freedom of allowing identity to flow, change, and explore new territories through experimentation.
Algorithm
This sketch visualizes the paradox of authenticity through two contrasting particle systems. The left side shows "authentic" particles tethered to fixed positionsโthey can only orbit within a small radius of their original location, representing how authenticity thinking traps us in rigid identities. The right side shows fluid particles free to explore the entire space, leaving flowing trails that represent growth and change through experimentation.
The visualization accompanies the blog post "The Authenticity Paradox" which argues that rigid commitment to an "authentic self" prevents the kind of experimentation and change that leads to genuine growth.
Pseudocode
SETUP:
Create canvas (400x300)
Initialize rigid particles in fixed grid on left side
Initialize fluid particles with random positions on right side
Each particle type has different movement rules
DRAW (every frame):
Get current theme colors
Clear background
FOR each rigid particle:
Pull strongly back toward fixed starting position
Allow tiny orbital movement around that point
Draw particle with visible tether to origin
FOR each fluid particle:
Move based on Perlin noise field
Apply momentum and damping
Wrap around canvas edges
Store position history for trail
Draw flowing trail and current position
Draw dividing line between systems
Label each side with its meaning
Source Code
let sketch = function(p) {
let rigidParticles = [];
let fluidParticles = [];
let time = 0;
class RigidParticle {
constructor(x, y) {
this.startX = x;
this.startY = y;
this.x = x;
this.y = y;
this.baseAngle = p.random(p.TWO_PI);
this.orbitRadius = p.random(2, 5);
this.locked = true;
}
update() {
// Rigidly returns to fixed position
let pullX = this.startX - this.x;
let pullY = this.startY - this.y;
this.x += pullX * 0.3;
this.y += pullY * 0.3;
// Small orbit around fixed point
this.x += p.cos(this.baseAngle + time * 0.02) * this.orbitRadius * 0.5;
this.y += p.sin(this.baseAngle + time * 0.02) * this.orbitRadius * 0.5;
}
draw(colors) {
// Draw as small, constrained circle
p.fill(...colors.accent2, 150);
p.noStroke();
p.circle(this.x, this.y, 6);
// Draw tether to fixed point
p.stroke(...colors.accent2, 50);
p.strokeWeight(1);
p.line(this.x, this.y, this.startX, this.startY);
}
}
class FluidParticle {
constructor(x, y) {
this.x = x;
this.y = y;
this.vx = p.random(-1, 1);
this.vy = p.random(-1, 1);
this.trail = [];
this.maxTrail = 15;
this.angle = p.random(p.TWO_PI);
this.wobble = p.random(0.02, 0.05);
}
update() {
// Fluid movement with noise
let noiseVal = p.noise(this.x * 0.01, this.y * 0.01, time * 0.01);
this.angle += (noiseVal - 0.5) * 0.3;
// Move based on angle with wobble
this.vx += p.cos(this.angle) * 0.2;
this.vy += p.sin(this.angle) * 0.2;
// Damping
this.vx *= 0.95;
this.vy *= 0.95;
// Update position
this.x += this.vx;
this.y += this.vy;
// Wrap around edges
if (this.x < 0) this.x = p.width;
if (this.x > p.width) this.x = 0;
if (this.y < 0) this.y = p.height;
if (this.y > p.height) this.y = 0;
// Trail
this.trail.push({x: this.x, y: this.y});
if (this.trail.length > this.maxTrail) {
this.trail.shift();
}
}
draw(colors) {
// Draw trail
for (let i = 0; i < this.trail.length - 1; i++) {
let alpha = (i / this.trail.length) * 100;
p.stroke(...colors.accent1, alpha);
p.strokeWeight(2);
p.line(
this.trail[i].x, this.trail[i].y,
this.trail[i + 1].x, this.trail[i + 1].y
);
}
// Draw particle
p.fill(...colors.accent1, 200);
p.noStroke();
p.circle(this.x, this.y, 7);
}
}
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
// Create rigid particles in a fixed pattern (left side)
let gridSize = 25;
let offsetX = 80;
let offsetY = 50;
for (let i = 0; i < 6; i++) {
for (let j = 0; j < 4; j++) {
let x = offsetX + i * gridSize;
let y = offsetY + j * gridSize;
rigidParticles.push(new RigidParticle(x, y));
}
}
// Create fluid particles (right side)
for (let i = 0; i < 25; i++) {
let x = p.random(p.width * 0.5, p.width - 40);
let y = p.random(40, p.height - 40);
fluidParticles.push(new FluidParticle(x, y));
}
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
time++;
// Draw rigid particles (left - trapped by authenticity)
for (let particle of rigidParticles) {
particle.update();
particle.draw(colors);
}
// Draw fluid particles (right - free to change)
for (let particle of fluidParticles) {
particle.update();
particle.draw(colors);
}
// Draw dividing line
p.stroke(...colors.accent3, 100);
p.strokeWeight(1);
p.line(p.width / 2, 0, p.width / 2, p.height);
// Draw labels
p.fill(...colors.accent3);
p.noStroke();
p.textAlign(p.CENTER, p.TOP);
p.textSize(10);
p.text("\"Authentic\"", p.width * 0.25, 15);
p.text("(Rigid, tethered to fixed identity)", p.width * 0.25, 28);
p.text("Fluid", p.width * 0.75, 15);
p.text("(Free to explore and change)", p.width * 0.75, 28);
};
};