PURPOSE

World-space renderer for a single artifact pickup, drawn as a green-blue swirling glass orb with a soft glow, an upward column of light, rotating swirl arcs, a specular highlight, and a pulsing outer ring. Called once per artifact box during the entity render pass.

OWNS

  • drawArtifactOrb(ctx, sz, time, phase, collecting) — the sole exported draw function.
  • The full visual treatment of an artifact pickup: glow radial gradient, vertical light beam (outer green + inner blue-white), base orb radial gradient (#aaffee → #44ddbb → #2288aa → #114466), rotating swirl arcs, specular highlight dot, and pulsing teal outer ring stroke.
  • Local animation derivations from time and phase: glow pulse, beam pulse, swirl angle and arc length, ring alpha.

READS FROM

  • ctx: CanvasRenderingContext2D — already translated by the caller to the orb’s screen position.
  • sz: number — base radius in screen pixels (camera zoom already applied by caller). Orb radius is derived as sz * 1.1.
  • time: numbergame.time, drives all sinusoidal pulse and rotation terms.
  • phase: number — per-pickup bob phase offset, used to desync animations between concurrent orbs.
  • collecting: boolean — when true, the glow and column of light are skipped (used during the fly-to-center collect animation).

PUSHES TO

  • The provided CanvasRenderingContext2D. The function mutates fillStyle, strokeStyle, lineWidth, globalAlpha, and issues beginPath / arc / fillRect / fill / stroke calls.
  • Restores ctx.globalAlpha = 1 before returning. Does not call ctx.save / ctx.restore; relies on the caller for that.

DOES NOT

  • Does not translate, rotate, or scale the context. The caller positions, bobs, and scales the orb.
  • Does not read game state, world, camera, or any module-level data.
  • Does not handle input, collision, collection logic, or the fly-to-center motion — collecting is a render-only flag.
  • Does not draw the artifact icon, label, or rarity affordances; only the orb itself.
  • Does not allocate persistent textures or use the sprite batch; gradients are recreated per call.

Signals

None. Pure rendering function with no event emission or subscription.

Entry points

  • drawArtifactOrb is imported by src/starship-survivors/engine/bridge.ts and called inside the artifact-box render loop, after the caller has saved the context, translated to screen position plus bob offset, and applied _collectScale. collecting is passed as !!aa._collecting, phase as ab.bobPhase || 0, time as game.time.

Pattern notes

  • Procedural Canvas2D rendering — no sprites, atlases, or shaders. Every layer is a fresh gradient or arc per frame.
  • Layer order is back-to-front: glow → beam (outer then inner) → base orb → swirl arcs → specular highlight → outer ring stroke.
  • All animation is derived from time and phase via Math.sin, with distinct frequencies (2.5, 2.1, 1.8, 1.2, 3.0) so layers desync visually.
  • The collecting short-circuit skips the glow and beam so the orb reads cleanly during the collect tween; the base orb, swirls, highlight, and ring still draw.
  • Swirl arcs use a fixed count of three, alternating teal and blue-cyan strokes at increasing radii (0.5 + i * 0.15 of orbR).
  • Visual style is intentionally matched to the weapon chest beam (per file comment) so artifact and weapon pickups feel like a family.
  • Caller-owned concerns: world-to-screen projection, bob offset, collect scale, and ctx.save/ctx.restore bracketing.