diff --git a/render.js b/render.js index 42f2dca..bd36cb8 100644 --- a/render.js +++ b/render.js @@ -161,6 +161,24 @@ export function proj(x, y, z) { return { x: W / 2 + x * s, y: TUNE.horizon + (TUNE.camY + aimCam * TUNE.aimCamY - y) * s, s }; } +// The run-off apron below the near baseline. Raising the court to make room for the pull (see +// fitViewport) left a wide band down there, and `pal.out` is a single flat colour — so the +// perspective visibly stopped partway down the screen and the rest read as dead margin. This falls +// the light off toward you, which gives the band depth, frames the rack, and darkens exactly the +// area the thumb covers anyway. Starts at alpha 0 on the baseline, so there is no seam to see. +// NOT a near backstop: at camZ 48 with the baseline at z 23.77 a real one would sit between the +// camera and the player and draw enormous. You are looking OVER it, which is why a broadcast frame +// never shows one either. Wear and props at the margins are the next layer, not this. +function drawRunOff() { + const top = proj(0, 0, COURT.L).y; + if (top >= H) return; // landscape has no apron at all — the baseline projects off the bottom + const g = ctx.createLinearGradient(0, top, 0, H); + g.addColorStop(0, 'rgba(6,10,6,0)'); + g.addColorStop(1, 'rgba(6,10,6,0.72)'); + ctx.fillStyle = g; + ctx.fillRect(0, top, W, H - top); +} + // ---------------------------------------------------------------- sprites ---- // assets/.png; game falls back to code-drawn figures until sprites load. const SPRV = 78; // asset cache-buster — bump with main.js?v=N (see the img.src note below) @@ -831,6 +849,7 @@ export function render() { line(-COURT.W / 2, COURT.svcNear, COURT.W / 2, COURT.svcNear, 1); line(0, COURT.svcFar, 0, COURT.svcNear, 1); line(0, 0, 0, 0.35, 1); line(0, COURT.L - 0.35, 0, COURT.L, 1); // center marks + drawRunOff(); // light falls off across the apron below the baseline // gore decals: what remains of the visiting team (flat ground layer, then far-side mounds) for (const d of gore) {