The Permission Fallacy
About This Sketch
Visualizing the permission barrier A figure stands before imaginary gates that fade away when approached Represents how the gatekeepers are internalized, not external
This sketch accompanies the blog post "The Permission Fallacy" and visualizes its core concepts through generative art.
Algorithm
Visualizing the permission barrier A figure stands before imaginary gates that fade away when approached Represents how the gatekeepers are internalized, not external
This sketch was originally created as a visual companion to the blog post "The Permission Fallacy" and explores its themes through generative art.
Pseudocode
SETUP:
Initialize canvas (400x300)
Set up drawing parameters
DRAW (every frame):
Get current theme colors
Clear background
Draw generative visualization
Update animation state
Source Code
let sketch = function(p) {
// Visualizing the permission barrier
// A figure stands before imaginary gates that fade away when approached
// Represents how the gatekeepers are internalized, not external
let time = 0;
let figure = {
x: 80,
y: 220,
targetX: 80
};
let gates = [];
let numGates = 5;
class Gate {
constructor(x, label) {
this.x = x;
this.baseX = x;
this.label = label;
this.opacity = 255;
this.height = 120;
this.fadeStart = false;
}
update(figureX) {
// Gate starts fading when figure gets close
let distance = Math.abs(this.x - figureX);
if (distance < 60) {
this.fadeStart = true;
}
if (this.fadeStart) {
this.opacity -= 3;
if (this.opacity < 0) this.opacity = 0;
}
}
display(colors) {
if (this.opacity <= 0) return;
// Draw gate posts
p.stroke(...colors.accent2, this.opacity);
p.strokeWeight(3);
p.line(this.x - 15, 220, this.x - 15, 220 - this.height);
p.line(this.x + 15, 220, this.x + 15, 220 - this.height);
// Draw gate top
p.strokeWeight(2);
p.line(this.x - 15, 220 - this.height, this.x + 15, 220 - this.height);
// Draw lock symbol
p.noStroke();
p.fill(...colors.accent2, this.opacity);
p.rect(this.x - 8, 160, 16, 18, 2);
p.arc(this.x, 160, 12, 12, p.PI, p.TWO_PI);
// Label
p.textAlign(p.CENTER, p.BOTTOM);
p.textSize(7);
p.fill(...colors.accent3, this.opacity);
p.text(this.label, this.x, 140);
}
}
class Figure {
constructor(x, y) {
this.x = x;
this.y = y;
this.targetX = x;
}
update() {
// Move towards target
let diff = this.targetX - this.x;
this.x += diff * 0.02;
}
display(colors) {
// Simple stick figure
p.noFill();
p.stroke(...colors.accent1);
p.strokeWeight(2);
// Head
p.circle(this.x, this.y - 35, 12);
// Body
p.line(this.x, this.y - 29, this.x, this.y - 10);
// Arms
let armAngle = p.sin(time * 0.05) * 0.2;
p.line(this.x, this.y - 22, this.x - 10, this.y - 12 + armAngle * 10);
p.line(this.x, this.y - 22, this.x + 10, this.y - 12 - armAngle * 10);
// Legs
let legAngle = p.sin(time * 0.05 + p.PI) * 0.3;
p.line(this.x, this.y - 10, this.x - 6, this.y + legAngle * 5);
p.line(this.x, this.y - 10, this.x + 6, this.y - legAngle * 5);
}
}
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
// Initialize gates at regular intervals
gates.push(new Gate(140, "Credentials"));
gates.push(new Gate(200, "Approval"));
gates.push(new Gate(260, "Readiness"));
gates.push(new Gate(320, "Permission"));
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
// Ground line
p.stroke(...colors.accent3, 100);
p.strokeWeight(1);
p.line(0, 220, 400, 220);
// Title area
p.noStroke();
p.fill(...colors.accent3, 180);
p.textAlign(p.CENTER, p.TOP);
p.textSize(11);
p.text("The Internalized Gates", 200, 15);
// Instruction text that changes over time
if (time < 180) {
p.textSize(8);
p.fill(...colors.accent3, 150);
p.text("Waiting for permission to move forward...", 200, 32);
} else if (time < 360) {
p.textSize(8);
let alpha = p.map(p.sin((time - 180) * 0.05), -1, 1, 100, 200);
p.fill(...colors.accent1, alpha);
p.text("But the gates were never real", 200, 32);
} else {
p.textSize(8);
p.fill(...colors.accent1, 180);
p.text("You just needed to start", 200, 32);
}
// Start movement after pause
if (time === 120) {
figure.targetX = 360;
}
// Update figure position
figure.update();
// Update and display gates
for (let gate of gates) {
gate.update(figure.x);
gate.display(colors);
}
// Display figure
figure.display(colors);
// Path line showing progress
if (figure.x > 85) {
p.stroke(...colors.accent1, 100);
p.strokeWeight(1);
p.line(80, 223, figure.x, 223);
// Footprints
for (let i = 80; i < figure.x; i += 20) {
p.noStroke();
p.fill(...colors.accent1, 60);
p.ellipse(i, 223, 4, 6);
}
}
// Message at bottom showing insight
if (time > 240 && time < 480) {
let msgAlpha = Math.min((time - 240) * 2, 150);
p.textAlign(p.CENTER, p.BOTTOM);
p.textSize(9);
p.fill(...colors.accent3, msgAlpha);
p.text("The gates dissolve when approached", 200, 265);
p.textSize(8);
p.fill(...colors.accent2, msgAlpha);
p.text("They were internalized barriers, not external ones", 200, 280);
}
// Final message
if (time > 480) {
let finalAlpha = Math.min((time - 480) * 2, 160);
p.textAlign(p.CENTER, p.BOTTOM);
p.textSize(10);
p.fill(...colors.accent1, finalAlpha);
p.text("You had permission all along", 200, 265);
p.textSize(7);
p.fill(...colors.accent3, finalAlpha);
p.text("The only permission that mattered was your own", 200, 280);
}
time++;
// Loop the animation
if (time > 600) {
time = 0;
figure.x = 80;
figure.targetX = 80;
gates = [];
gates.push(new Gate(140, "Credentials"));
gates.push(new Gate(200, "Approval"));
gates.push(new Gate(260, "Readiness"));
gates.push(new Gate(320, "Permission"));
}
};
};