The Clean Slate Lie
About This Sketch
A haunting visualization of psychological persistence. This sketch shows a traveler moving between "fresh starts" - new cities, new jobs, new beginnings - but leaving trails of ghost patterns behind. The trails persist and accumulate, making visible the uncomfortable truth that we carry our patterns with us wherever we go.
Watch as the traveler seeks clean slates, only to find their patterns have already arrived. The ghost trails represent the behavioral tendencies, thought patterns, and psychological defense mechanisms that make you you - and that no change of scenery can erase without deliberate internal work.
Algorithm
This sketch visualizes the core thesis of "The Clean Slate Lie" - that our psychological patterns follow us wherever we go.
A traveler (representing "you") moves between different destinations labeled as fresh starts: "New City," "New Job," "New Start," etc. As the traveler moves, it leaves behind ghost trails that persist and accumulate. These trails represent the patterns, habits, and psychological tendencies that follow you to each new context.
The visual metaphor makes concrete the abstract idea that changing your environment doesn't erase your patterns - they travel with you, accumulating across contexts. The ghost trails fade slowly but continuously spawn, showing that patterns are persistent and self-reinforcing.
This accompanies the blog post exploring why geographic cures and context changes fail to transform us without deliberate internal work.
Pseudocode
SETUP:
Initialize canvas (400x300)
Define traveler starting position (center)
Create array of destination locations with labels
Initialize empty array for ghost trails
DRAW (every frame):
Get current theme colors
Clear background
Calculate distance from traveler to target destination
IF traveler not at target:
Move traveler toward target (smooth interpolation)
Every 3 frames: spawn new ghost trail at traveler position
ELSE:
Increment move timer
IF timer exceeds threshold:
Select next destination
Reset timer
FOR each ghost trail:
Update opacity (fade out slowly)
Display trail with theme-aware colors
Remove if fully faded
FOR each destination:
Draw destination marker (circle)
Highlight current destination
Display label text
Draw traveler as glowing dot
Display "You" label
IF many trails accumulated:
Display insight text about pattern accumulation
Show legend explaining ghost trails
Source Code
let sketch = function(p) {
// Visualization: "ghost traces" following a moving point
// Represents how patterns follow you across contexts
// The main dot moves to "new locations" but leaves persistent trails
// showing that wherever you go, your patterns have already been there
let traveler = {
x: 200,
y: 150,
targetX: 200,
targetY: 150,
destinations: []
};
let ghostTrails = []; // The patterns that follow
let historyPoints = [];
let moveTimer = 0;
let currentDestination = 0;
class GhostTrail {
constructor(x, y, generation) {
this.x = x;
this.y = y;
this.generation = generation;
this.opacity = 200;
this.fadeRate = 0.5;
this.size = 3;
}
update() {
this.opacity -= this.fadeRate;
return this.opacity > 0;
}
display(colors) {
let alpha = p.max(0, this.opacity);
p.noStroke();
// Older generations are darker (deeper patterns)
if (this.generation > 20) {
p.fill(...colors.accent2, alpha * 0.6);
} else if (this.generation > 10) {
p.fill(...colors.accent1, alpha * 0.5);
} else {
p.fill(...colors.accent3, alpha * 0.4);
}
p.circle(this.x, this.y, this.size);
}
}
p.setup = function() {
p.createCanvas(400, 300);
// Define "new locations" the traveler will visit
traveler.destinations = [
{x: 100, y: 100, label: "New City"},
{x: 300, y: 80, label: "New Job"},
{x: 320, y: 200, label: "New Start"},
{x: 80, y: 220, label: "Fresh Beginning"},
{x: 200, y: 150, label: "Another Chance"}
];
traveler.targetX = traveler.destinations[0].x;
traveler.targetY = traveler.destinations[0].y;
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
// Title
p.fill(...colors.accent3);
p.noStroke();
p.textAlign(p.CENTER);
p.textSize(12);
p.text('The Clean Slate Lie', 200, 20);
// Subtitle
p.textSize(7);
p.fill(...colors.accent3, 180);
p.text('Your patterns follow you everywhere', 200, 32);
// Move traveler toward target
let dx = traveler.targetX - traveler.x;
let dy = traveler.targetY - traveler.y;
let distance = p.sqrt(dx * dx + dy * dy);
if (distance > 2) {
traveler.x += dx * 0.03;
traveler.y += dy * 0.03;
// Create ghost trails as the traveler moves
if (p.frameCount % 3 === 0) {
ghostTrails.push(new GhostTrail(
traveler.x + p.random(-5, 5),
traveler.y + p.random(-5, 5),
currentDestination
));
}
} else {
moveTimer++;
// Stay at destination for a while, then move to next
if (moveTimer > 120) {
currentDestination = (currentDestination + 1) % traveler.destinations.length;
traveler.targetX = traveler.destinations[currentDestination].x;
traveler.targetY = traveler.destinations[currentDestination].y;
moveTimer = 0;
}
}
// Update and display ghost trails
ghostTrails = ghostTrails.filter(ghost => {
ghost.update();
ghost.display(colors);
return ghost.opacity > 0;
});
// Draw destinations
for (let i = 0; i < traveler.destinations.length; i++) {
let dest = traveler.destinations[i];
let isCurrent = i === currentDestination;
// Destination marker
p.noFill();
if (isCurrent) {
p.stroke(...colors.accent1, 150);
p.strokeWeight(2);
} else {
p.stroke(...colors.accent3, 80);
p.strokeWeight(1);
}
p.circle(dest.x, dest.y, 30);
// Label
p.noStroke();
p.fill(...colors.accent3, isCurrent ? 200 : 100);
p.textAlign(p.CENTER);
p.textSize(7);
p.text(dest.label, dest.x, dest.y + 25);
}
// Draw the traveler (you)
p.noStroke();
p.fill(...colors.accent1, 220);
p.circle(traveler.x, traveler.y, 8);
// Glow effect
p.fill(...colors.accent1, 60);
p.circle(traveler.x, traveler.y, 16);
// Label for traveler
p.fill(...colors.accent3, 200);
p.textSize(7);
p.textAlign(p.CENTER);
p.text('You', traveler.x, traveler.y - 15);
// Show insight about patterns
if (ghostTrails.length > 50) {
p.fill(...colors.accent2, 200);
p.textAlign(p.CENTER);
p.textSize(7);
p.text('Notice: Your patterns accumulate across contexts', 200, 280);
}
// Legend
p.textAlign(p.LEFT);
p.textSize(6);
p.fill(...colors.accent3, 150);
p.text('Ghost trails = patterns that follow you', 10, 290);
};
};