// Loose bars, flying grains and queued blueprint blocks in the grain buffer. function worldObjects() { const { bw, bh, px, vx0, vy0, smoothOn: sm, lens } = R; const useFog = SET.fog, incand = SET.incandescence; // bars and other loose objects if (!lens) for (const e of ents) { if (useFog && fogSeen(e.ix, e.iy) < 64) continue; const ex = e.ix - vx0, ey = e.iy - vy0; if (ex + BAR_W < 0 || ey + BAR_H < 0 || ex >= bw || ey >= bh) continue; const m = e.m; for (let dy = 0; dy < BAR_H; dy++) for (let dx = 0; dx < BAR_W; dx++) { const sx = ex + dx, sy = ey + dy; if (sx < 0 || sy < 0 || sx >= bw || sy >= bh) continue; let r = COLR[m], g = COLG[m], b = COLB[m]; const end = dx === 0 || dx === BAR_W - 1; if (dy === 0) { r += end ? 10 : 34; g += end ? 8 : 28; b += end ? 6 : 24; } else { r -= end ? 34 : 18; g -= end ? 30 : 16; b -= end ? 26 : 14; } if (e.T > 450 && incand) { const gi = glowIndex(e.T), w = GLOW_W[gi]; r = r * (1 - w) + GLOW_R[gi] * w; g = g * (1 - w) + GLOW_G[gi] * w; b = b * (1 - w) + GLOW_B[gi] * w; } if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; if (R.gpuOn && !gpuOverrideHas(sy * bw + sx)) { if (sm) cellPixel(sx + vx0, sy + vy0); else GPU.overrideCount++; } px[sy * bw + sx] = (sm ? 0x04000000 : 0xff000000) | ((b > 255 ? 255 : b | 0) << 16) | ((g > 255 ? 255 : g | 0) << 8) | (r > 255 ? 255 : r | 0); } } // grains in flight from the vacuum nozzle, a screw or a belt (rain and snow are drawn over the top, see drawRain) if (!lens) for (const f of flyers) { if (f.rain || (useFog && fogSeen(f.x, f.y) < 64)) continue; const sx = Math.floor(f.x) - vx0, sy = Math.floor(f.y) - vy0; if (sx < 0 || sy < 0 || sx >= bw || sy >= bh) continue; const m = f.m, v = ((sx * 7 + sy * 13) & 15) - 8; if (R.gpuOn && !gpuOverrideHas(sy * bw + sx)) { if (sm) cellPixel(sx + vx0, sy + vy0); else GPU.overrideCount++; } px[sy * bw + sx] = (sm ? 0x02000000 : 0xff000000) | (Math.max(0, Math.min(255, COLB[m] + v)) << 16) | (Math.max(0, Math.min(255, COLG[m] + v)) << 8) | Math.max(0, Math.min(255, COLR[m] + v)); } // blueprint ghosts: blocks waiting to be built if (ghostBlocks.size) { const bx0 = vx0 >> 2, by0 = vy0 >> 2, bx1 = (vx0 + bw) >> 2, by1 = (vy0 + bh) >> 2; const pulse = (R.frame >> 3) & 3; for (const [b, gv] of ghostBlocks) { const gbx = b % BW, gby = (b / BW) | 0; if (gbx < bx0 || gbx > bx1 || gby < by0 || gby > by1) continue; const blocked = ghostBlocked.has(b), code = gv[0], v = gv[1]; let tr = 90, tg = 190, tb = 230; 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), diagonal = code === BP_SCREW && (v >= 4 || straightScrewJoins(gbx, gby, v, ghostBlocks)); const joins = slope ? slopeBeltConnections(gbx, gby, code, ghostBlocks) : diagonal ? (v >= 4 ? diagonalScrewJoins(gbx, gby, v, ghostBlocks) : straightScrewJoins(gbx, gby, v, ghostBlocks)) : 0; const caps = code === BP_BELT || code === BP_FILTER ? flatBeltCaps(b, ghostBlocks) : 3; for (let dy = slope ? -9 : diagonal ? -4 : 0; dy < (slope || diagonal ? 8 : BS); dy++) for (let dx = slope ? -5 : diagonal ? -4 : 0; dx < (slope ? 9 : diagonal ? 8 : BS); dx++) { let sd = 0; if (diagonal) { if (v < 4 && ((v & 1) ? dx < 0 || dx >= BS : dy < 0 || dy >= BS)) continue; const x = gbx * BS + dx, y = gby * BS + dy; if (x < 0 || y < 0 || x >= W || y >= H) continue; 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 = diagonalScrewShape(x + 0.5, y + 0.5, b, v, joins); if (sd > 0) continue; } if (slope) { const x = gbx * BS + dx, y = gby * BS + dy; if (x < 0 || y < 0 || x >= W || y >= H) continue; 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); const up = !isFilter(code) && slopeUphill(code, v), rib = up && slopePreviewCleat(x, y, b, code); if (sd > 0 && !rib && (!up || 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; if (sx < 0 || sy < 0 || sx >= bw || sy >= bh) continue; const k = sy * bw + sx; if (R.gpuOn && !gpuOverrideHas(k)) cellPixel(sx + vx0, sy + vy0); const c = px[k]; const edge = slope || diagonal ? sd > -0.8 : (dx === 0 && (caps & 1)) || dy === 0 || (dx === BS - 1 && (caps & 2)) || dy === BS - 1; const a = edge ? (((dx + dy + pulse) & 3) === 0 ? 0.85 : 0.6) : 0.28; const pr = c & 255, pg = (c >> 8) & 255, pb = (c >> 16) & 255; px[k] = (sm ? 0x04000000 : 0xff000000) | ((pb + (tb - pb) * a) << 16) | ((pg + (tg - pg) * a) << 8) | (pr + (tr - pr) * a); } } } }