Where ideas percolate and thoughts brew

Outcome Focus vs. Process Focus

About This Sketch

Visualizing Sian Beilock's choking research and John Nicholls' ego/task involvement distinction. Left: particles pulled toward a shared outcome target become increasingly erratic the closer they get — anxiety scales with proximity to the prize. Right: particles following their own individual process trajectories move with consistent composure, unaffected by how near they are to completion.

Algorithm

Two panels contrast how caring about outcomes versus caring about execution affects performance under pressure. Left panel — outcome focus: particles share a single pulsing target. Their noise (jitter) scales inversely with distance: the closer they get to the goal, the more erratic their movement. Proximity breeds anxiety. They overshoot and oscillate. Right panel — process focus: each particle has its own stable attractor. Noise is minimal and uniform regardless of proximity. Particles approach their individual targets with consistent, composed trajectories.

Pseudocode

SETUP:
  Initialize outcome particles at random positions (left half)
  Initialize process particles at random positions (right half)
  Each process particle gets a unique fixed attractor (right half)

DRAW:
  Draw dividing line

  LEFT (outcome focus):
    Pulse shared target (importance signal)
    For each particle:
      Compute attraction force toward shared target
      Compute anxiety = map(distance, 0→120, HIGH→LOW)
      Add noise * anxiety to velocity (choke near goal)
      Update position, constrain to left half

  RIGHT (process focus):
    For each particle:
      Draw faint attractor ring at individual target
      Compute attraction force toward own target
      Add minimal uniform noise (natural variance only)
      Update position, constrain to right half

  Draw labels

Source Code

let sketch = function(p) {
    const W = 400, H = 300;
    const MID = W / 2;

    let oParticles = [];
    const O_COUNT = 16;
    const O_TARGET = { x: MID * 0.5, y: H * 0.5 };

    let pParticles = [];
    const P_COUNT = 14;

    function initOutcome() {
        oParticles = [];
        for (let i = 0; i < O_COUNT; i++) {
            oParticles.push({
                x: p.random(14, MID - 14),
                y: p.random(20, H - 20),
                vx: p.random(-0.4, 0.4),
                vy: p.random(-0.4, 0.4),
                size: p.random(3.5, 5.5)
            });
        }
    }

    function initProcess() {
        pParticles = [];
        for (let i = 0; i < P_COUNT; i++) {
            pParticles.push({
                x: p.random(MID + 14, W - 14),
                y: p.random(20, H - 20),
                vx: p.random(-0.3, 0.3),
                vy: p.random(-0.3, 0.3),
                tx: p.random(MID + 30, W - 30),
                ty: p.random(30, H - 30),
                size: p.random(3.5, 5.5)
            });
        }
    }

    p.setup = function() {
        p.createCanvas(W, H);
        p.colorMode(p.RGB);
        initOutcome();
        initProcess();
    };

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

        let t = p.frameCount * 0.015;

        p.stroke(colors.accent3[0], colors.accent3[1], colors.accent3[2], 40);
        p.strokeWeight(1);
        p.line(MID, 16, MID, H - 16);

        let pulse = 0.5 + 0.5 * Math.sin(t * 3.0);
        for (let r = 28; r > 4; r -= 6) {
            p.noStroke();
            p.fill(colors.accent2[0], colors.accent2[1], colors.accent2[2],
                   p.map(r, 4, 28, 0, 16 + pulse * 12));
            p.ellipse(O_TARGET.x, O_TARGET.y, r * 2, r * 2);
        }
        p.fill(...colors.accent2, 200 + pulse * 55);
        p.noStroke();
        p.ellipse(O_TARGET.x, O_TARGET.y, 6 + pulse * 2.5, 6 + pulse * 2.5);

        for (let op of oParticles) {
            let dx = O_TARGET.x - op.x;
            let dy = O_TARGET.y - op.y;
            let dist = Math.sqrt(dx * dx + dy * dy);
            let force = 0.15 / Math.max(dist, 10);
            op.vx += dx * force;
            op.vy += dy * force;
            let anxietyScale = p.map(dist, 0, 120, 0.6, 0.02, true);
            op.vx += (p.noise(op.x * 0.04, op.y * 0.04, t * 0.5) - 0.5) * anxietyScale * 2.2;
            op.vy += (p.noise(op.x * 0.04 + 70, op.y * 0.04, t * 0.5) - 0.5) * anxietyScale * 2.2;
            op.vx *= 0.87;
            op.vy *= 0.87;
            op.x += op.vx;
            op.y += op.vy;
            op.x = p.constrain(op.x, 10, MID - 10);
            op.y = p.constrain(op.y, 14, H - 14);
            p.fill(colors.accent2[0], colors.accent2[1], colors.accent2[2], 155);
            p.noStroke();
            p.ellipse(op.x, op.y, op.size, op.size);
        }

        p.noStroke();
        p.fill(colors.accent3[0], colors.accent3[1], colors.accent3[2], 95);
        p.textAlign(p.CENTER);
        p.textSize(8.5);
        p.text("outcome focus", MID / 2, H - 10);

        for (let pp of pParticles) {
            p.noFill();
            p.stroke(colors.accent1[0], colors.accent1[1], colors.accent1[2], 28);
            p.strokeWeight(1);
            p.ellipse(pp.tx, pp.ty, 18, 18);
            p.fill(...colors.accent1, 100);
            p.noStroke();
            p.ellipse(pp.tx, pp.ty, 4.5, 4.5);

            let dx = pp.tx - pp.x;
            let dy = pp.ty - pp.y;
            let dist = Math.sqrt(dx * dx + dy * dy);
            let force = 0.11 / Math.max(dist, 10);
            pp.vx += dx * force;
            pp.vy += dy * force;
            pp.vx += (p.noise(pp.x * 0.025, pp.y * 0.025, t * 0.3) - 0.5) * 0.06;
            pp.vy += (p.noise(pp.x * 0.025 + 80, pp.y * 0.025, t * 0.3) - 0.5) * 0.06;
            pp.vx *= 0.91;
            pp.vy *= 0.91;
            pp.x += pp.vx;
            pp.y += pp.vy;
            pp.x = p.constrain(pp.x, MID + 10, W - 10);
            pp.y = p.constrain(pp.y, 14, H - 14);
            p.fill(colors.accent1[0], colors.accent1[1], colors.accent1[2], 185);
            p.noStroke();
            p.ellipse(pp.x, pp.y, pp.size, pp.size);
        }

        p.noStroke();
        p.fill(colors.accent3[0], colors.accent3[1], colors.accent3[2], 95);
        p.textAlign(p.CENTER);
        p.textSize(8.5);
        p.text("process focus", MID + (W - MID) / 2, H - 10);
    };
};