← ArmasObjeto 3Dfogon/ammo-box
Caja de munición
Arrastrá para girarlo// «Caja de munición» · propio
// An olive green metal ammunition box with a hinged lid half open, a folding handle on top, a latch at the front, and rows of brass cartridges showing inside.
// An olive green metal ammunition box: the hinged lid half open, a folding handle on top, a latch at the front and
// rows of brass cartridges inside. The lid swings on its hinge at the back.
const olive = ["#3f4a24", "#4d5a2c", "#5a6934", "#68783d", "#778847"];
const steel = ["#55585a", "#74777a", "#96999b"];
const brass = ["#8f6a1f", "#b8892e", "#d3a43f", "#ebc45c"];
const copper = ["#9a5530", "#b86c3e", "#d08650"];
const clampi = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
const X0 = 8, X1 = 39, Y0 = 15, Y1 = 32, TOP = 19;
// The box: hollow, with a foot rim, a pressed groove round it and a paler band on the front.
for (let x = X0; x <= X1; x++)
for (let y = Y0; y <= Y1; y++)
for (let z = 0; z <= TOP; z++) {
const wall = x <= X0 + 1 || x >= X1 - 1 || y <= Y0 + 1 || y >= Y1 - 1;
if (!wall && z > 1) continue;
const outer = x === X0 || x === X1 || y === Y0 || y === Y1;
let tone = 2 + (z > 14 ? 1 : 0) - (z < 3 ? 1 : 0) + (x === X0 ? 1 : 0);
if (outer && (z === 5 || z === 13)) tone -= 2;
if (!outer) tone = 1;
if (z === TOP) tone = 4;
if (rand() < 0.05) tone--;
set(x, y, z, olive[clampi(tone, 0, 4)]);
}
box(X0 - 1, Y0 - 1, 0, X1 + 1, Y1 + 1, 0, olive[0]);
for (let x = X0 - 1; x <= X1 + 1; x++) for (let y = Y0 - 1; y <= Y1 + 1; y++) if (x < X0 || x > X1 || y < Y0 || y > Y1) set(x, y, 1, olive[1]);
box(11, Y0, 8, 20, Y0, 10, "#c9a93a");
box(11, Y0, 9, 20, Y0, 9, "#dcc050");
// Corner wear.
for (const [x, y] of [[X0, Y0], [X1, Y0], [X0, Y1]]) for (let z = 2; z <= TOP; z++) if (rand() < 0.35) set(x, y, z, steel[0]);
// The latch at the front: a steel plate, its loop and the catch.
box(22, Y0 - 1, 11, 25, Y0 - 1, 18, steel[1]);
box(22, Y0 - 1, 18, 25, Y0 - 1, 18, steel[2]);
box(23, Y0 - 2, 13, 24, Y0 - 2, 16, steel[0]);
set(22, Y0 - 1, 11, steel[0]);
set(25, Y0 - 1, 11, steel[0]);
// Carry loops at the ends.
for (const x of [X0 - 1, X1 + 1]) {
box(x, 21, 12, x, 26, 12, steel[0]);
box(x, 21, 13, x, 21, 15, steel[1]);
box(x, 26, 13, x, 26, 15, steel[1]);
}
// The cartridges: standing in rows, brass cases with copper bullets.
for (let x = X0 + 2; x <= X1 - 2; x++)
for (let y = Y0 + 2; y <= Y1 - 2; y++) {
const i = (x - X0 - 2) % 3, j = (y - Y0 - 2) % 3;
if (i === 2 || j === 2) {
for (let z = 2; z <= 11; z++) set(x, y, z, "#2a2412");
continue;
}
for (let z = 2; z <= 13; z++) set(x, y, z, brass[clampi(1 + (i === 0 && j === 0 ? 1 : 0) - (z < 6 ? 1 : 0), 0, 3)]);
set(x, y, 14, brass[i === 0 && j === 0 ? 3 : 2]);
set(x, y, 15, brass[i === 0 && j === 0 ? 3 : 2]);
set(x, y, 16, i === 1 && j === 0 ? copper[1] : brass[i === 0 && j === 0 ? 3 : i === 1 && j === 1 ? 1 : 2]);
}
// The hinges at the back.
for (const x of [12, 32]) box(x, Y1 + 1, TOP - 1, x + 3, Y1 + 1, TOP + 1, steel[0]);
// The lid: drawn open, turning on the hinge at the back.
part("lid", [24, Y1 + 0.5, TOP + 1]);
const OPEN = (40 * Math.PI) / 180, C = Math.cos(OPEN), S = Math.sin(OPEN);
const HY = Y1 + 0.5, HZ = TOP + 1;
// (d: how far from the hinge along the lid; h: how far above its plate)
function lid(x, d, h, c) {
set(x, HY - d * C + h * S, HZ + d * S + h * C, c);
}
const LEN = Y1 - Y0 + 2;
for (let x = X0 - 1; x <= X1 + 1; x++)
for (let d = 0; d <= LEN; d += 0.4)
for (let h = -3; h <= 1.4; h += 0.4) {
const plate = h >= 0;
const lip = d >= LEN - 1.2 || ((x === X0 - 1 || x === X1 + 1) && d >= 1.5);
if (!plate && !lip) continue;
let tone = plate ? 3 : 2;
if (plate && (x === 13 || x === 34)) tone = 1;
if (plate && h >= 0.8 && (d < 1 || d > LEN - 1)) tone = 4;
if (!plate && h < -2.2) tone = 1;
if (x === X0 - 1) tone++;
lid(x, d, h, olive[clampi(tone, 0, 4)]);
}
// The folding handle, lying flat on the lid, on two brackets.
for (let x = 16; x <= 31; x++)
for (let d = 7; d <= 12; d += 0.4) {
const ring = x <= 17 || x >= 30 || d < 8.2 || d > 10.9;
if (ring) for (let h = 1.6; h <= 2.6; h += 0.4) lid(x, d, h, x >= 20 && x <= 27 && d > 10.9 ? "#2b2c2e" : steel[h > 2 ? 2 : 1]);
}
for (const x of [18, 29]) for (let d = 6; d <= 7.4; d += 0.4) for (let h = 1.6; h <= 3; h += 0.4) lid(x, d, h, steel[0]);
// The catch the latch closes on.
for (let x = 22; x <= 25; x++) for (let h = -3; h <= 0; h += 0.4) lid(x, LEN + 0.6, h, steel[1]);
animate("lid", { type: "swing", axis: "x", speed: 1.5, amplitude: 0.3 });import { draw } from "./assets/voxel";
import { ammoBox } from "./assets/ammo-box";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, ammoBox, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: lo que mide en px su lado más largo
// angle: giro sobre el piso, en radianes
// t: segundos; si se mueve, se anima solo con eso# En una terminal, en la carpeta del juego
fogon assets add ammo-box
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["ammo-box"] })
# Queda en client/assets/ammo-box.ts
# https://fogon.gg/object/ammo-box