diff --git a/docs/PROJECT_MAP.md b/docs/PROJECT_MAP.md index dfb9d99..c4f5af7 100644 --- a/docs/PROJECT_MAP.md +++ b/docs/PROJECT_MAP.md @@ -343,14 +343,14 @@ Drawing (src/render/): browser only. This file: the renderer state R, colour tab Propagated coloured light from glowing and burning cells. - functions: computeLight -### src/render/world.js (309 lines) +### src/render/world.js (308 lines) Scale colour without changing the smooth-look class. - functions: fogColor, drawWorld - variables: TUBE_CLASS -### src/render/machines.js (174 lines) +### src/render/machines.js (207 lines) Machine overlays: fans, engines, silo and the rest, drawn on top of the world. -- functions: cellRect, drawHazardRims, drawMachines, drawSilo, drawSiloPixel +- functions: cellRect, drawHazardRims, drawMachines, drawProcBlocks, drawSilo, drawSiloPixel ### src/render/overlays.js (229 lines) Other overlays: floating text, rain and snow, flow arrows, filter tags, molds, the bot, particles. diff --git a/src/render/machines.js b/src/render/machines.js index f177ace..14a49ee 100644 --- a/src/render/machines.js +++ b/src/render/machines.js @@ -75,6 +75,39 @@ function drawMachines() { } ctx.restore(); } + drawProcBlocks(); +} +// Crushing rollers and saw blades sit over the shared steel housings in both looks. +function drawProcBlocks() { + const ctx = R.ctx; + for (const b of procBlocks) { + const bx = b % BW, by = (b / BW) | 0; + const [sx, sy, sw] = cellRect(bx * BS, by * BS, BS, BS); + if (sx > R.canvas.width || sy > R.canvas.height || sx + sw < 0 || sy + sw < 0) continue; + if (SET.fog && fogSeen(bx * BS + 2, by * BS + 2) < 64) continue; + const saw = blockP[b] === BP_SAW, busy = tick - (procState.get(b)?.busyT ?? -999) < 30; + const angle = busy ? tick * (saw ? 0.5 : 0.25) : b * 0.7; + const radius = sw * (saw ? 0.38 : 0.22), teeth = saw ? 10 : 6; + ctx.save(); + ctx.lineWidth = Math.max(1, sw * 0.025); + for (let wheel = 0; wheel < (saw ? 1 : 2); wheel++) { + const cx = sx + sw * (saw ? 0.5 : wheel ? 0.73 : 0.27), cy = sy + sw * 0.5; + const a = wheel ? -angle : angle; + ctx.fillStyle = saw ? '#b9c0c8' : '#8a8f96'; ctx.strokeStyle = '#444b54'; + if (sw >= 12) for (let k = 0; k < teeth; k++) { + const t = a + k * Math.PI * 2 / teeth, half = (saw ? 0.18 : 0.24); + ctx.beginPath(); + ctx.moveTo(cx + Math.cos(t - half) * radius * 0.9, cy + Math.sin(t - half) * radius * 0.9); + ctx.lineTo(cx + Math.cos(t) * radius * 1.15, cy + Math.sin(t) * radius * 1.15); + ctx.lineTo(cx + Math.cos(t + half) * radius * 0.9, cy + Math.sin(t + half) * radius * 0.9); + ctx.closePath(); ctx.fill(); ctx.stroke(); + } + ctx.beginPath(); ctx.arc(cx, cy, radius, 0, Math.PI * 2); ctx.fill(); ctx.stroke(); + if (saw) { ctx.beginPath(); ctx.arc(cx, cy, radius * 0.65, 0, Math.PI * 2); ctx.stroke(); } + ctx.fillStyle = '#292e36'; ctx.beginPath(); ctx.arc(cx, cy, Math.max(1, radius * 0.19), 0, Math.PI * 2); ctx.fill(); + } + ctx.restore(); + } } // The silo: legs and braces, a cone to a slide gate, a ribbed steel drum with a ladder and a sight // glass that shows how full it is, a roof with the loading hatch. All in grain units from its corner. diff --git a/src/render/world.js b/src/render/world.js index d73911f..ea7a47d 100644 --- a/src/render/world.js +++ b/src/render/world.js @@ -116,9 +116,8 @@ function drawWorld() { else if (m === GATE) { if ((x & 1) === 0 && (y & 3) !== 0) { r -= 40; g -= 24; b -= 20; } } else if (m === CUTST) { const lx = x & 3, ly = y & 3; if (ly === 1 || ly === 3 || lx === (ly < 2 ? 3 : 1)) { r -= 34; g -= 33; b -= 30; } else if (ly === 0 || ly === 2) { r += 10; g += 10; b += 9; } } else if (m === GRINDER || m === SAWB) { - const s = procState.get((y >> 2) * BW + (x >> 2)), step = s && tick - s.busyT < 30 ? anim >> 2 : 0, lx = x & 3, ly = y & 3; - const tooth = m === GRINDER ? (ly === 1 || ly === 2) && ((lx + ly + step) & 1) : ly === 1 || ly === 2 && ((lx + step) & 1); - r = tooth ? 166 : 46; g = tooth ? 174 : 52; b = tooth ? 186 : 62; + const lx = x & 3, ly = y & 3, frame = lx === 0 || lx === 3 || ly === 0 || ly === 3; + r = frame ? 96 : 38; g = frame ? 102 : 42; b = frame ? 112 : 50; } else if (m === WOOD) { if ((y & 3) === 2 || ((x + (y >> 2) * 3) & 7) === 0) { r -= 26; g -= 22; b -= 16; } } // planks else if (m === LWOOD) { if (((x * 3 + y) & 3) === 0) { r -= 30; g -= 26; b -= 18; } } // stringy fibres diff --git a/test/play.py b/test/play.py index ce29b11..f6806dd 100644 --- a/test/play.py +++ b/test/play.py @@ -700,6 +700,17 @@ with sync_playwright() as p: pg.keyboard.press('Control+z'); settle(200) check('Ctrl+Z takes the Grinder row back', ev(f'(() => {{ for (let bx = {bbx} - 6; bx <= {bbx} - 4; bx++) if (blockP[({bby} + 3) * BW + bx]) return false; return true; }})()')) + check('drawing Grinder wheels and the Saw blade leaves the sim RNG unchanged', ev(f'''(() => {{ + const bx = {bbx} - 6, by = {bby} + 3; + const grinder = placeBlock(BP_GRIND, 0, bx, by, true), saw = placeBlock(BP_SAW, 0, bx + 1, by, true); + try {{ + rebuildProcessors(); + const before = RS; + drawProcBlocks(); + return grinder === '' && saw === '' && RS === before; + }} finally {{ removeBlock(bx, by); removeBlock(bx + 1, by); rebuildProcessors(); }} + }})()''')) + # 7b. filter: choose several materials with F, place a line, replace belts with G, edit the whole line ev('seen[CUORE] = 1; seen[FEORE] = 1; seen[SAND] = 1; money = 1000; GAME.filterCfg = { m: [], inv: 0 };') ok = select('3', "piece().id === 'filter'")