Eye 10 adds mouse-follow mode: both pupils continuously rotate to face the cursor, driven by draw() at 30 fps. Toggle Follow on, move your mouse over the canvas — the eyes track it. Then turn Track off and watch the “wonky” vergence effect emerge from two objects doing simple geometry independently.
Big Idea 1 — draw() as the Driver
In earlier stages, pupils moved because of events (mouse pressed, mouse dragged).
Here they move because of the animation loop: every frame, draw() calls lookAt(mouseX, mouseY, grid) on each eye.
This is a different programming model — reactive (event-driven) vs. continuous (frame-driven) — and students encounter both in real applications.
Big Idea 2 — lookAt() vs. setPupilOffset()
setPupilOffset(radius, angleDeg) is imperative: you place the pupil.
lookAt(x, y, grid) is declarative: the eye computes where to look.
Internally, lookAt() converts screen coordinates to user space, computes
the angle from the eye center to the target, and calls setPupilOffset().
Two different methods; one internal implementation.
Big Idea 3 — Emergent Vergence
With Track OFF, each eye computes its own angle to the mouse from its own center position.
Because the two eyes are horizontally separated, their angles to a nearby point differ slightly —
producing a natural vergence gap that makes the face look subtly cross-eyed or wall-eyed depending on mouse position.
Nobody programmed the “wonky” effect. It emerged from two independent objects doing honest geometry.
This is a memorable demonstration of emergent behavior.
Big Idea 4 — Priority Chains Inside the Class
Follow mode and drag mode coexist because the class manages priority internally:
an active drag is never overridden by the follow loop.
handleMouseDragged() sets an _isDragging flag;
draw()’s follow logic checks it and skips that eye while dragging.
The sketch doesn’t arbitrate — it just calls both features every frame and lets the class sort it out.