The Coziness Industrial Complex
About This Sketch
A visualization contrasting performed coziness with natural comfort. Complex, hollow geometric shapes with dollar signs represent the coziness industrial complex—expensive, busy, and actually stress-inducing. Simple, solid, warmly-glowing shapes represent natural comfort—cheap, lasting, and genuinely comfortable. Watch the complexity meter rise as performed coziness accumulates, while actual comfort comes from simpler sources. The 75/25 ratio reflects modern reality: we're drowning in aesthetic performance of comfort while losing access to simple, natural ease.
Algorithm
This sketch visualizes the contrast between performed coziness and natural comfort through two types of objects that accumulate on screen.
Performed coziness items (75% of spawns) are represented as hollow, complex geometric shapes with multiple overlapping patterns, dollar signs, and rapid spinning. They contribute to a "complexity" meter and have negative comfort values—actually adding stress rather than comfort. They're visually busy, short-lived, and fade quickly.
Natural comfort items (25% of spawns) appear as simple, solid polygons with warm glowing centers and gentle pulsing. They contribute positively to an "actual comfort" meter, last much longer, and create subtle ripple effects showing lasting impact. They rotate slowly and peacefully.
The sketch tracks and displays both "Actual Comfort" and "Complexity" levels in real-time bars, making visible how the accumulation of performed coziness increases stress while simple comfort creates genuine ease. The 75/25 ratio reflects how performed coziness has overtaken natural comfort in modern culture.
This accompanies the blog post "The Coziness Industrial Complex" which explores how comfort has been turned into a consumption aesthetic that's actually uncomfortable.
Pseudocode
SETUP:
Initialize canvas (400x300)
Create empty array for cozy items
DRAW (every frame):
Get current theme colors
Semi-transparent background (creates trailing effect)
Draw title
SPAWN NEW ITEMS (4% chance per frame):
75% chance: Create performed coziness item
- Complex (8-16 sided geometric)
- Hollow with overlapping shapes
- High complexity value (15-30)
- Fast rotation and pulsing
- Short lifespan (30-60 frames)
- Negative comfort impact
25% chance: Create natural comfort item
- Simple (3-6 sided polygon)
- Solid with warm glow
- Low complexity value (1-5)
- Slow rotation and gentle pulse
- Long lifespan (200-400 frames)
- High positive comfort impact
UPDATE ALL ITEMS:
Age each item
Apply rotation and pulsing
Fade out near end of lifespan
Remove if lifespan exceeded
DISPLAY ALL ITEMS:
For performed items:
Draw multiple overlapping geometric shapes
Add tiny center (low actual comfort)
Show dollar sign (expensive)
For natural items:
Draw simple solid shape
Add warm inner glow
Create gentle ripple effect (lasting impact)
CALCULATE METRICS:
Sum complexity from performed items
Sum comfort from natural items
Display bars showing levels
DRAW LEGEND:
Show example of each type
Explain what you're seeing
Add bottom note about observation
Source Code
let sketch = function(p) {
let cozyItems = [];
let maxItems = 50;
let stressLevel = 0;
// Two types: natural comfort vs performed coziness
class CozyItem {
constructor(x, y, isPerformed) {
this.x = x;
this.y = y;
this.isPerformed = isPerformed;
this.age = 0;
if (isPerformed) {
// Performed coziness: lots of items, complex, stressful
this.comfortValue = p.random(-0.2, 0.1); // Usually adds stress
this.complexity = p.random(15, 30); // High complexity
this.cost = p.random(50, 200); // Expensive
this.size = p.random(6, 12);
this.rotationSpeed = p.random(0.02, 0.05); // Busy
this.pulseSpeed = p.random(0.05, 0.1); // Demanding attention
this.lifespan = p.random(30, 60); // Short-lived trend
this.numLines = Math.floor(p.random(8, 16)); // Complex shape
} else {
// Natural comfort: simple, effective, cheap
this.comfortValue = p.random(0.5, 1.0); // Actually comfortable
this.complexity = p.random(1, 5); // Simple
this.cost = p.random(0, 20); // Cheap or free
this.size = p.random(8, 15); // Substantial but simple
this.rotationSpeed = p.random(0.001, 0.01); // Calm
this.pulseSpeed = p.random(0.01, 0.02); // Gentle
this.lifespan = p.random(200, 400); // Long-lasting
this.numLines = Math.floor(p.random(3, 6)); // Simple shape
}
this.rotation = p.random(p.TWO_PI);
this.pulsePhase = p.random(p.TWO_PI);
this.alpha = 255;
}
update() {
this.age++;
this.rotation += this.rotationSpeed;
this.pulsePhase += this.pulseSpeed;
// Fade out as lifespan ends
if (this.age > this.lifespan * 0.7) {
this.alpha = p.map(this.age, this.lifespan * 0.7, this.lifespan, 255, 0);
}
return this.age < this.lifespan;
}
display(colors) {
p.push();
p.translate(this.x, this.y);
p.rotate(this.rotation);
let pulse = p.sin(this.pulsePhase) * 0.15 + 1;
let displaySize = this.size * pulse;
if (this.isPerformed) {
// Performed coziness: Complex, hollow, geometric
p.noFill();
p.stroke(...colors.accent3, this.alpha * 0.8);
p.strokeWeight(1.5);
// Multiple overlapping shapes (complexity)
for (let i = 0; i < 3; i++) {
p.push();
p.rotate((p.TWO_PI / 3) * i);
p.beginShape();
for (let j = 0; j < this.numLines; j++) {
let angle = (p.TWO_PI / this.numLines) * j;
let r = displaySize * (0.5 + i * 0.2);
let px = p.cos(angle) * r;
let py = p.sin(angle) * r;
p.vertex(px, py);
}
p.endShape(p.CLOSE);
p.pop();
}
// Tiny core (low actual comfort)
p.fill(...colors.accent3, this.alpha * 0.3);
p.noStroke();
p.circle(0, 0, displaySize * 0.2);
// Price tag indicator (dollar signs)
p.fill(...colors.accent2, this.alpha * 0.5);
p.textSize(6);
p.textAlign(p.CENTER, p.CENTER);
p.text('$', 0, -displaySize * 0.7);
} else {
// Natural comfort: Simple, solid, warm
p.fill(...colors.accent1, this.alpha * 0.7);
p.noStroke();
// Simple shape
p.beginShape();
for (let j = 0; j < this.numLines; j++) {
let angle = (p.TWO_PI / this.numLines) * j;
let r = displaySize;
let px = p.cos(angle) * r;
let py = p.sin(angle) * r;
p.vertex(px, py);
}
p.endShape(p.CLOSE);
// Warm glow (actual comfort)
p.fill(...colors.accent2, this.alpha * 0.5);
p.circle(0, 0, displaySize * 0.6);
// Gentle ripple of lasting comfort
if (this.age > 20) {
let rippleSize = p.map(p.sin(this.age * 0.02), -1, 1, displaySize * 1.2, displaySize * 1.5);
let rippleAlpha = this.alpha * 0.2;
p.noFill();
p.stroke(...colors.accent1, rippleAlpha);
p.strokeWeight(1);
p.circle(0, 0, rippleSize);
}
}
p.pop();
}
}
p.setup = function() {
p.createCanvas(400, 300);
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg, 60); // Trails
// Title
p.fill(...colors.accent3);
p.noStroke();
p.textAlign(p.CENTER);
p.textSize(11);
p.text('The Coziness Industrial Complex', 200, 18);
// Generate new items
// 75% performed (reflects reality)
if (p.random() < 0.04 && cozyItems.length < maxItems) {
let isPerformed = p.random() < 0.75;
let x = p.random(50, 350);
let y = p.random(50, 250);
cozyItems.push(new CozyItem(x, y, isPerformed));
}
// Calculate cumulative stress
stressLevel = 0;
let comfortLevel = 0;
for (let item of cozyItems) {
if (item.isPerformed) {
stressLevel += item.complexity * 0.1;
} else {
comfortLevel += item.comfortValue * 2;
}
}
// Update and display items
for (let i = cozyItems.length - 1; i >= 0; i--) {
if (!cozyItems[i].update()) {
cozyItems.splice(i, 1);
} else {
cozyItems[i].display(colors);
}
}
// Stress/Comfort meter
p.textAlign(p.LEFT);
p.textSize(8);
p.fill(...colors.accent3);
p.text('Actual Comfort:', 15, 270);
p.text('Complexity:', 15, 285);
// Comfort bar (goes up with simple items)
let comfortWidth = p.constrain(comfortLevel * 8, 0, 100);
p.fill(...colors.accent1, 150);
p.noStroke();
p.rect(95, 263, comfortWidth, 8, 2);
// Stress bar (goes up with performed items)
let stressWidth = p.constrain(stressLevel, 0, 100);
p.fill(...colors.accent3, 150);
p.rect(95, 278, stressWidth, 8, 2);
// Legend
p.textSize(7);
// Performed (hollow geometric)
p.push();
p.translate(220, 268);
p.noFill();
p.stroke(...colors.accent3, 200);
p.strokeWeight(1);
for (let i = 0; i < 6; i++) {
let angle = (p.TWO_PI / 6) * i;
let px = p.cos(angle) * 5;
let py = p.sin(angle) * 5;
if (i === 0) p.beginShape();
p.vertex(px, py);
if (i === 5) p.endShape(p.CLOSE);
}
p.pop();
p.fill(...colors.accent3);
p.noStroke();
p.text('Performed: Complex, expensive, stressful', 230, 271);
// Natural (simple solid)
p.fill(...colors.accent1, 180);
p.circle(225, 283, 8);
p.fill(...colors.accent2, 120);
p.circle(225, 283, 5);
p.fill(...colors.accent3);
p.text('Natural: Simple, cheap, actually comfortable', 230, 286);
// Bottom note
p.fill(...colors.accent3, 130);
p.textAlign(p.CENTER);
p.textSize(7);
p.text('Watch complexity rise. Notice what actually feels good.', 200, 297);
};
};