👻 ⭐ Twinkling Stars:
Three Languages, One Sketch
The same Processing sketch — identical logic, identical vocabulary — in JavaScript (p5.js), Java Processing, and Python Processing. Five big ideas that make it work in all three.
Five Concepts at Work in Every Version
These five design decisions appear in all three sketches. Find each one in the code panels below — the pattern is identical; only the language syntax differs.
A magic number is a raw value embedded in code with no label —
createCanvas(400, 400) tells you nothing about why 400 was chosen.
A named constant fixes that: var CW = 400; createCanvas(CW, CH) makes the
intent explicit and makes changing the value a one-line edit.
Every configurable value in the sketch gets a name:
NUM_STARS, TWINKLE_PERIOD, SKY_H,
STAR_HUE. Each language enforces this differently:
colorMode(HSB, 360, 100, 100, 100) tells Processing to interpret every
stroke(), fill(), and background() call as
Hue (0–360), Saturation (0–100),
Brightness (0–100), Alpha (0–100).
The sky: H=277 (purple on the wheel), S=85 (vivid),
B=52 (dark). Stars share H=60 (yellow) but get
random saturation, so some are warm-white and others vivid gold.
After colorMode() is called, the new interpretation
applies globally for the rest of the sketch — in all three languages.
100 stars, each with 7 properties:
x, y, sw, h,
s, b, offset.
The data model is identical. The container syntax is not:
Java is the only version that requires a formal class definition
for Star. Python and JavaScript leave structure optional.
That difference is itself a lesson in what each language values.
mousePressed() is a Processing lifecycle function:
it is called automatically once each time the user clicks the canvas.
You never call it yourself — Processing does, behind the scenes.
mouseX and mouseY are Processing globals that
update every frame to reflect the cursor position.
The guard clause —
if (mouseX >= 0 && mouseX <= CW …) —
restricts the response to clicks that land inside the canvas boundary,
ignoring any click on the browser chrome. The toggle itself is one line:
Each star’s alpha (opacity) oscillates using a sine wave:
alpha = A · sin(B · (frameCount + offset)) + C
A = 35 (half the swing: (100−30)/2),
C = 65 (center: (100+30)/2),
B ≈ 0.0698 (TWO_PI / 90).
The key is the per-star phase offset (0–89 frames):
adding a unique offset to frameCount before evaluating the sine
places each star at a different point in the cycle.
Without it, all 100 stars would dim and brighten simultaneously.
With it, they sparkle independently — even though every star
uses the exact same formula.
All Three Sketches, Side by Side
Yellow paper = JavaScript • Blue paper = Java • Green paper = Python. Each panel scrolls independently.
What’s the Same — and What’s Different
Scroll through all three panels and look for the same variable names, the same
arithmetic, the same function names. The Processing vocabulary —
background(),
stroke(),
colorMode(),
sin(),
TWO_PI,
frameCount,
mousePressed()
— is the same in all three. What changes is only the host language’s syntax:
how you declare a variable, how you access a field, and whether the language enforces
a formal class definition. The algorithm is language-independent.
- JS:
star.offset| Java:star.offset| Python:star['offset'] - JS:
createCanvas(CW, CH)| Java / Python:size(CW, CH)— but Java requires a literal, not a variable - Java only: requires a
class Stardefinition — JS and Python use plain objects/dicts - JS/Java:
!shouldTwinkle| Python:not should_twinkle