The Effort Trap
About This Sketch
Three paths, same starting point, same goal. One moves directly, efficiently closing the distance. Another wanders but progresses. The third thrashes randomly, expending massive effort while barely advancing.
The sketch visualizes a fundamental truth about work: effort is a multiplier on direction. The high-efficiency path reaches the goal with minimal steps. The low-efficiency path burns 10x the energy and still fails. All three "work hard" but only direction determines results.
Watch the wasted-effort path (red/orange) meander aimlessly despite constant movement. Every step costs energy, but random direction means zero progress. This is what grinding without strategy looks like—motion mistaken for progress, busyness confused with productivity.
The smart-work path (golden) isn't lucky or talented. It continuously corrects course toward the goal. Same effort, better direction, exponentially better results. This is what working smart looks like—ruthless efficiency about where energy goes.
Algorithm
Pseudocode
SETUP:
Create canvas (400x300)
Initialize three paths with different efficiency values:
- High efficiency (0.9): Direct path
- Medium efficiency (0.5): Somewhat wandering
- Low efficiency (0.1): Very wandering
FOR each path:
INITIALIZE:
- Starting position (left side)
- Initial direction (toward goal)
- Efficiency parameter (0-1)
- Target (right side, center)
DRAW (every frame):
Get current theme colors
Clear background
Draw goal indicator (concentric circles at target)
FOR each active path:
UPDATE:
Calculate ideal direction toward goal
Blend current direction with ideal based on efficiency
Add random wobble inversely proportional to efficiency
Move in current direction
Track effort (increment step counter)
Calculate progress (distance to goal)
Check if reached goal or exhausted effort
DRAW:
Choose color based on efficiency level
Draw path as connected line segments
Show current position if still active
Show success/failure indicator if finished
Draw labels and legend
IF all paths finished AND sufficient time passed:
Reset animation with new paths
Source Code
let sketch = function(p) {
let paths = [];
let currentPath = 0;
class Path {
constructor(startX, startY, direction, efficiency) {
this.points = [{x: startX, y: startY}];
this.direction = direction; // angle in radians
this.efficiency = efficiency; // how direct the path is (0-1)
this.effort = 0; // total effort expended
this.progress = 0; // actual progress toward goal
this.color = null;
this.active = true;
this.targetX = 350; // goal is right side
this.targetY = 150; // goal is middle
this.wobble = p.random(0.1, 0.3); // how much the path wanders
}
update() {
if (!this.active) return;
let last = this.points[this.points.length - 1];
// Calculate ideal direction toward goal
let idealAngle = p.atan2(this.targetY - last.y, this.targetX - last.x);
// Blend current direction with ideal direction based on efficiency
this.direction = p.lerp(
this.direction + p.random(-this.wobble, this.wobble),
idealAngle,
this.efficiency
);
// Move in current direction
let stepSize = 3;
let newX = last.x + p.cos(this.direction) * stepSize;
let newY = last.y + p.sin(this.direction) * stepSize;
// Constrain to canvas
newX = p.constrain(newX, 10, 390);
newY = p.constrain(newY, 60, 240);
this.points.push({x: newX, y: newY});
// Track effort (every step costs effort)
this.effort += 1;
// Track progress (distance toward goal)
let distToGoal = p.dist(newX, newY, this.targetX, this.targetY);
let startDist = p.dist(this.points[0].x, this.points[0].y, this.targetX, this.targetY);
this.progress = p.map(distToGoal, startDist, 0, 0, 100);
// Stop if reached goal or hit edge repeatedly
if (distToGoal < 20 || this.effort > 200) {
this.active = false;
}
}
draw(colors) {
// Color based on efficiency
let pathColor;
if (this.efficiency > 0.7) {
pathColor = colors.accent1; // Good direction
} else if (this.efficiency > 0.3) {
pathColor = colors.accent3; // Neutral
} else {
pathColor = colors.accent2; // Bad direction
}
// Draw path
p.noFill();
p.stroke(...pathColor, 150);
p.strokeWeight(2);
p.beginShape();
for (let pt of this.points) {
p.vertex(pt.x, pt.y);
}
p.endShape();
// Draw current position
if (this.active) {
let last = this.points[this.points.length - 1];
p.fill(...pathColor, 200);
p.noStroke();
p.circle(last.x, last.y, 6);
}
// Draw endpoint if finished
if (!this.active) {
let last = this.points[this.points.length - 1];
let distToGoal = p.dist(last.x, last.y, this.targetX, this.targetY);
if (distToGoal < 20) {
// Success - reached goal
p.fill(...pathColor, 150);
p.noStroke();
p.circle(last.x, last.y, 12);
} else {
// Failed - gave up
p.stroke(...pathColor, 100);
p.strokeWeight(2);
p.noFill();
p.circle(last.x, last.y, 8);
p.line(last.x - 4, last.y - 4, last.x + 4, last.y + 4);
p.line(last.x - 4, last.y + 4, last.x + 4, last.y - 4);
}
}
}
}
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
// Create three paths with different efficiencies
// High efficiency - direct path
paths.push(new Path(50, 100, 0, 0.9));
// Medium efficiency - somewhat wandering
paths.push(new Path(50, 150, 0, 0.5));
// Low efficiency - very wandering
paths.push(new Path(50, 200, 0, 0.1));
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
// Draw goal
p.fill(...colors.accent1, 50);
p.noStroke();
p.circle(350, 150, 30);
p.fill(...colors.accent1, 100);
p.circle(350, 150, 20);
p.fill(...colors.accent1, 200);
p.circle(350, 150, 8);
// Update and draw all paths
for (let path of paths) {
path.update();
path.draw(colors);
}
// Draw labels
p.fill(...colors.accent3);
p.noStroke();
p.textAlign(p.LEFT, p.CENTER);
p.textSize(9);
p.text("Start", 10, 150);
p.text("Goal", 360, 150);
// Draw title and legend
p.textAlign(p.CENTER, p.TOP);
p.textSize(11);
p.fill(...colors.accent3);
p.text("Effort × Direction = Results", 200, 15);
p.textSize(8);
p.textAlign(p.LEFT, p.TOP);
p.fill(...colors.accent1);
p.text("High Efficiency: Smart Work", 20, 35);
p.fill(...colors.accent3);
p.text("Medium Efficiency: Busy Work", 20, 47);
p.fill(...colors.accent2);
p.text("Low Efficiency: Wasted Effort", 20, 59);
// Check if all paths are done, restart animation
let allDone = paths.every(p => !p.active);
if (allDone && p.frameCount > 180) {
paths = [];
paths.push(new Path(50, 100, 0, 0.9));
paths.push(new Path(50, 150, 0, 0.5));
paths.push(new Path(50, 200, 0, 0.1));
}
};
};