PURPOSE
Renders a single ShootingStar entity to the 2D canvas: a rainbow-hued tail, a pulsing 5-pointed golden star, an intense radial outer glow, and a spinning golden collection ring with cardinal/diagonal tick marks. Includes a separate “collected” mode that flies the star toward screen center with growing scale and brighter glow.
OWNS
SCALEconstant — visual scale multiplier (1.0, 1:1 with archive original).RAINBOW_HUESpalette — seven RGB triplets cycled along the tail (red, orange, yellow, green, blue, indigo, violet).FLY_DURATIONconstant — 0.6s, mirrorsSTAR_FLY_DURATIONinshooting-star.ts._safeRadialGradienthelper — wrapsctx.createRadialGradientclamping inner radius to ≥0.01 and outer radius to ≥0.1._starPathhelper — traces a 10-vertex (5-pointed) star polygon into the current 2D path centered at (0,0), alternating outer/inner radii.drawShootingStarexported function — the renderer entry point.- The full visual composition: tail strokes, white-hot core trail, outer glow gradient, three-layer star fill (white /
#ffcc33/#ff8800), outer/inner golden rings, eight tick marks.
READS FROM
ShootingStartype from../world/shooting-star.Camera.toS(x, y)from./camera— converts world coordinates to screen coordinates for the star center and every trail sample.W,Hfrom../core/state— screen dimensions used to compute the flight target (W/2,H/2) in collected mode.- Star fields read:
_collected,_collectTime,_collectScreenX,_collectScreenY,x,y,trail(array of{x, y}samples),spin. - Caller-supplied:
ctx(2D context),zoom,time(world clock for pulse/ring oscillation),idx(per-star phase offset),uiTime(optional, drives collected-mode interpolation).
PUSHES TO
- The supplied
CanvasRenderingContext2D— mutatesglobalAlpha,fillStyle,strokeStyle,lineWidth,lineCap, and the transform stack viasave/translate/rotate/scale/restore. - Resets
ctx.globalAlpha = 1before returning from both the collected branch and the live branch.
DOES NOT
- Does not mutate the
ShootingStaritself (no writes to position, spin, trail, or collection flags). - Does not iterate the global star list — caller drives the per-star loop and supplies
idx. - Does not handle input, collision, scoring, or trail growth.
- Does not load assets, fonts, or sprite atlases — purely procedural canvas drawing.
- Does not check whether the star is on-screen; relies on caller-side culling if any.
- Does not despawn or finalize the collection animation; just renders the current frame based on
uiTime - _collectTime.
Signals
- None emitted. Pure draw function with no event dispatch, no telemetry, no logging.
Entry points
drawShootingStar(ctx, star, zoom, time, idx, uiTime?)— the only exported symbol. Called per-frame per-star by the rendering pipeline.
Pattern notes
- Two-branch structure: if
star._collected && uiTime != null, runs the fly-to-center animation (ease-out quad ont = elapsed / FLY_DURATION, scale 1.0 → 1.5, amplified glow, simplified two-layer star) and early-returns; otherwise renders the full world-space presentation. - Trail rendering walks
trailonce for the rainbow strokes (hue index(ti * 0.8) % 7, alpha and width grow withfrac = ti / tLen) and a second time for the last 12 samples as a white-hot polyline core. - Pulse animation:
1 + sin(time * 8 + idx * 2) * 0.15scales the star body each frame; ring alphas oscillate at independent frequencies (sin(time * 4 + idx)andsin(time * 6 + idx * 3)). - Ring rotation is derived as
(star.spin || 0) * 1.5, so it counter-spins relative to the star body. - All radii are multiplied by
SCALE * zoomso the visual is consistent under camera zoom;SCALEis held at 1.0 but kept as a knob. - Underscored helpers (
_safeRadialGradient,_starPath) are module-private by convention, not exported. - Comments reference the archive source (
archive/html-source/08b-render-gameplay.jslines 2369-2516) the renderer is ported from, with the note that the port is 2× larger with enhanced glow.