Sprites respect the window they are seen through
DUKK's floor-to-ceiling white sliver, decoded: the sprite gate only asked "did this column's ray warp?" — so a REAL body standing in front of a warp mouth was clipped out of the mouth's columns (leaving a baffling sliver of a huge close sprite), and a body virtualized through warp A could paint columns bent by warp B. Every column now remembers WHICH warp bent its ray and how far away that mouth stood; a real body paints a column only nearer than its mouth (in front of the window), and a virtual one only through its own warp's columns, beyond the mouth. Projectile legs carry the same identity. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
045e868190
commit
cd9ce9fddf
@@ -238,7 +238,12 @@
|
||||
// side must MATCH its column's, or bodies near a far mouth would
|
||||
// ghost into real corridors the unrolled space happens to overlap.
|
||||
const zbuf = new Float64Array(W);
|
||||
const warpedCol = new Uint8Array(W);
|
||||
// Per column: which warp (if any) the ray bent through, and how far
|
||||
// away that mouth stood. A REAL body paints a column only if it is
|
||||
// nearer than the mouth (it stands in front of the window); a
|
||||
// VIRTUAL one only through its OWN warp's columns, beyond the mouth.
|
||||
const warpIdCol = new Int32Array(W).fill(-1);
|
||||
const warpDistCol = new Float64Array(W).fill(Infinity);
|
||||
// Known illusions: the ray passes, but a translucent ghost of a wall
|
||||
// stands at the crossing — drawn after the sprites so bodies show
|
||||
// through it, shimmering so nobody mistakes it for stone.
|
||||
@@ -250,7 +255,10 @@
|
||||
const hit = castRay(view, ex, ey, rayAngle, doors);
|
||||
const depth = hit.dist * Math.cos(rayAngle - facing); // no fisheye
|
||||
zbuf[col] = depth;
|
||||
warpedCol[col] = hit.warped ? 1 : 0;
|
||||
if (hit.warpId !== undefined) {
|
||||
warpIdCol[col] = hit.warpId;
|
||||
warpDistCol[col] = (hit.warpDist ?? 0) * Math.cos(rayAngle - facing);
|
||||
}
|
||||
if (hit.ghost) {
|
||||
ghosts.push({
|
||||
col, depth: hit.ghost.dist * Math.cos(rayAngle - facing),
|
||||
@@ -341,6 +349,7 @@
|
||||
scale: f.kind === "projectile" ? 0.3 : 0.25 + 0.6 * p,
|
||||
rise: f.kind === "impact" ? (f.rise ?? 0.3) : 0.3,
|
||||
warped: f.kind === "projectile" ? f.warped : undefined,
|
||||
warpId: f.kind === "projectile" ? f.warpId : undefined,
|
||||
}, ex, ey);
|
||||
if (s) sprites.push({ ...s, alpha: f.kind === "impact" ? 1 - p : 1, fallback: f.art });
|
||||
}
|
||||
@@ -359,7 +368,9 @@
|
||||
if (s.alpha !== undefined || s.glow) ctx.globalAlpha = s.alpha ?? 1;
|
||||
for (let col = Math.max(0, s.left | 0); col < Math.min(W, s.right); col++) {
|
||||
if (s.depth >= zbuf[col]!) continue;
|
||||
if ((s.warped ? 1 : 0) !== warpedCol[col]!) continue;
|
||||
if (s.warped) {
|
||||
if (warpIdCol[col] !== (s.warpId ?? -2) || s.depth <= warpDistCol[col]!) continue;
|
||||
} else if (s.depth >= warpDistCol[col]!) continue;
|
||||
const texX = ((col - s.left) / (s.right - s.left));
|
||||
if (img) {
|
||||
ctx.drawImage(
|
||||
@@ -437,6 +448,7 @@
|
||||
top: number;
|
||||
bottom: number;
|
||||
warped?: boolean;
|
||||
warpId?: number;
|
||||
glow?: boolean;
|
||||
alpha?: number;
|
||||
fallback?: string;
|
||||
@@ -444,7 +456,7 @@
|
||||
function project(
|
||||
b: { x: number; y: number; src: string; scale: number; rise: number;
|
||||
aspect?: number; alpha?: number; glow?: boolean; bias?: number;
|
||||
fallback?: string; warped?: boolean },
|
||||
fallback?: string; warped?: boolean; warpId?: number },
|
||||
ex: number, ey: number,
|
||||
): Projected | null {
|
||||
const relX = b.x - ex, relY = b.y - ey;
|
||||
@@ -464,7 +476,7 @@
|
||||
: size;
|
||||
const bottom = half + wallH / 2 - b.rise * wallH;
|
||||
return {
|
||||
src: b.src, depth: depth - (b.bias ?? 0), warped: b.warped,
|
||||
src: b.src, depth: depth - (b.bias ?? 0), warped: b.warped, warpId: b.warpId,
|
||||
alpha: b.alpha, glow: b.glow, fallback: b.fallback,
|
||||
left: screenX - wide / 2, right: screenX + wide / 2,
|
||||
top: bottom - size, bottom,
|
||||
|
||||
Reference in New Issue
Block a user