Where ideas percolate and thoughts brew

The Originality Trap

About This Sketch

A visualization of creative synthesis. Three influence sources (circles) remain constant, connected by subtle lines. Synthesis particles periodically emerge from their center, each taking a unique direction—representing how originality comes not from avoiding influence, but from deeply metabolizing multiple sources until something genuinely new emerges.

Algorithm

This sketch visualizes the concept of creative synthesis from multiple influences. Three static "influence" circles represent different sources of inspiration or existing work. These are connected by faint lines, showing relationships between existing ideas. Periodically, new "synthesis particles" emerge from the centroid (center point) of all influences. Each particle inherits aspects from all influences (blended color, central starting position) but moves in its own unique direction, representing how true originality emerges not from avoiding influence but from metabolizing multiple influences into something new. The particles fade as they move away from their sources, visualizing how synthesized ideas take on their own life and become distinct from their origins. The visual metaphor: originality isn't created in isolation—it emerges from the unique combination and transformation of existing influences.

Pseudocode

SETUP:
  Initialize canvas (400x300)
  Create 3 influence circles at fixed positions
  Each influence has a position, color hue, and size

DRAW (every frame):
  Get current theme colors
  Draw semi-transparent background (creates trail effect)

  Display all influence circles

  Every 15 frames:
    Create new synthesis particle
    Position at centroid of all influences
    Assign random direction and speed
    Blend colors from multiple influences

  For each synthesis particle:
    Move in assigned direction
    Fade out over time
    Remove when fully faded or off-screen

  Draw connecting lines between influences (subtle)

Source Code

let sketch = function(p) {
    let influences = [];
    let synthesis = [];
    let time = 0;

    class Influence {
        constructor(x, y, hue) {
            this.x = x;
            this.y = y;
            this.hue = hue;
            this.size = p.random(20, 40);
            this.alpha = 180;
        }

        display(colors) {
            p.noStroke();
            let col = p.lerpColor(
                p.color(...colors.accent1, this.alpha),
                p.color(...colors.accent2, this.alpha),
                this.hue
            );
            p.fill(col);
            p.ellipse(this.x, this.y, this.size);
        }
    }

    class SynthesisParticle {
        constructor(influences, colors) {
            // Start at centroid of influences
            let avgX = influences.reduce((sum, inf) => sum + inf.x, 0) / influences.length;
            let avgY = influences.reduce((sum, inf) => sum + inf.y, 0) / influences.length;
            this.x = avgX;
            this.y = avgY;

            // Move in unique direction (the "synthesis")
            this.angle = p.random(p.TWO_PI);
            this.speed = p.random(1, 3);
            this.life = 255;
            this.size = p.random(4, 8);

            // Color blends all influences
            this.color = p.lerpColor(
                p.color(...colors.accent1),
                p.color(...colors.accent3),
                p.random()
            );
        }

        update() {
            this.x += p.cos(this.angle) * this.speed;
            this.y += p.sin(this.angle) * this.speed;
            this.life -= 2;
        }

        display() {
            p.noStroke();
            this.color.setAlpha(this.life);
            p.fill(this.color);
            p.ellipse(this.x, this.y, this.size);
        }

        isDead() {
            return this.life <= 0 || this.x < 0 || this.x > 400 || this.y < 0 || this.y > 300;
        }
    }

    p.setup = function() {
        p.createCanvas(400, 300);
        p.colorMode(p.RGB);

        // Create initial influences at fixed positions
        influences.push(new Influence(100, 150, 0.2));
        influences.push(new Influence(300, 150, 0.5));
        influences.push(new Influence(200, 80, 0.8));
    };

    p.draw = function() {
        const colors = getThemeColors();
        p.background(...colors.bg, 25); // Slight trail effect

        // Display influences (constant sources)
        for (let inf of influences) {
            inf.display(colors);
        }

        // Generate synthesis particles periodically
        time++;
        if (time % 15 === 0) {
            synthesis.push(new SynthesisParticle(influences, colors));
        }

        // Update and display synthesis
        for (let i = synthesis.length - 1; i >= 0; i--) {
            synthesis[i].update();
            synthesis[i].display();

            if (synthesis[i].isDead()) {
                synthesis.splice(i, 1);
            }
        }

        // Draw subtle lines showing influence connections
        p.stroke(...colors.accent3, 30);
        p.strokeWeight(1);
        for (let i = 0; i < influences.length; i++) {
            for (let j = i + 1; j < influences.length; j++) {
                p.line(influences[i].x, influences[i].y, influences[j].x, influences[j].y);
            }
        }
    };
};