The Punchline

Artificial Noodles ·

Inspired by Comedic timing on Wikipedia

Built with Pure Canvas 2D · Playfair Display 900 · Space Mono · Per-keystroke rhythm tracking · Character-particle shatter system

Techniques Binary-search font fitting · Per-word entrance animation by timing quality · Character-by-character explosion with gravity + rotation · Phase state machine (intro → setup → beat → punch → shatter → silence → reveal) · Forced-silence detection

Direction Typing IS comedic timing. Your rhythm of keypresses determines whether the punchline lands. The third joke proves the point: it has no punchline because the silence is the punchline.

Result A bold serif word fills the screen with each keypress. Press at the right tempo and the punchline shatters in a confetti of letterforms; rush it and the joke dies on stage. Then the third joke, which teaches you that you’ve been competing the wrong way

The Story

Comedic timing is the part of stand-up that can’t be taught. You can write a great joke and still kill it with a bad delivery. The setup-pause-punchline structure is the most studied form in comedy: every element is calibrated in fractions of a second. Rush the setup and the audience hasn’t tracked the reversal yet. Drag the pause and the room cools down. The punchline itself has to land on a precise beat — too early, no one’s ready; too late, the moment is gone.

Stand-up comedians like Mitch Hedberg, Steven Wright, and Norm Macdonald built entire careers on timing rather than content. The jokes themselves were often almost mundane; what made them work was the gap. Norm Macdonald famously held setups for what felt like an unbearable amount of time before the punchline. The audience would start to think the joke had failed — and then he’d land it, and the relief was the laugh.

The third joke in this experience is a meta-joke about that exact structure. “The secret to comedy is…” — and then nothing. To get the punchline, you have to stop pressing keys. The silence is the timing, and the timing is the punchline.


The Take

You arrive at a black screen. The Punchline. A comedy of timing. Press any key to begin. You press a key. The letter “I” appears, three feet tall in a serif you’d see on a New Yorker cover. You press again. told. Again. my. The words are coming one per keystroke, each one filling most of the viewport, each one disappearing to make room for the next.

Within four or five words, you start to feel a tempo. Press at the wrong rate and the words come in compressed and dim, a little jittery — the joke is being rushed. Press at the right rate and the words slam in crisp, full-bright, with a faint elastic snap. There’s no metronome telling you the beat. The visual quality of each word is the only feedback. You calibrate by ear, like a musician.

After the eleventh word — high. — there’s a forced beat. A blinking caret in the middle of the screen. The prompt below changes from space to deliver it. You press, and the punchline lands: She looked surprised. — at full size, full bright, and then it explodes. Each letter becomes a particle, flying outward with rotation and gravity, accompanied by a brief warm flash. Perfect delivery. says the next screen.

The second joke is faster. I have a fear of speed bumps. Then the punchline. I’m slowly getting over it. Same shatter, same flash. Not bad. You’re getting confident.

The third joke begins. The secret to comedy is. Then nothing. The “is” lingers, fading slowly. The screen darkens around the edges. You wait. If you press a key, the screen flashes a small red wait. and the silence timer resets. After about four seconds of held silence, a single word materializes on its own: timing. — slowly fading in, growing from small to large. There is no shatter. The silence was the shatter.


The Tech

Pure Canvas 2D, no frameworks

The entire experience is one <canvas> element with a 2D context. No Three.js, no WebGL, no DOM elements except the canvas. The aesthetic is two fonts loaded from Google Fonts (Playfair Display 900 for the words, Space Mono for everything else) and one color palette: black background, warm parchment-white text, comedy-club red for the set counter.

Phase state machine

The experience is a pure state machine with nine phases:

intro → setup → beat → punch → shatter ─┐

              between ←─────────────────┘

              setup → ... → silence → reveal → end

Each phase has its own renderer; transitions happen on input or on timer. The whole thing is ~450 lines of JavaScript. There is no physics solver, no shader, no agent simulation — the only “simulation” is the per-character particle system that runs for ~2 seconds during a punchline shatter.

Timing quality scoring

Each keypress in the setup phase records the gap since the previous press in milliseconds. The gap is compared to the joke’s idealGap (420ms for joke 1, 380ms for joke 2, 480ms for joke 3) and an error is computed:

const error = Math.abs(gap - idealGap) / idealGap;
const wordQuality = Math.max(0, Math.min(1, 1 - error * 2.0));

A perfect press scores 1.0, a press at 50% off scores 0.0. Each setup word stores its quality. When the setup ends, the average quality is computed — that’s avgQuality, which determines the punchline delivery.

Per-word entrance animation by quality

Each new word has a 200ms entrance animation. The animation parameters depend on the press’s quality:

This visual feedback teaches the rhythm without an explicit metronome. Within three or four words, anyone can find the beat.

Punchline shatter

The punchline appears as a single text string. If avgQuality > 0.45, after a 380ms hold, the text shatters into individual character particles:

for each character:
  cx = current x position + width/2
  angleBase = atan2(random() * H - H/3, cx - W/2)   // radial outward, biased upward
  angle = angleBase + (random() - 0.5) * 0.7
  speed = 280 + random() * 540
  velocity = (cos(angle) * speed + dxBias, -180 + sin(angle) * speed)

Each particle has position, velocity, rotation, rotational velocity, alpha, and remembers its character glyph and font size. Each frame: gravity (580 px/s²) accelerates downward; position integrates by velocity; rotation integrates by rotational velocity; alpha decays at 0.55/s. Particles that leave the screen or fade below visibility are skipped.

When all particles are dead, the phase transitions to between. A simple count-alive loop drives the transition — no explicit timer needed.

Binary-search font fitting

Each word renders at a font size calibrated to fill ~75% of viewport width. The font size is found by binary search:

function fitText(text, maxWidth) {
  let lo = 14, hi = min(440, H * 0.6);
  while (hi - lo > 1) {
    const mid = (lo + hi) >> 1;
    ctx.font = `900 ${mid}px 'Playfair Display', serif`;
    if (ctx.measureText(text).width > maxWidth) hi = mid;
    else lo = mid;
  }
  return lo;
}

Results are cached in a Map keyed by text|width. This means the word “I” renders at the maximum allowed size (huge, dramatic) while “eyebrows” renders at maybe 80px — the natural rhythm of word lengths becomes its own visual music.

The silence mechanic

The third joke’s punchline is the absence of one. After the user types through The secret to comedy is, the phase transitions to silence and a counter starts incrementing. If the user presses any key during silence, the counter is decremented by 1.5s and a red wait. hint flashes briefly. After 4 seconds of accumulated true silence, the phase transitions to reveal, and the word timing. materializes on its own with no shatter, no flash — just a slow fade-in. The third joke teaches you that you’ve been doing it wrong: the timing was never about how often you press. It was about knowing when to stop.

Subliminal background pulse

When a word lands with quality > 0.6, a very subtle radial gradient (warm-white at 10% opacity) pulses outward from center, decaying over ~0.4 seconds. It’s barely perceptible — but it gives the room a “responding” quality that reinforces the good-timing reward. The room is laughing, quietly, in the background.


Experience: The Punchline


This blog post was AI generated with Claude Code. Authored by Artificial Noodles.