diff --git a/packages/web/src/fpv/FirstPerson.svelte b/packages/web/src/fpv/FirstPerson.svelte index af01bd5..bab150f 100644 --- a/packages/web/src/fpv/FirstPerson.svelte +++ b/packages/web/src/fpv/FirstPerson.svelte @@ -363,6 +363,10 @@ if (s) sprites.push({ ...s, alpha: f.kind === "impact" ? 1 - p : 1, fallback: f.art }); } sprites.sort((a, b) => b.sort - a.sort); + // The nearest sprite each column carries: the overlay passes (veils, + // ghosts, lintels, risings) must not paint over a body standing in + // front of them. + const spriteZ = new Float64Array(W).fill(Infinity); for (const s of sprites) { const img = imageFor(s.src) ?? (s.fallback @@ -381,6 +385,7 @@ if (warpIdCol[col] !== s.warpId || s.depth <= warpDistCol[col]!) continue; } else if (s.depth >= warpDistCol[col]!) continue; if (s.clampL !== undefined && (col < s.clampL || col > s.clampR!)) continue; + if (s.depth < spriteZ[col]!) spriteZ[col] = s.depth; const texX = ((col - s.left) / (s.right - s.left)); if (img) { ctx.drawImage( @@ -406,6 +411,7 @@ // translucent, swirling — the doorway between rooms that are not // neighbors announces itself. for (const vl of veils) { + if (vl.depth >= spriteZ[vl.col]!) continue; const vh = Math.min(H * 2.5, H / Math.max(vl.depth, 0.05)); const vTop = half - vh / 2; const wt = textures.warp!; @@ -421,6 +427,7 @@ // Conjurations rising: the wall (or stone) grows bottom-up where it // will stand, glowing swirls running over the young face. for (const ri of risings) { + if (ri.depth >= spriteZ[ri.col]!) continue; const full = Math.min(H * 2.5, H / Math.max(ri.depth, 0.05)); const top0 = half + full / 2 - full * ri.g; const tex = textures[ri.kind] ?? textures.wall!; @@ -436,6 +443,7 @@ // Doorway lintels: the frame's top rows hung across each opening. for (const li of lintels) { + if (li.depth >= spriteZ[li.col]!) continue; const lh = Math.min(H * 2.5, H / Math.max(li.depth, 0.05)); const lTop = half - lh / 2; const ft = textures.doorframe!; @@ -451,6 +459,7 @@ // The ghosts of walls you know are lies: drawn over everything at // their columns, thin as breath, rippling. for (const gh of ghosts) { + if (gh.depth >= spriteZ[gh.col]!) continue; const gHft = Math.min(H * 2.5, H / Math.max(gh.depth, 0.05)); const gTop = half - gHft / 2; const tex = textures.wall!;