Silo: pixel-art version for the pixel look
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -183,6 +183,9 @@ above, including:
|
||||
in an older world but not in a new one. Most likely the sizzle: in a test, a lava and water
|
||||
contact far from the bot sizzled about 580 times a minute, all played at full volume.
|
||||
|
||||
- **The silo has pixel art in the pixel look**, drawn grain by grain like the rest of the world;
|
||||
the smooth look keeps the illustrated silo. The owner noticed it looked the same in both.
|
||||
|
||||
## Ideas not built yet
|
||||
|
||||
- **Concrete**, as a stronger wall material from rubble.
|
||||
|
||||
+3
-2
@@ -341,9 +341,9 @@ drawWorld: the per-grain pixel buffer (pixel look), also the input of the smooth
|
||||
- functions: drawWorld
|
||||
- variables: TUBE_CLASS
|
||||
|
||||
### src/render/machines.js (157 lines)
|
||||
### src/render/machines.js (197 lines)
|
||||
Machine overlays: fans, engines, refiner, cutter, silo and the rest, drawn on top of the world.
|
||||
- functions: cellRect, drawHazardRims, drawMachines, drawSilo
|
||||
- functions: cellRect, drawHazardRims, drawMachines, drawSilo, drawSiloPixel
|
||||
|
||||
### src/render/overlays.js (228 lines)
|
||||
Other overlays: floating text, rain and snow, flow arrows, filter tags, molds, the bot, particles.
|
||||
@@ -470,4 +470,5 @@ The frame loop and boot.
|
||||
- `tools/scenes/belt-heap.js`: A belt feeding an upward screw: sand underneath a deep heap of copper ore. Run clear-sky.js first, e.g. python3 tools/shot.py /tmp/belt-heap.png --setup tools/scenes/clear-sky.js --js "$(cat tools/scenes/belt-heap.js)" --ticks 240 --zoom 7
|
||||
- `tools/scenes/clear-sky.js`: A clear work area left of the bot's starting point (the trade dock is to its right): open sky 160 grains wide and 40 tall, over a flat stone floor. Money and a bag of building stuff to build with. Sets FLOOR (the first row of the floor), BX, BY (the leftmost block of the area that stands on the floor) and CAM (the middle of the area).
|
||||
- `tools/scenes/mold-labels.js`: Run after clear-sky.js: filling, blocked, set, and hot machinery in one view.
|
||||
- `tools/scenes/silo.js`: Run after clear-sky.js; leave paused so the open gate keeps its demonstration charge.
|
||||
- `tools/scenes/stone-uses.js`: The stone and sand machines: a half-full silo with its gate open over a belt, a stone cutter fed with rubble, and cut stone and glass brick walls. Run clear-sky.js first, e.g. python3 tools/shot.py /tmp/stone.png --setup tools/scenes/clear-sky.js --js "$(cat tools/scenes/stone-uses.js)" --ticks 240 --zoom 7
|
||||
|
||||
@@ -4,6 +4,22 @@ What agents have done, newest first. Add an entry for every piece of work: the d
|
||||
note or request it was for, what changed, the files touched, the tests run, and anything left
|
||||
open or not verified. Keep each entry short; the git history has the details.
|
||||
|
||||
## 2026-10-23: pixel-art silo for the pixel look (Claude Code, with Codex)
|
||||
|
||||
Note: "the silo art looks the same for both pixelated graphiocs and smooth."
|
||||
|
||||
- `src/render/machines.js`: `drawSilo` is the smooth (illustrated) version as before; in the
|
||||
pixel look `drawSiloPixel` draws it grain by grain: a drum shaded by column with rib rows and
|
||||
ladder rungs, a cone to the slide gate, legs, the roof hatch with its lid, and the sight glass
|
||||
filling in the contents colour. Codex's first version read poorly (dark side columns made
|
||||
the drum look narrow); Claude redrew the grain layout.
|
||||
- `tools/scenes/silo.js` (run after `clear-sky.js`): three silos, empty, half sand, nearly full
|
||||
copper ore with the gate open. Shots `shots/silo-*.png` at zoom 6 and 12; smooth shots match
|
||||
the before shots pixel for pixel. `docs/DESIGN.md`, `docs/PROJECT_MAP.md`.
|
||||
- Tests: all 11 headless suites and `play.py` (129) pass. `t_smooth.py`'s half-resolution check
|
||||
failed twice on the slow fallback at load ~5 (known flaky; it passed in the previous task).
|
||||
- Open: nothing.
|
||||
|
||||
## 2026-10-23: world sounds are local (Claude Code, with Codex)
|
||||
|
||||
Note: "there is a sound effect that seems to happen randomly but constantly… maybe the sound
|
||||
|
||||
@@ -102,6 +102,7 @@ function drawMachines() {
|
||||
// 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.
|
||||
function drawSilo(ctx, mm, sx, sy, zp) {
|
||||
if (!R.smoothOn) { drawSiloPixel(ctx, mm, sx, sy, zp); return; }
|
||||
const X = u => sx + u * zp, Y = u => sy + u * zp, full = Math.min(1, (mm.sn || 0) / SILO_CAP);
|
||||
const steel = (x0, x1) => { const g = ctx.createLinearGradient(X(x0), 0, X(x1), 0); g.addColorStop(0, '#3b4249'); g.addColorStop(0.22, '#a9b3bb'); g.addColorStop(0.5, '#87919a'); g.addColorStop(1, '#353c43'); return g; };
|
||||
ctx.save();
|
||||
@@ -155,3 +156,42 @@ function drawSilo(ctx, mm, sx, sy, zp) {
|
||||
ctx.beginPath(); ctx.moveTo(X(8.9), Y(0.9)); ctx.lineTo(X(10.2), Y(-1.4)); ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
function drawSiloPixel(ctx, mm, sx, sy, zp) {
|
||||
const full = Math.min(1, (mm.sn || 0) / SILO_CAP), col = `rgb(${COLR[mm.sm]},${COLG[mm.sm]},${COLB[mm.sm]})`;
|
||||
const grain = (x, y, c) => { ctx.fillStyle = c; ctx.fillRect(sx + x * zp, sy + y * zp, zp, zp); };
|
||||
// Steel shaded by column (light on the left, dark at the right edge), darker rib rows, and fixed
|
||||
// grain noise so it never shimmers. The drum is rows 2-19, the cone 20-22 narrowing to the gate.
|
||||
const steel = [[78,86,94],[176,186,194],[160,170,179],[148,158,167],[140,150,159],[134,144,153],
|
||||
[126,136,145],[118,128,137],[108,118,127],[96,105,114],[84,93,101],[62,70,78]];
|
||||
for (let y = 2; y < 23; y++) for (let x = 0; x < 12; x++) {
|
||||
if (y >= 20 && (x < y - 19 || x > 30 - y)) continue;
|
||||
const c = steel[x], h = Math.imul(mm.x + x, 374761393) ^ Math.imul(mm.y + y, 668265263);
|
||||
const n = (((h ^ h >>> 13) >>> 0) % 3 - 1) * 4 - (y === 6 || y === 11 || y === 15 || y === 19 ? 26 : 0) - (y >= 20 ? 10 : 0)
|
||||
- (x === 2 && y < 19 && !(y & 1) ? 34 : 0); // ladder rungs up the left side
|
||||
grain(x, y, `rgb(${c[0] + n},${c[1] + n},${c[2] + n})`);
|
||||
}
|
||||
// legs with a strut to the cone, the gate opening, and the slide gate (pulled aside when open)
|
||||
for (let y = 20; y < 24; y++) { grain(0, y, '#2f353b'); grain(11, y, '#2f353b'); }
|
||||
grain(1, 21, '#2f353b'); grain(10, 21, '#2f353b');
|
||||
for (let x = 4; x < 8; x++) grain(x, 23, '#1c1f23');
|
||||
if (mm.open) for (let x = 8; x < 11; x++) grain(x, 23, '#c99a3c'); else for (let x = 3; x < 9; x++) grain(x, 23, '#6b737b');
|
||||
// the sight glass fills from the bottom in the colour of what is inside
|
||||
for (let y = 3; y < 19; y++) grain(9, y, mm.sn > 0 && y >= 19 - Math.max(1, Math.round(16 * full)) ? col : '#14181c');
|
||||
// roof: a rim, shoulders, the dark hatch and its lid standing open
|
||||
for (let x = 0; x < 12; x++) {
|
||||
grain(x, 1, x >= 3 && x < 9 ? '#15181b' : '#5b646c');
|
||||
if (x < 3 || x >= 9) grain(x, 0, '#7d878f');
|
||||
}
|
||||
const lid = tick - (mm.fillT || -99) < 10 ? '#e0b43c' : '#9aa4ae';
|
||||
grain(8, 0, lid); grain(9, -1, lid);
|
||||
if (zp >= 3) {
|
||||
if (!R.monoFont) R.monoFont = getComputedStyle(document.documentElement).getPropertyValue('--font-mono').trim() || 'monospace';
|
||||
ctx.save(); ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillStyle = 'rgba(20,24,28,0.75)';
|
||||
ctx.font = `700 ${Math.max(8, Math.round(zp * 1.15))}px ${R.monoFont}`;
|
||||
ctx.fillText('SILO', sx + 5.6 * zp, sy + 5 * zp);
|
||||
ctx.font = `600 ${Math.max(8, Math.round(zp * 0.95))}px ${R.monoFont}`;
|
||||
ctx.fillText(mm.sn ? mm.sn.toLocaleString('en-US') : 'EMPTY', sx + 5.6 * zp, sy + 16.8 * zp);
|
||||
if (mm.sn) { grain(4, 18, col); grain(5, 18, col); grain(6, 18, col); }
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// Run after clear-sky.js; leave paused so the open gate keeps its demonstration charge.
|
||||
for (let k = 0; k < 3; k++) {
|
||||
const bx = BX + 10 + k * 7, by = BY - 5;
|
||||
placeMachineAt('silo', 0, bx, by);
|
||||
const mm = machines.find(m => m && m.type === 'silo' && m.x === bx * 4 && m.y === by * 4);
|
||||
mm.sm = k === 2 ? CUORE : SAND; mm.sn = k === 0 ? 0 : Math.floor(SILO_CAP * (k === 1 ? 0.5 : 0.95));
|
||||
mm.open = k === 2;
|
||||
}
|
||||
window.CAM = [(BX + 18.5) * 4, (BY - 2) * 4];
|
||||
Reference in New Issue
Block a user