Tessarune
Dungeon Mechanisms · crate.js

Crate and barrel

32×32 · 545 lines of JavaScript

A 32×32 program with two breakable shapes: a supply crate of boards with a framed front, a diagonal brace and riveted iron corner plates, and a bulged barrel of 14 staves with two iron hoops and a recessed lid with a bung. Every pixel knows which board or stave it belongs to, so the break moves whole boards. Each shape has “idle” (8 frames, a glint over the iron), “hit” (6 frames, once: squash and rock), “break” (10 frames, once: the boards or staves burst and fall into a pile with a puff of splinters) and “broken” (8 frames, a top board or leaning stave teeters as dust settles).

Crate and barrel — Rendered output6×
Rendered by this program, variant “break” · 32×32 · 10 frames
Dungeon MechanismsGet the animated sprites: Dungeon Mechanisms on itch.ioVol.2 · 12 traps, doors and breakables

The header. The comment at the top of the file is the brief: size, view, light direction and every variant.

crate.js · 1–13
// Supply crate and banded barrel — 32x32, top-down 3/4, key light top-left. Two breakable shapes in one file.// Both are ray-marched per pixel from a small solid model (camera elevation: ellipse ratio 0.35, as in Vol.1), so// the resting prop, every squash/rock pose of the hit and the broken remains come from one model://   crate  — a box of boards: top boards, a framed front (rails, posts, two infill planks, a diagonal brace),//            iron corner plates with rivets, nails at the board ends.//   barrel — a bulged solid of revolution: 14 staves, two iron hoops, a recessed lid of three boards with a bung.// Every pixel knows which board / stave group it belongs to, so the break moves WHOLE boards: they burst, tumble// and land as a pile. Off the prop, a piece is re-lit as a chunk (lit top-left edge, dark lower edge).// Variants (shape s = crate | barrel; the crate's names carry no suffix)://   idle[-s]    loop 8f      — a glint runs over the iron//   hit[-s]     one-shot 6f  — squash on impact, rocks on its bottom edge right/left, settles on idle frame 0//   break[-s]   one-shot 10f — cracks, boards/staves burst and fall into a pile, splinter puff; ends on broken f0//   broken[-s]  loop 8f      — the pile; the top board (crate) / a leaning stave (barrel) teeters, dust settles

The last lines. submit declares the canvas and lists the variants the renderer exports.

