Where ideas percolate and thoughts brew

The Action Bias

About This Sketch

When someone is "acting" on it, add random interference

This sketch accompanies the blog post "The Action Bias" and visualizes its core concepts through generative art.

Algorithm

When someone is "acting" on it, add random interference This sketch was originally created as a visual companion to the blog post "The Action Bias" 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) {

    let pendulums = [];

    class Pendulum {
        constructor(x, angle, length, active) {
            this.x = x;
            this.angle = angle;
            this.angleVel = 0;
            this.angleAcc = 0;
            this.length = length;
            this.active = active; // whether someone is "acting" on it
            this.damping = active ? 0.995 : 0.998; // active = more interference = more damping
            this.gravity = 0.2;
        }

        update() {
            if (this.active) {
                // When someone is "acting" on it, add random interference
                this.angleAcc = -this.gravity * p.sin(this.angle) / this.length;
                this.angleAcc += p.random(-0.002, 0.002); // random interference from action
            } else {
                // When left alone, natural motion
                this.angleAcc = -this.gravity * p.sin(this.angle) / this.length;
            }

            this.angleVel += this.angleAcc;
            this.angleVel *= this.damping;
            this.angle += this.angleVel;
        }

        display(colors) {
            let posX = this.x + this.length * p.sin(this.angle);
            let posY = 100 + this.length * p.cos(this.angle);

            // Line
            p.stroke(...(this.active ? colors.accent2 : colors.accent1), 150);
            p.strokeWeight(2);
            p.line(this.x, 100, posX, posY);

            // Pivot point
            p.noStroke();
            p.fill(...colors.accent3, 200);
            p.ellipse(this.x, 100, 6, 6);

            // Bob
            p.fill(...(this.active ? colors.accent2 : colors.accent1), 220);
            p.ellipse(posX, posY, 12, 12);
        }

        // How close to equilibrium (rest state)
        equilibrium() {
            return p.abs(this.angle) + p.abs(this.angleVel);
        }
    }

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

        // Create pendulums - some "acted upon" (active), some left alone (inactive)
        // The ones left alone will settle to equilibrium faster
        pendulums.push(new Pendulum(100, 0.8, 80, true));  // acted upon
        pendulums.push(new Pendulum(200, 0.8, 80, false)); // left alone
        pendulums.push(new Pendulum(300, 0.8, 80, true));  // acted upon
    };

    p.draw = function() {
        const colors = getThemeColors();
        p.background(...colors.bg);

        // Labels
        p.textAlign(p.CENTER, p.TOP);
        p.textSize(10);
        p.fill(...colors.accent3, 200);
        p.noStroke();
        p.text("Action", 100, 15);
        p.text("Waiting", 200, 15);
        p.text("Action", 300, 15);

        // Instructions
        p.textAlign(p.CENTER, p.BOTTOM);
        p.textSize(9);
        p.fill(...colors.accent3, 150);
        p.text("The middle pendulum (left alone) settles fastest", 200, 290);

        // Update and display all pendulums
        for (let pendulum of pendulums) {
            pendulum.update();
            pendulum.display(colors);
        }

        // Show equilibrium levels
        p.textAlign(p.CENTER, p.TOP);
        p.textSize(8);
        for (let i = 0; i < pendulums.length; i++) {
            let eq = pendulums[i].equilibrium();
            let percentage = p.constrain(100 - eq * 100, 0, 100);
            p.fill(...colors.accent3, 150);
            p.text(p.floor(percentage) + "% settled", pendulums[i].x, 240);
        }
    };
};