Overlays yield to the body standing in front of them

The warp veil painted over a wizard standing before the mouth — the
overlay passes ran after the sprites with no knowledge of their depth.
Each column now remembers its nearest sprite, and every overlay family
(veils, ghost walls, doorway lintels, rising conjurations) skips the
columns where a body stands closer, while still washing translucently
over anything beyond.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Eric Wagoner
2026-08-23 21:46:27 -04:00
co-authored by Claude Fable 5
parent 7a32370ccb
commit b235a7a9cd
+9
View File
@@ -363,6 +363,10 @@
if (s) sprites.push({ ...s, alpha: f.kind === "impact" ? 1 - p : 1, fallback: f.art }); if (s) sprites.push({ ...s, alpha: f.kind === "impact" ? 1 - p : 1, fallback: f.art });
} }
sprites.sort((a, b) => b.sort - a.sort); 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) { for (const s of sprites) {
const img = imageFor(s.src) ?? const img = imageFor(s.src) ??
(s.fallback (s.fallback
@@ -381,6 +385,7 @@
if (warpIdCol[col] !== s.warpId || s.depth <= warpDistCol[col]!) continue; if (warpIdCol[col] !== s.warpId || s.depth <= warpDistCol[col]!) continue;
} else if (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.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)); const texX = ((col - s.left) / (s.right - s.left));
if (img) { if (img) {
ctx.drawImage( ctx.drawImage(
@@ -406,6 +411,7 @@
// translucent, swirling — the doorway between rooms that are not // translucent, swirling — the doorway between rooms that are not
// neighbors announces itself. // neighbors announces itself.
for (const vl of veils) { 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 vh = Math.min(H * 2.5, H / Math.max(vl.depth, 0.05));
const vTop = half - vh / 2; const vTop = half - vh / 2;
const wt = textures.warp!; const wt = textures.warp!;
@@ -421,6 +427,7 @@
// Conjurations rising: the wall (or stone) grows bottom-up where it // Conjurations rising: the wall (or stone) grows bottom-up where it
// will stand, glowing swirls running over the young face. // will stand, glowing swirls running over the young face.
for (const ri of risings) { 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 full = Math.min(H * 2.5, H / Math.max(ri.depth, 0.05));
const top0 = half + full / 2 - full * ri.g; const top0 = half + full / 2 - full * ri.g;
const tex = textures[ri.kind] ?? textures.wall!; const tex = textures[ri.kind] ?? textures.wall!;
@@ -436,6 +443,7 @@
// Doorway lintels: the frame's top rows hung across each opening. // Doorway lintels: the frame's top rows hung across each opening.
for (const li of lintels) { 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 lh = Math.min(H * 2.5, H / Math.max(li.depth, 0.05));
const lTop = half - lh / 2; const lTop = half - lh / 2;
const ft = textures.doorframe!; const ft = textures.doorframe!;
@@ -451,6 +459,7 @@
// The ghosts of walls you know are lies: drawn over everything at // The ghosts of walls you know are lies: drawn over everything at
// their columns, thin as breath, rippling. // their columns, thin as breath, rippling.
for (const gh of ghosts) { 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 gHft = Math.min(H * 2.5, H / Math.max(gh.depth, 0.05));
const gTop = half - gHft / 2; const gTop = half - gHft / 2;
const tex = textures.wall!; const tex = textures.wall!;