👻 ✨ 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.
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.
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 → JSghost.xobject dot notation - Canvas init:
Python
size(800, 600)→ JScreateCanvas(CW, CH).parent('ghostCanvas') - Push/pop:
Python needs separate
pushMatrix()andpushStyle()→ JSpush()handles both transforms and styles - List ops:
Python
ghosts.append(g)→ JSghosts.push(g)• Pythonghosts[:] = [first]→ JSghosts.length = 0; ghosts.push(first); - Naming:
Python
should_twinkle,float_offset→ JSshouldTwinkle,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