crate.js · 541–545
submit(Breakable, {  size: [W, H], origin: "top-left", kind: "icon", scale: 1,  anchor: { x: CX, y: GROUND },  variants: V,});
Show the whole program (545 lines)
crate.js · 545 lines
// Supply crate and banded barrel — 32x32, top-down 3/4, key light top-left. Two breakable shapes in one file.// Both are ray-marched per pixel from a small solid model (camera elevation: ellipse ratio 0.35, as in Vol.1), so// the resting prop, every squash/rock pose of the hit and the broken remains come from one model://   crate  — a box of boards: top boards, a framed front (rails, posts, two infill planks, a diagonal brace),//            iron corner plates with rivets, nails at the board ends.//   barrel — a bulged solid of revolution: 14 staves, two iron hoops, a recessed lid of three boards with a bung.// Every pixel knows which board / stave group it belongs to, so the break moves WHOLE boards: they burst, tumble// and land as a pile. Off the prop, a piece is re-lit as a chunk (lit top-left edge, dark lower edge).// Variants (shape s = crate | barrel; the crate's names carry no suffix)://   idle[-s]    loop 8f      — a glint runs over the iron//   hit[-s]     one-shot 6f  — squash on impact, rocks on its bottom edge right/left, settles on idle frame 0//   break[-s]   one-shot 10f — cracks, boards/staves burst and fall into a pile, splinter puff; ends on broken f0//   broken[-s]  loop 8f      — the pile; the top board (crate) / a leaning stave (barrel) teeters, dust settlesconst W = 32, H = 32, CX = 16, GROUND = 29;const SE = 0.35, CE = Math.sqrt(1 - SE * SE);const LIGHT = (() => { const v = [-0.55, 0.5, 0.68], m = Math.hypot(...v); return v.map((c) => c / m); })();   // view: right, up, toward cameraconst N_IDLE = 8, N_HIT = 6, N_BREAK = 10, N_BROKEN = 8;const WOOD = ["w0", "w1", "w2", "w3", "w4"], IRON = ["n0", "n1", "n2", "n3", "n4"];// ---- shared camera / pose helpers ------------------------------------------------------------------------------function toObj(x, h, z, T) {  const x1 = x - T.dx - T.piv, h1 = h - T.hop;  const c = Math.cos(T.ang), s = Math.sin(T.ang);  const xo = x1 * c - h1 * s + T.piv, ho = x1 * s + h1 * c;  return [xo / T.sx, ho / T.sy, z / T.sx];}function nToView(n, T) {  let a = n[0] / T.sx, b = n[1] / T.sy, c3 = n[2] / T.sx;  const m = Math.hypot(a, b, c3); a /= m; b /= m; c3 /= m;  const c = Math.cos(T.ang), s = Math.sin(T.ang);  const wx = a * c + b * s, wh = -a * s + b * c;  return [wx, wh * CE - c3 * SE, wh * SE + c3 * CE];}const dotL = (n) => n[0] * LIGHT[0] + n[1] * LIGHT[1] + n[2] * LIGHT[2];function cast(shape, T, cut) {  const buf = new Array(W * H).fill(null);  for (let py = 0; py < H; py++) for (let px = 0; px < W; px++) {    const X = px + 0.5 - CX, Y = py + 0.5 - shape.refy;    if (Math.abs(X - T.dx) > 13) continue;    for (let d = 18; d >= -18; d -= 0.15) {      const wh = -Y * CE + d * SE, wz = Y * SE + d * CE;      const [xo, ho, zo] = toObj(X, wh, wz, T);      const hit = shape.solid(xo, ho, zo, cut);      if (hit) { hit.d = dotL(nToView(hit.n, T)); buf[py * W + px] = hit; break; }    }  }  return shape.tone(buf, cut);}// ---- CRATE -----------------------------------------------------------------------------------------------------const CW = 11, CH = 15, CD = 9, FB = 2.6, PL = 3.3;        // half width, height, half depth, frame board, plateconst CRATE = {  refy: 26.2,  solid(x, h, z) {    if (h < 0 || h > CH || Math.abs(x) > CW || Math.abs(z) > CD) return null;    // entry face: the nearest of top / front / sides    let f = "front", best = CD - z;    if (CH - h < best) { f = "top"; best = CH - h; }    if (x + CW < best) { f = "left"; best = x + CW; }    if (CW - x < best) { f = "right"; best = CW - x; }    const n = f === "front" ? [0, 0, 1] : f === "top" ? [0, 1, 0] : f === "left" ? [-1, 0, 0] : [1, 0, 0];    return { f, x, h, z, n };  },  // board id + material of a surface point  board(b) {    const ax = Math.abs(b.x);    if (b.f === "top") {      if (ax > CW - PL && Math.abs(b.z) > CD - PL) return { id: b.x < 0 ? "topL" : "topR", m: "iron", rivet: Math.abs(ax - (CW - 1.6)) < 0.55 && Math.abs(Math.abs(b.z) - (CD - 1.6)) < 0.8 };      const k = Math.min(3, Math.floor((b.x + CW) / (CW / 2)));      return { id: k < 2 ? "topL" : "topR", m: "wood", k: "t" + k, u: b.z };    }    const u = b.f === "front" ? b.x : b.f === "left" ? -b.z : b.z, v = b.h;    const side = b.f !== "front";    if (!side && ax > CW - PL && (v > CH - PL || v < PL)) {      return { id: b.x < 0 ? "postL" : "postR", m: "iron", rivet: Math.abs(ax - (CW - 1.5)) < 0.55 && Math.abs((v > CH / 2 ? CH - v : v) - 1.5) < 0.55 };    }    if (side) return { id: b.f === "left" ? "postL" : "postR", m: "wood", k: "s", u: v };    if (v > CH - FB) return { id: "railT", m: "wood", k: "rT", u: b.x, raised: true };    if (v < FB) return { id: "railB", m: "wood", k: "rB", u: b.x, raised: true };    if (ax > CW - FB) {      const nail = Math.abs(ax - (CW - 1.3)) < 0.55 && (Math.abs(v - 5) < 0.55 || Math.abs(v - 10) < 0.55);      return { id: b.x < 0 ? "postL" : "postR", m: nail ? "nail" : "wood", k: "p" + (b.x < 0 ? "L" : "R"), u: v, raised: true, post: true };    }    // diagonal brace from lower left to upper right over the infill    const x0 = -CW + FB, y0 = FB, x1 = CW - FB, y1 = CH - FB;    const dist = ((b.x - x0) * (y1 - y0) - (v - y0) * (x1 - x0)) / Math.hypot(x1 - x0, y1 - y0);    if (Math.abs(dist) < 1.45) return { id: "brace", m: "wood", k: "br", u: b.x, raised: true, below: dist > 0.6 };    const lower = v < CH / 2;    return { id: lower ? "plankB" : "plankT", m: "wood", k: lower ? "pB" : "pT", u: b.x, under: dist > 1.45 && dist < 2.6 };  },  tone(buf) {    const out = new Array(W * H).fill(null);    const info = buf.map((b) => (b ? this.board(b) : null));    for (let i = 0; i < W * H; i++) {      const b = buf[i]; if (!b) continue;      const q = info[i], px = i % W, py = (i - px) / W;      const up = py > 0 ? info[i - W] : null, dn = py < H - 1 ? info[i + W] : null;      const lf = px > 0 ? info[i - 1] : null, rt = px < W - 1 ? info[i + 1] : null;      let key, lv;      if (q.m === "iron" || q.m === "nail") {        lv = b.d > 0.75 ? 3 : 2;        const same = (o) => o && o.m === "iron" && o.id === q.id;        if (q.m === "iron") {          if (!same(up) || !same(lf)) lv = 3; else if (!same(dn) || !same(rt)) lv = 1;        }        if (q.m === "nail") lv = 1;        key = q.rivet ? "n4" : IRON[lv];        out[i] = { key, part: "iron", piece: q.id, lv, m: "iron" };        continue;      }      // wood: base level by face, then seams and lit edges between boards      lv = b.f === "top" ? (b.d > 0.55 ? 3 : 2) : b.f === "front" ? (b.d > 0.8 ? 3 : b.d > 0.45 ? 2 : 1) : 1;      if (b.f === "front" && !q.raised) lv = Math.max(1, lv - 1);            // infill sits back in the frame      if (q.under) lv = Math.max(0, lv - 1);                                  // the brace shades the plank below it      const other = (o) => o && o.m !== "iron" && o.k !== q.k;      if (other(rt) || other(dn)) lv = b.f === "top" ? 1 : 0;      else if (!up || other(up) || other(lf)) lv = Math.min(4, lv + 1);      // countable grain marks: a short dark streak on some boards      else if (q.k && hash(q.k.charCodeAt(0) * 7 + q.k.length, Math.floor((q.u + 20) / 5)) > 0.72 && Math.floor(q.u + 20) % 5 === 2 && py % 3 === 1) lv = Math.max(0, lv - 1);      out[i] = { key: WOOD[lv], part: q.id.startsWith("top") ? "lid" : q.id === "brace" ? "brace" : q.post || q.k === "s" ? "posts" : "boards", piece: q.id, lv, m: "wood" };    }    return out;  },};// ---- BARREL ----------------------------------------------------------------------------------------------------const BTOP = 17, BLID = 16.1, BWALL = 1.0;const BPROF = [[0, 6.3], [2, 7.1], [5, 7.8], [8.5, 8.1], [12, 7.8], [15, 7.1], [17, 6.3]];const BRT = [];for (let i = 0; i <= 340; i++) {  const h = i * 0.05;  let r = BPROF[BPROF.length - 1][1];  for (let k = 1; k < BPROF.length; k++) {    const [h0, r0] = BPROF[k - 1], [h1, r1] = BPROF[k];    if (h <= h1) { const u = (h - h0) / (h1 - h0), s = u * u * (3 - 2 * u); r = r0 + (r1 - r0) * s; break; }  }  BRT.push(r);}const BR = (h) => BRT[Math.max(0, Math.min(340, Math.round(h * 20)))];const BdR = (h) => (BR(h + 0.4) - BR(h - 0.4)) / 0.8;const STAVES = 14;const HOOPS = [[2.2, 3.8], [13.2, 14.8]];const BCUT = (th) => {                                       // jagged stave stubs left standing  const s = ((th / TAU) * STAVES + 20) % STAVES, k = Math.floor(s);  return 4.3 + hash(k, 3.3) * 2.6;};const STAVE_GROUP = (th) => {                                // which flying piece a stave belongs to: equal screen widths  const a = Math.sin(th);                                    // -1..1 across the barrel  return a < -0.6 ? 0 : a < -0.2 ? 1 : a < 0.2 ? 2 : a < 0.6 ? 3 : 4;};const BARREL = {  refy: 27.3,  solid(x, h, z, cut) {    if (h < 0 || h > BTOP) return null;    const rho = Math.hypot(x, z), r = BR(h);    if (rho > r) return null;    const rin = r - BWALL, th = Math.atan2(x, z);    const hollow = cut ? h > 1.2 : h > BLID;    if (hollow && rho < rin) return null;    if (cut && h > BCUT(th)) return null;    let s = "out", best = r - rho;    if (!cut && BTOP - h < best) { s = "chime"; best = BTOP - h; }    if (hollow && rho - rin < best) { s = "in"; best = rho - rin; }    if (!cut && !hollow && rho < rin && BLID - h < best) { s = "lid"; best = BLID - h; }    if (cut && !hollow && rho < rin && 1.2 - h < best) { s = "floor"; best = 1.2 - h; }    if (cut && BCUT(th) - h < best) { s = "cut"; best = BCUT(th) - h; }    const n = s === "out" ? [x / (rho || 1), -BdR(h), z / (rho || 1)] : s === "in" ? [-x / (rho || 1), 0, -z / (rho || 1)] : [0, 1, 0];    return { s, x, h, z, rho, th, n };  },  tone(buf, cut) {    const out = new Array(W * H).fill(null);    const stave = (b) => (b && (b.s === "out" || b.s === "cut") ? Math.floor(((b.th / TAU) * STAVES + 20) % STAVES) : -1);    for (let i = 0; i < W * H; i++) {      const b = buf[i]; if (!b) continue;      const px = i % W, py = (i - px) / W;      const up = py > 0 ? buf[i - W] : null, rt = px < W - 1 ? buf[i + 1] : null;      const hoop = b.s === "out" ? HOOPS.findIndex(([a, c]) => b.h >= a && b.h <= c) : -1;      const piece = cut ? "base" : b.s === "lid" || (b.s === "chime" && b.z < 0) ? "lid" : b.h < 4.2 && b.s === "out" ? "stub" : b.s === "out" || b.s === "chime" ? "st" + STAVE_GROUP(b.th) : "inside";      if (b.s === "out" && hoop >= 0) {        let lv = b.d > 0.8 ? 3 : b.d > 0.4 ? 2 : b.d > 0 ? 1 : 0;        const [a, c] = HOOPS[hoop];        if (b.h > c - 0.55 && lv > 0) lv = Math.min(4, lv + 1);             // the hoop's upper edge catches light        else if (b.h < a + 0.5) lv = Math.max(0, lv - 1);        const rivet = Math.abs(b.h - (a + c) / 2) < 0.5 && Math.abs(((b.th / TAU) * 7 + 20.5) % 1 - 0.5) < 0.07;        out[i] = { key: rivet ? "n4" : IRON[lv], part: "hoops", piece, lv, m: "iron", hoopIdx: hoop };        continue;      }      if (b.s === "out" || b.s === "cut") {        let lv = b.d > 0.9 ? 4 : b.d > 0.55 ? 3 : b.d > 0.2 ? 2 : b.d > -0.15 ? 1 : 0;        if (lv === 4 && !(b.h > 5 && b.h < 12)) lv = 3;        const k = stave(b);        if (b.s === "cut" || (cut && (!up || up.s === "in" || up.s === "floor"))) { out[i] = { key: b.x < 2 ? "w3" : "w2", part: "staves", piece, lv: 3, m: "wood" }; continue; }        if (stave(rt) >= 0 && stave(rt) !== k && b.x < 5.5) lv = Math.max(0, Math.min(lv, 2) - 1);   // stave seam        if (b.h < 1 && lv > 0) lv -= 1;        out[i] = { key: WOOD[lv], part: "staves", piece, lv, m: "wood" };        continue;      }      if (b.s === "chime") { out[i] = { key: b.x < 1 ? "w4" : "w3", part: "staves", piece, lv: 4, m: "wood" }; continue; }      if (b.s === "lid") {        // three boards across x, a dark ring in the chime's shadow, a bung on the right board        const r = Math.hypot(b.x, b.z), edge = r > BR(BLID) - BWALL - 0.9;        const k = b.x < -2.3 ? 0 : b.x < 2.3 ? 1 : 2;        let lv = edge && b.z < 1 ? 1 : b.x < -2.3 ? 3 : 2;        const kr = rt && rt.s === "lid" ? (rt.x < -2.3 ? 0 : rt.x < 2.3 ? 1 : 2) : k;        if (kr !== k) lv = 1;        if (k === 0 && !edge && up && up.s === "chime") lv = 3;        const bung = Math.hypot(b.x - 3.7, b.z + 0.6) < 0.95;        out[i] = { key: bung ? "w0" : WOOD[lv], part: "lid", piece, lv, m: "wood" };        continue;      }      out[i] = { key: b.s === "in" && b.x > 0.5 && b.z < 0 ? "w1" : "w0", part: "inside", piece: cut ? "base" : piece, lv: 0, m: "dark" };    }    return out;  },};// ---- compositing ---------------------------------------------------------------------------------------------function markOcc(occ, idx) {  occ[idx] = 1;  const x = idx % W, y = (idx - x) / W;  for (const [nx, ny] of [[x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]]) if (nx >= 0 && ny >= 0 && nx < W && ny < H) occ[ny * W + nx] = 1;}function emitLayer(g, occ, name, pix, detached) {  const seam = [];  for (const idx of pix.keys()) {    const x = idx % W, y = (idx - x) / W;    for (const [nx, ny] of [[x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]]) {      if (nx < 0 || ny < 0 || nx >= W || ny >= H) continue;      const k = ny * W + nx;      if (!pix.has(k) && occ[k]) seam.push(k);    }  }  for (const k of seam) pix.set(k, "ink");  let x0 = W, x1 = -1, y0 = H, y1 = -1;  for (const idx of pix.keys()) { const x = idx % W, y = (idx - x) / W; x0 = Math.min(x0, x); x1 = Math.max(x1, x); y0 = Math.min(y0, y); y1 = Math.max(y1, y); }  if (x1 < 0) return;  const body = () => g.outlined("ink", () => g.field({ x: [x0, x1], y: [y0, y1] }, (x, y) => pix.get(y * W + x) ?? null));  if (detached) g.detached(name, body); else g.part(name, body);  for (const idx of pix.keys()) markOcc(occ, idx);}function drawBody(g, occ, buf, over, only) {  let x0 = W, x1 = -1, y0 = H, y1 = -1;  const use = (b) => b && (!only || only(b));  for (let i = 0; i < W * H; i++) if (use(buf[i])) { const x = i % W, y = (i - x) / W; x0 = Math.min(x0, x); x1 = Math.max(x1, x); y0 = Math.min(y0, y); y1 = Math.max(y1, y); }  if (x1 < 0) return;  const parts = [];  for (const b of buf) if (use(b) && !parts.includes(b.part)) parts.push(b.part);  g.outlined("ink", () => {    for (const p of parts) g.part(p, () => g.field({ x: [x0, x1], y: [y0, y1] }, (x, y) => {      const i = y * W + x, b = buf[i];      return use(b) && b.part === p ? (over && over.has(i) ? over.get(i) : b.key) : null;    }));  });  for (let i = 0; i < W * H; i++) if (use(buf[i])) markOcc(occ, i);}// ---- pieces: the intact prop's pixels grouped by board / stave group ------------------------------------------function piecesOf(buf) {  const groups = new Map();  for (let i = 0; i < W * H; i++) {    const b = buf[i]; if (!b || b.piece === "inside" || b.piece === "base" || b.piece === "stub") continue;    if (!groups.has(b.piece)) groups.set(b.piece, []);    groups.get(b.piece).push([i % W, Math.floor(i / W), b]);  }  // close gaps inside each row of a board (the brace covered a strip of both infill planks)  for (const [id, px] of groups) {    const rows = new Map();    for (const e of px) { if (!rows.has(e[1])) rows.set(e[1], []); rows.get(e[1]).push(e); }    for (const [y, r] of rows) {      r.sort((a, b) => a[0] - b[0]);      for (let j = 1; j < r.length; j++) for (let x = r[j - 1][0] + 1; x < r[j][0]; x++) px.push([x, y, r[j - 1][2]]);    }  }  const out = {};  for (const [id, px] of groups) {    let cx = 0, cy = 0;    for (const [x, y] of px) { cx += x + 0.5; cy += y + 0.5; }    cx /= px.length; cy /= px.length;    out[id] = { px, cx, cy, m: new Map(px.map(([x, y, b]) => [`${x},${y}`, b])) };  }  return out;}function chunkKey(b, src, x, y) {  // a loose board on the floor: flat mid tone, lit top/left edge, dark lower/right edge (rivets keep their spark)  const has = (dx, dy) => src.has((y + dy) * W + (x + dx));  if (b.key === "n4") return b.key;  const iron = b.m === "iron", ramp = iron ? IRON : WOOD;  let lv = iron ? Math.max(1, Math.min(2, b.lv)) : Math.max(2, Math.min(3, b.lv));  if (!has(0, -1) || !has(-1, 0)) lv = Math.min(iron ? 3 : 4, lv + 1);  else if (!has(0, 1) || !has(1, 0)) lv = Math.max(0, lv - 1);  return ramp[lv];}function piecePixels(p, tx, ty, deg, sy, relit) {  const a = (deg * Math.PI) / 180, c = Math.cos(a), sn = Math.sin(a);  const src = new Map();  const r = 14, bx = Math.round(tx), by = Math.round(ty);  for (let y = by - r; y <= by + r; y++) for (let x = bx - r; x <= bx + r; x++) {    if (x < 0 || y < 0 || x >= W || y >= H) continue;    const dx = x + 0.5 - tx, dy = (y + 0.5 - ty) / sy;    const lx = dx * c + dy * sn, ly = -dx * sn + dy * c;    const b = p.m.get(`${Math.floor(lx + p.cx)},${Math.floor(ly + p.cy)}`);    if (b) src.set(y * W + x, b);  }  const pix = new Map();  for (const [k, b] of src) { const x = k % W, y = (k - x) / W; pix.set(k, relit ? chunkKey(b, src, x, y) : b.key); }  return pix;}// ---- effects ----------------------------------------------------------------------------------------------------function star(g, x, y, size) {  g.detached("glint", () => {    if (size === 0) { g.pixel(x, y, "n5"); return; }    g.pixel(x, y, "n5");    for (const [dx, dy] of [[1, 0], [-1, 0], [0, 1], [0, -1]]) g.pixel(x + dx, y + dy, "n4");  });}function dust(g, f) {  // two soft dust clouds roll out from the foot: each is three round clumps, a small n4 core in a checker of n3,  // drifting outward and up, thinning to a sparse n2 dither and gone  const k = f - 1;  if (k < 0 || k > 4) return;  const CLUMPS = [[0, 0, 2.0, 0], [-2.6, 0.7, 1.5, 1], [2.3, -1.0, 1.4, 1]];   // outward, down, radius, dither parity  g.detached("dust", () => {    const seen = new Set();    for (const s of [-1, 1]) for (const [ox, oy, r0, par] of CLUMPS) {      const r = r0 + k * 0.4, cx = CX + s * (11.5 + k * 1.7 + ox), cy = GROUND - 1.2 - k * 0.8 + oy;      for (let py = Math.floor(cy - r - 1); py <= cy + r + 1; py++) for (let px = Math.floor(cx - r - 1); px <= cx + r + 1; px++) {        const d = Math.hypot(px + 0.5 - cx, (py + 0.5 - cy) * 1.1) / r;        if (d > 1 || px < 0 || px >= W || py < 0 || py >= H || seen.has(py * W + px)) continue;        const on = ((px + py + par) & 1) === 0;        let key = null;        if (k === 0) key = d < 0.5 ? "n4" : on ? "n3" : null;        else if (k === 1) key = d < 0.35 ? "n4" : on ? (d < 0.7 ? "n3" : "n2") : null;        else if (k === 2) key = on ? (d < 0.55 ? "n3" : "n2") : null;        else if (k === 3) key = on && (px + 2 * py) % 3 !== 0 ? "n2" : null;        else key = on && (px + 2 * py) % 4 === 0 ? "n2" : null;        if (key) { seen.add(py * W + px); g.pixel(px, py, key); }      }    }  });}// splinters: sticks flung from the impact and from every board that bursts (crate lid boards, brace)const SPLINTERS = [[-1, -0.9, 1], [1, -1.1, 1], [-0.6, -1.5, 0], [0.8, -0.6, 0], [0.2, -1.7, 1]];function splinters(g, s, f) {  const k = f - 1;  if (k < 0 || k > 3) return;  const S = SHAPES[s], P = piecesFor(s);  const origins = [[CX, S.cy, 0]];  for (const id of Object.keys(S.land)) if (S.land[id][7]) origins.push([P[id].cx, P[id].cy, origins.length]);  g.detached("splinters", () => {    for (const [ox, oy, o] of origins) SPLINTERS.forEach(([vx, vy, long], i) => {      if (o > 0 && (i + o) % 2 === 1) return;                  // fewer from each burst board      const tt = k + 1, sp = o > 0 ? 2.6 : 4.5;      const x = Math.round(ox + vx * sp * tt + (o ? (o - 2) * 0.6 * tt : 0)), y = Math.round(oy + vy * sp * tt + 0.9 * tt * tt);      if (x < 0 || x >= W || y < 0 || y >= H) return;      const dx = vx > 0 ? 1 : -1, steep = Math.abs(vy) > 1.2;      g.pixel(x, y, (i + o) % 2 ? "w4" : "w3");      if (long && k < 3) g.pixel(x - (steep ? 0 : dx), y + (steep ? 1 : 0), "w2");      if (k < 2 && o > 0) g.pixel(x - (steep ? 0 : dx) * 2, y + (steep ? 2 : 0), "w1");    });  });}function motes(g, t, pts) {  g.detached("motes", () => {    pts.forEach(([x0, y0, ph], i) => {      const p = (t + ph) % 1;      if (p > 0.75) return;      const x = x0 + Math.round(Math.sin(TAU * (p + i * 0.3)) * 1), y = y0 + Math.round(p * 5);      g.pixel(x, y, p < 0.4 ? "n4" : "n3");    });  });}// ---- per-shape setup: rest pose, hit keys, landing table ------------------------------------------------------const REST = { sx: 1, sy: 1, ang: 0, piv: 0, hop: 0, dx: 0 };const HIT_KEYS = [  // sx, sy, ang(deg), pivot side, dx  [1.08, 0.9, 0, 0, 0],  [0.96, 1.05, 7, 1, 1],  [1, 1, -5, -1, 0],  [1, 1, 2.5, 1, 0],  [1.01, 0.99, -1, -1, 0],  [1, 1, 0, 0, 0],];// landing: piece -> [x, y, spin, flat (y scale at rest), landing frame, peak, layer (draw order in the pile)]const SHAPES = {  crate: {    model: CRATE, pivot: CW, rock: 0.7, shadow: 11, shadowBroken: 15, cy: 18,    land: {      postR: [27, 21, 26, 1, 6, 2, 0],       // leans on the heap at the right, behind it      railT: [15, 18, 6, 0.8, 7, 3, 0],      postL: [4, 24, 10, 0.6, 5, 2, 1],      plankT: [11, 24, -22, 0.8, 5, 2, 2],      plankB: [21, 25, 20, 0.8, 6, 3, 3],    // crosses over plankT      railB: [15, 30, -4, 0.7, 3, 0, 4],      // these burst into splinters instead of landing      topL: [10, 14, 0, 1, 9, 2, 9, true],      topR: [22, 14, 0, 1, 9, 2, 9, true],      brace: [16, 20, 0, 1, 9, 2, 9, true],    },    teeter: { piece: "plankB", px: 16, py: 23 },    motes: [[9, 16, 0], [23, 15, 0.5]],  },  barrel: {    model: BARREL, pivot: 6.3, rock: 1, shadow: 10, shadowBroken: 14, cy: 18,    land: {      lid: [7, 17, -8, 1, 7, 6, 0],          // lid disc, flat on the floor behind-left      st2: [24, 17, 80, 0.6, 6, 4, 0],       // widest stave group lying behind-right      st4: [27, 22, 18, 1, 6, 3, 0],         // leans on the stump at the right      st0: [6, 27, -35, 0.7, 5, 2, 2],      st3: [22, 30, 100, 0.5, 5, 2, 2],      st1: [10, 16, 0, 1, 9, 2, 9, true],    // bursts into splinters    },    teeter: { piece: "st4", px: 28, py: 27 },    motes: [[10, 16, 0.2], [22, 17, 0.7]],  },};const CACHE = {};function cached(key, fn) { return CACHE[key] || (CACHE[key] = fn()); }const intact = (s) => cached(s + ":intact", () => cast(SHAPES[s].model, REST, false));const baseOf = (s) => cached(s + ":base", () => (s === "barrel" ? cast(BARREL, REST, true) : null));const piecesFor = (s) => cached(s + ":pieces", () => piecesOf(intact(s)));function hitPose(s, f) {  if (f === N_HIT - 1) return intact(s);  const [sx, sy, deg, side, dx] = HIT_KEYS[f];  return cached(s + ":hit" + f, () => cast(SHAPES[s].model, { sx, sy, ang: (deg * SHAPES[s].rock * Math.PI) / 180, piv: side * SHAPES[s].pivot, hop: 0, dx }, false));}// crack frame: board seams go inkfunction crackOver(s) {  return cached(s + ":cracks", () => {    const buf = cast(SHAPES[s].model, { sx: 1.06, sy: 0.93, ang: 0, piv: 0, hop: 0, dx: 0 }, false);    const m = new Map();    for (let i = 0; i < W * H; i++) {      const b = buf[i]; if (!b || b.piece === "inside") continue;      const r = buf[i + 1], d = buf[i + W];      if ((r && r.piece !== b.piece && r.piece !== "inside") || (d && d.piece !== b.piece && d.piece !== "inside")) m.set(i, b.m === "iron" ? "n1" : "w0");    }    return { buf, m };  });}function pieceState(s, id, f) {  const p = piecesFor(s)[id], L = SHAPES[s].land[id];  const [rx, ry, spin, flat, lf, peak] = L;  if (f <= 0) return { x: p.cx, y: p.cy, a: 0, sy: 1, relit: false };  const u = Math.min(1, (f - 1) / (lf - 1)), e = 1 - (1 - u) * (1 - u);  const ox = p.cx - CX, oy = p.cy - SHAPES[s].cy, ol = Math.hypot(ox, oy) || 1;  const x0 = p.cx + (ox / ol) * 1.5, y0 = p.cy + (oy / ol) * 1.2;  let x = x0 + (rx - x0) * e, y = y0 + (ry - y0) * u - peak * 4 * u * (1 - u);  if (f === lf + 1 && peak > 0) y -= 1;  return { x, y, a: spin * e, sy: 1 + (flat - 1) * u, relit: f > 1 };}function drawPile(g, occ, s, f, t) {  const S = SHAPES[s], ids = Object.keys(S.land).filter((id) => !(S.land[id][7] && (f === null || f >= 2)));  const base = baseOf(s);  const st = (id) => {    if (f === null) {      const [x, y, a, sy] = S.land[id];      let ang = a;      if (id === S.teeter.piece) ang += 4 * Math.sin(TAU * t);           // the top board rocks on the pile      return { x, y, a: ang, sy, relit: true };    }    return pieceState(s, id, f);  };  // pieces that have landed are layered as a pile; the rest fly in front  const landed = (id) => f === null || f >= S.land[id][4];  const order = ids.slice().sort((a, b) => {    const la = landed(a), lb = landed(b);    if (la !== lb) return la ? -1 : 1;    return la ? S.land[a][6] - S.land[b][6] || S.land[a][1] - S.land[b][1] : st(a).y - st(b).y;  });  if (base) {    for (const id of order) if (landed(id) && S.land[id][6] === 0) { const q = st(id); emitLayer(g, occ, id, piecePixels(piecesFor(s)[id], q.x, q.y, q.a, q.sy, q.relit), true); }    drawBody(g, occ, base);  }  for (const id of order) {    if (base && landed(id) && S.land[id][6] === 0) continue;    const q = st(id);    emitLayer(g, occ, id, piecePixels(piecesFor(s)[id], q.x, q.y, q.a, q.sy, q.relit), true);  }}// idle glint: crate — a star blinks on the top-left iron plate; barrel — a glint slides along the upper hoopfunction idleOver(s, f) {  const buf = intact(s), over = new Map();  if (s === "crate") return { over, star: f === 3 ? [7, 11, 1] : f === 2 || f === 4 ? [7, 11, 0] : null };  const hoopTop = [];  for (let i = 0; i < W * H; i++) { const b = buf[i]; if (b && b.hoopIdx === 1 && b.lv >= 3) hoopTop.push(i); }  hoopTop.sort((a, b) => (a % W) - (b % W));  const path = [null, 0, 0.2, 0.4, 0.6, null, null, null][f];  if (path !== null && hoopTop.length) {    const i = hoopTop[Math.round(path * (hoopTop.length - 1))];    over.set(i, "n5"); if (buf[i + 1] && buf[i + 1].hoopIdx === 1) over.set(i + 1, "n4");  }  return { over, star: null };}const Breakable = sprite(pal, (g, t, mode, s) => {  const S = SHAPES[s], occ = new Uint8Array(W * H);  const N = mode === "idle" ? N_IDLE : mode === "hit" ? N_HIT : mode === "break" ? N_BREAK : N_BROKEN;  const f = mode === "idle" || mode === "broken" ? Math.round(t * N) % N : Math.min(N - 1, Math.round(t * N));  const spread = mode === "broken" || (mode === "break" && f >= 4);  contactShadow(g, CX, GROUND, spread ? S.shadowBroken : S.shadow, 2);  if (mode === "idle") {    const { over, star: st } = idleOver(s, f);    drawBody(g, occ, intact(s), over);    if (st) star(g, st[0], st[1], st[2]);    return;  }  if (mode === "hit") {    drawBody(g, occ, hitPose(s, f));    if (f === 0) star(g, 29, 15, 1);    if (f === 1) g.detached("chips", () => { g.pixel(29, 12, "w3"); g.pixel(30, 16, "w4"); g.pixel(28, 10, "w2"); });    return;  }  if (mode === "break") {    if (f === 0) { const c = crackOver(s); drawBody(g, occ, c.buf, c.m); star(g, 29, 15, 1); return; }    if (f === N_BREAK - 1) { drawPile(g, occ, s, null, 0); motes(g, 0, S.motes); return; }   // == broken frame 0    drawPile(g, occ, s, f, 0);    dust(g, f);    splinters(g, s, f);    return;  }  drawPile(g, occ, s, null, t);  motes(g, t, S.motes);});const V = [];for (const s of ["crate", "barrel"]) {  const suf = s === "crate" ? "" : "-barrel";  V.push({ name: "idle" + suf, args: ["idle", s], animate: { fps: 10, duration: N_IDLE / 10, loop: true } });  V.push({ name: "hit" + suf, args: ["hit", s], animate: { fps: 10, duration: N_HIT / 10, loop: false } });  V.push({ name: "break" + suf, args: ["break", s], animate: { fps: 10, duration: N_BREAK / 10, loop: false } });  V.push({ name: "broken" + suf, args: ["broken", s], animate: { fps: 10, duration: N_BROKEN / 10, loop: true } });}submit(Breakable, {  size: [W, H], origin: "top-left", kind: "icon", scale: 1,  anchor: { x: CX, y: GROUND },  variants: V,});

These excerpts omit the boilerplate prepended by the asset pack build script: a single-line runtime header, the shared palette, and common helper utilities (contactShadow, litIndex, flame, hash, chk, TAU). The displayed line numbers match the original source files. Each program was authored by an AI coding agent and adjusted after visual inspection of the rendered frames.

Have your agent write programs like this.

Tessarune gives it the drawing API reference, 25 production manuals and a renderer to check its work against.