Ch1 — mirror reflection: canonical ghost, slower resolve, two blinks
Julia: "the reflection in the mirror is off. Pip's human face looks good, but the ghost
reflection is too quick and he should blink twice in the reflection and match the look of Pip
as a ghost."
Match — by construction, not by eye
The reflection was a hand-rolled lookalike: it re-drew the arc/wave body inline and drew
its own eyes, blush and mouth. It had drifted from the real Pip in concrete ways —
shadowBlur 4 against the canonical 12, no cool underglow, no idle bob, and a different blink
rule.
It now calls the shared art-source drawPip() — the same function the gallery and
gameplay use — so the ghost in the glass cannot drift from Pip again.
drawPip() gains a back-compatible options bag { blink, floorGlow }:
blink lets a caller drive the eyes instead of the built-in 4-second cycle;
floorGlow: false suppresses the floor glow, since there is no floor inside a mirror.
Both existing call sites are unaffected (the parameter is optional).
Too quick
|
before |
after |
| melt duration |
2.2s |
3.2s |
| ghost fade-in window |
meltT 0.15 → 0.60 |
0.35 → 0.85 |
| ghost fully opaque at |
~3.12s |
4.55s |
The ghost used to race the melt — it was solid before the human face had finished dissolving.
It now arrives as the face finishes.
Two blinks
One 250ms blink becomes two 140ms blinks, on cue at 5.80s and 6.55s, with 0.61s of
open eyes between them.
Verified
Timing simulated (2 distinct blinks, correct ordering) and geometry checked — the ghost is
138px inside a 174px glass, head top 17 / foot 155, fits with margin. Conformance unchanged at
110 comparisons, 0 divergences. node --check PARSE OK.
Feel is Julia's in-browser call.
Ch1 — mirror reflection: canonical ghost, slower resolve, two blinks
Julia: "the reflection in the mirror is off. Pip's human face looks good, but the ghost
reflection is too quick and he should blink twice in the reflection and match the look of Pip
as a ghost."
Match — by construction, not by eye
The reflection was a hand-rolled lookalike: it re-drew the arc/wave body inline and drew
its own eyes, blush and mouth. It had drifted from the real Pip in concrete ways —
shadowBlur4 against the canonical 12, no cool underglow, no idle bob, and a different blinkrule.
It now calls the shared art-source
drawPip()— the same function the gallery andgameplay use — so the ghost in the glass cannot drift from Pip again.
drawPip()gains a back-compatible options bag{ blink, floorGlow }:blinklets a caller drive the eyes instead of the built-in 4-second cycle;floorGlow: falsesuppresses the floor glow, since there is no floor inside a mirror.Both existing call sites are unaffected (the parameter is optional).
Too quick
The ghost used to race the melt — it was solid before the human face had finished dissolving.
It now arrives as the face finishes.
Two blinks
One 250ms blink becomes two 140ms blinks, on cue at 5.80s and 6.55s, with 0.61s of
open eyes between them.
Verified
Timing simulated (2 distinct blinks, correct ordering) and geometry checked — the ghost is
138px inside a 174px glass, head top 17 / foot 155, fits with margin. Conformance unchanged at
110 comparisons, 0 divergences.
node --checkPARSE OK.Feel is Julia's in-browser call.