Sidewall belt and screen drawing, cheaper cleat checks (t42, t43)
Far sidewall drawn behind the load with cleat ribs at their physics positions; sloped screens get a tinted mesh between rails and shake only when loaded. Powder skips cleat checks outside chunks that have cleats, and empty slopes let their chunks sleep. Record the screw conveyor and stall/carry-depth decisions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,22 @@ vec3 slopeShape(vec2 p, vec2 worldOrigin, float grade, int joins) {
|
||||
`;
|
||||
|
||||
const SM_SLOPE_DRAW = `
|
||||
if (nc == 31 || nc == 32) {
|
||||
vec4 tag = cellAt(tTree, c);
|
||||
float grade = nc == 31 ? -1.0 : 1.0;
|
||||
vec2 local = floor(tag.gb * 255.0 + 0.5) - 8.0 + fract(w);
|
||||
float sy = grade < 0.0 ? 4.0 : 0.0;
|
||||
float foot = (local.x + grade * (local.y - sy)) * 0.5;
|
||||
float depth = (grade * local.x - local.y + sy) * 0.70710678;
|
||||
int wallFlags = int(tag.a * 255.0 + 0.5);
|
||||
float ends = max((wallFlags & 8) == 0 ? -foot : -100.0, (wallFlags & 16) == 0 ? foot - 4.0 : -100.0);
|
||||
float sd = max(ends * 1.41421356, max(-depth, depth - ${CLEAT_HEIGHT.toFixed(1)}));
|
||||
float phase = float(wallFlags & 7);
|
||||
float wave = 0.5 + 0.5 * sin((foot + w.x - local.x - phase) * 3.14159265);
|
||||
vec3 rubber = mix(vec3(0.16,0.18,0.21), vec3(0.21,0.23,0.27), wave);
|
||||
C = mix(C, rubber, 1.0 - smoothstep(-px, px, sd));
|
||||
}
|
||||
|
||||
// Slopes use the flat belt's band, rollers and mesh in coordinates along the run.
|
||||
if ((nc == 2 || (nc >= 23 && nc <= 30)) &&
|
||||
(int(cellAt(tTree, c).a * 255.0 + 0.5) & 128) != 0 &&
|
||||
@@ -58,9 +74,7 @@ const SM_SLOPE_DRAW = `
|
||||
float rg = step(0.72, fract((axis - dir * (depth < 2.0 ? 1.0 : -1.0) * time * 30.0) * 0.5));
|
||||
vec3 belt;
|
||||
if (-sd < (mesh ? 1.1 : 0.8)) {
|
||||
belt = bandColor(lb, rg);
|
||||
if (mesh && ((joins & 32) != 0) == (depth < 2.0) && dot(own.rgb, vec3(1)) > 0.01)
|
||||
belt = mix(belt, own.rgb * (depth < 2.0 ? 1.0 : 0.8), 0.75 * rg);
|
||||
belt = mesh ? mix(vec3(0.22,0.25,0.29), vec3(0.48,0.53,0.59), depth < 2.0 ? 0.85 : 0.35) : bandColor(lb, rg);
|
||||
belt *= mix(0.55, 1.0, smoothstep(0.0, max(px * 1.4, 0.12), -sd));
|
||||
} else if (mesh) {
|
||||
vec2 cg = abs(fract(alongWorld) - 0.5);
|
||||
|
||||
+36
-10
@@ -135,16 +135,42 @@ function screenLoaded(b) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Far sidewalls stay behind the load. The cleat raster is the simulation barrier raster.
|
||||
function slopeDetailAt(i, x, y) {
|
||||
// Filled far wall, in belt coordinates. Project onto the face so ends stop at the slope ends.
|
||||
let slopeWallOwner = -1;
|
||||
function slopeWallShape(x, y, b, code = blockP[b]) {
|
||||
const g = beltGrade(code), ox = b % BW * BS, oy = ((b / BW) | 0) * BS;
|
||||
const sy = g < 0 ? BS : 0, lx = x - ox, ly = y - oy - sy;
|
||||
const foot = (lx + g * ly) / 2, depth = (g * lx - ly) * Math.SQRT1_2;
|
||||
return Math.max(-foot * Math.SQRT2, (foot - BS) * Math.SQRT2, -depth, depth - CLEAT_HEIGHT);
|
||||
}
|
||||
function slopeWallAt(x, y, smooth = false) {
|
||||
slopeWallOwner = -1;
|
||||
let best = smooth ? 0.8 : 0;
|
||||
for (let by = Math.max(0, (y >> 2) - 1); by <= Math.min(BH - 1, (y >> 2) + 3); by++)
|
||||
for (let bx = Math.max(0, (x >> 2) - 2); bx <= Math.min(BW - 1, (x >> 2) + 2); bx++) {
|
||||
const b = by * BW + bx;
|
||||
if (!isBelt(blockP[b]) || !isSlopeBelt(blockP[b])) continue;
|
||||
const sd = slopeWallShape(x + 0.5, y + 0.5, b);
|
||||
if (sd <= best) { best = sd; slopeWallOwner = b; }
|
||||
}
|
||||
return slopeWallOwner;
|
||||
}
|
||||
// The load occludes the far wall; ribs use exactly the simulation barrier raster.
|
||||
function slopeDetailAt(i, x, y, smooth = false) {
|
||||
slopeWallOwner = -1;
|
||||
if (!slopeBeltHalo[(y >> 2) * BW + (x >> 2)] && !cleatMask[i]) return 0;
|
||||
if (occ[i] || mach[i] || (mat[i] !== EMPTY && PH[mat[i]] !== PH_GAS) || part[i]) return 0;
|
||||
if (cleatMask[i]) return 1;
|
||||
for (let by = y >> 2; by <= Math.min(BH - 1, (y + 9) >> 2); by++) {
|
||||
const b = by * BW + (x >> 2), c = blockP[b];
|
||||
if (!isSlopeBelt(c)) continue;
|
||||
const depth = beltFaceY(c, x >> 2, by, x) - y;
|
||||
if (isFilter(c) ? depth === 2 : depth >= 6 && depth <= 7 + ((x + slopePhase[b]) & 1)) return isFilter(c) ? 3 : 2;
|
||||
if (occ[i] || mach[i] || part[i]) return 0;
|
||||
if (cleatMask[i] && PH[mat[i]] !== PH_SOLID) return 1;
|
||||
if (mat[i] !== EMPTY && PH[mat[i]] !== PH_GAS) return 0;
|
||||
return slopeWallAt(x, y, smooth) >= 0 ? 2 : 0;
|
||||
}
|
||||
|
||||
function slopePreviewCleat(x, y, b, code) {
|
||||
const bx = b % BW, by = (b / BW) | 0, g = beltGrade(code);
|
||||
for (let h = 0; h <= CLEAT_REACH; h++) {
|
||||
const foot = x - g * h;
|
||||
if (foot >= bx * BS && foot < (bx + 1) * BS && foot % CLEAT_SPACING === 0 &&
|
||||
y + h + 1 === beltFaceY(code, bx, by, foot)) return true;
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
+16
-7
@@ -289,11 +289,12 @@ function drawWorld() {
|
||||
const color = slopeBeltColor(sb, x, y, anim, br, bgc, bb);
|
||||
r = color & 255; g = color >> 8 & 255; b = color >> 16 & 255;
|
||||
}
|
||||
const slopeDetail = slopeDetailAt(i, x, y);
|
||||
const slopeDetail = slopeDetailAt(i, x, y, sm);
|
||||
if (slopeDetail) {
|
||||
r = slopeDetail === 1 ? 145 : slopeDetail === 3 ? 96 : 48;
|
||||
g = slopeDetail === 1 ? 125 : slopeDetail === 3 ? 106 : 52;
|
||||
b = slopeDetail === 1 ? 94 : slopeDetail === 3 ? 120 : 60;
|
||||
const wave = slopeDetail === 2 && ((x + beltGrade(blockP[slopeWallOwner]) * y - slopePhase[slopeWallOwner]) & 3) < 2;
|
||||
r = slopeDetail === 1 ? 100 : wave ? 51 : 43;
|
||||
g = slopeDetail === 1 ? 104 : wave ? 55 : 47;
|
||||
b = slopeDetail === 1 ? 112 : wave ? 63 : 55;
|
||||
}
|
||||
// incandescence
|
||||
if (T > 450 && m !== EMPTY && incand) {
|
||||
@@ -345,7 +346,13 @@ function drawWorld() {
|
||||
((y - ((sb / BW) | 0) * BS + 8) << 16) | ((x - (sb % BW) * BS + 8) << 8);
|
||||
if (slopeArt) { r = fm ? COLR[fm] : 0; g = fm ? COLG[fm] : 0; b = fm ? COLB[fm] : 0; }
|
||||
}
|
||||
if (slopeDetail) cl = 4;
|
||||
if (slopeDetail === 1) cl = 4;
|
||||
else if (slopeDetail === 2) {
|
||||
const wb = slopeWallOwner;
|
||||
cl = beltGrade(blockP[wb]) < 0 ? 31 : 32;
|
||||
tpx[row + bx] = ((128 | slopePhase[wb] | ((slopeBeltJoins[wb] & 12) << 1)) << 24) | cl |
|
||||
((y - ((wb / BW) | 0) * BS + 8) << 16) | ((x - wb % BW * BS + 8) << 8);
|
||||
}
|
||||
top = cl << 24;
|
||||
fpx[row + bx] = (tb ? 0xff000000 : 0) | (cl === 5 ? 0xff0000 : 0) | (cl === 3 ? 0xff00 : 0) | (cl === 1 && !builtForLight(i, x, y) ? 0xff : 0);
|
||||
}
|
||||
@@ -396,7 +403,7 @@ function drawWorld() {
|
||||
if (blocked) { tr = 230; tg = 70; tb = 60; }
|
||||
else if (isWall(code) && WALL_OF[v]) { const wm = WALL_OF[v]; tr = (COLR[wm] + 90) / 2; tg = (COLG[wm] + 190) / 2; tb = (COLB[wm] + 230) / 2; }
|
||||
const slope = isSlopeBelt(code), joins = slope ? slopeBeltConnections(gbx, gby, code, ghostBlocks) : 0;
|
||||
for (let dy = slope ? -4 : 0; dy < (slope ? 8 : BS); dy++) for (let dx = slope ? -4 : 0; dx < (slope ? 8 : BS); dx++) {
|
||||
for (let dy = slope ? -9 : 0; dy < (slope ? 8 : BS); dy++) for (let dx = slope ? -5 : 0; dx < (slope ? 9 : BS); dx++) {
|
||||
let sd = 0;
|
||||
if (slope) {
|
||||
const x = gbx * BS + dx, y = gby * BS + dy;
|
||||
@@ -404,7 +411,9 @@ function drawWorld() {
|
||||
const i = y * W + x, n = (y >> 2) * BW + (x >> 2);
|
||||
if (n !== b && (mat[i] !== EMPTY || part[i] || mach[i] || occ[i] || blockP[n])) continue;
|
||||
sd = slopeBeltShape(x + 0.5, y + 0.5, b, joins, code);
|
||||
if (sd > 0) continue;
|
||||
const rib = !isFilter(code) && slopePreviewCleat(x, y, b, code);
|
||||
if (sd > 0 && !rib && (isFilter(code) || slopeWallShape(x + 0.5, y + 0.5, b, code) > 0)) continue;
|
||||
if (rib) sd = -0.1;
|
||||
}
|
||||
if (isSlope(code) && !slopeCell(code, dx, dy)) continue;
|
||||
const sx = gbx * BS + dx - vx0, sy = gby * BS + dy - vy0;
|
||||
|
||||
Reference in New Issue
Block a user