Henry’s Ghost  •  Ghost Wrangler in p5.js  •  09/27/2026
TNT — Creative Coding & Cross Training

👻 ✨ Henry’s Ghost Saga:
Ghost Wrangler in p5.js

Click ghosts to select them, move them with WASD, add new ghosts by clicking empty space, and watch them float over a twinkling star-field background.
A Python Processing sketch by Henry — ported to JavaScript p5.js for cross-training.

👻  Student Work — Henry’s Original Design

The Sketch

Henry built this ghost-wrangler app in Python Processing. It features custom-shaped ghost bodies drawn with beginShape()/ endShape(CLOSE), sinusoidal floating animation, eyes that follow the mouse cursor, random blinking, a wavy hem on the ghost’s bottom, and a gradient night-sky background filled with 80 twinkling stars.

Clicking a ghost selects it (shown by a pulsing blue selection ring). The selected ghost can then be moved with W A S D. Clicking empty space spawns a new ghost. Press C to clear extra ghosts, R to remove the last one, Space to make all ghosts blink, and +/− to change movement speed.

p5.js techniques at work: beginShape() / endShape(CLOSE) for custom ghost silhouette • push() / pop() replaces both pushMatrix() and pushStyle() • lerpColor() for the gradient sky • atan2() + polar offset for mouse-tracking pupils • sin() for floating, twinkling, waving, and pulsing selection ring • object literals ({ x, y, size, … }) replace Python dicts

    Live sketch requires a larger screen.
    Try rotating to landscape.

    Live Sketch — Ghost Wrangler

    Click a ghost to select it • WASD to move • click empty space to add • Space to blink all

    Cross-Training Note — Python vs JavaScript

    Henry’s original Python Processing sketch and this p5.js port are functionally identical. The translation reveals the cleanest Python-to-JavaScript mapping in the Processing ecosystem: nearly every function call stays the same; only the data-access syntax and a handful of idioms change.

    • Data: Python ghost['x'] dict access → JS ghost.x object dot notation
    • Canvas init: Python size(800, 600) → JS createCanvas(CW, CH).parent('ghostCanvas')
    • Push/pop: Python needs separate pushMatrix() and pushStyle() → JS push() handles both transforms and styles
    • List ops: Python ghosts.append(g) → JS ghosts.push(g) • Python ghosts[:] = [first] → JS ghosts.length = 0; ghosts.push(first);
    • Naming: Python should_twinkle, float_offset → JS shouldTwinkle, floatOffset (camelCase)
    • Identical in both: beginShape() / endShape(CLOSE) • vertex() • arc() • lerpColor() • atan2() • sin() / cos() • constrain() • dist() • millis() • mouseX / mouseY

    Download Python source  •  Development chat log  •  Cross Training (JS / Java / Python)  •  Creative Cross Training home