← City3D assetfogon/shipping-container
Contenedor
Drag to turn it// «Contenedor» · propio
// A 20-foot steel shipping container, rust red, with corrugated sides, a darker frame, and double doors with vertical lock bars at the front.
// A 20-foot shipping container. Its length runs back (y); the doors are at the front (-y).
const RED = {
base: "#a8432e", light: "#b94d34", dark: "#8a3524", groove: "#6b281c", top: "#c05a40", frame: "#7c3023", frameTop: "#93392a",
rust: "#8a4a22", rust2: "#b56d35", casting: "#3d3f44", steel: "#c4c0b8", steelDark: "#85827c", seam: "#3f1811",
};
// A container L long, W wide (odd, so the doors meet in the middle) and H high, with a frame F thick. `put(u, v, w, color)`
// places a block u along its length (0 at the doors), v across and w up. The walls are corrugated: every third column
// is set back one block.
function container(put, L, W, H, F, C, bars) {
const mid = (W - 1) / 2;
const side = (u, w) => {
if (u % 3 === 0) return null;
if (w < 3 + (u % 5 === 0 ? 1 : 0) && rand() < 0.5) return C.dark; // grime near the ground
if (rand() < 0.035) return rand() < 0.5 ? C.rust : C.rust2;
return u % 3 === 1 ? C.light : C.base;
};
const door = (v, w) => {
if (v === mid) return C.seam;
if ((v === F || v === W - 1 - F) && (w === F + 1 || w === Math.floor(H / 2) || w === H - 2 - F)) return C.casting; // hinges
if (w === F || w === H - 1 - F) return C.dark;
return rand() < 0.03 ? C.rust : C.base;
};
for (let u = 0; u < L; u++)
for (let v = 0; v < W; v++)
for (let w = 0; w < H; w++) {
const du = Math.min(u, L - 1 - u), dv = Math.min(v, W - 1 - v), dw = Math.min(w, H - 1 - w);
const depth = Math.min(du, dv, dw);
if (depth > 1) continue; // hollow
const frame = (du < F && dv < F) || (dw < F && dv < F) || (dw < F && du < F);
let c;
if (du <= F && dv <= F && dw <= F) c = C.casting; // the corner blocks cranes grab
else if (frame) c = w >= H - F ? C.frameTop : C.frame;
else if (depth === 1) c = C.groove; // seen only through the grooves
else if (dw === 0) c = w === 0 ? C.frame : u % 3 === 0 ? null : rand() < 0.06 ? C.light : C.top;
else if (du === 0 && u === 0) c = door(v, w);
else if (du === 0) c = (v - F) % 3 === 0 ? null : (v - F) % 3 === 1 ? C.light : C.base;
else c = side(u, w);
if (c) put(u, v, w, c);
}
// Lock bars on the doors, with their brackets and handles.
const grip = Math.floor(H * 0.4);
for (const v of bars) {
for (let w = F; w <= H - 1 - F; w++) put(-1, v, w, w === F || w === H - 1 - F || w === Math.floor(H * 0.7) ? C.steelDark : C.steel);
}
put(-1, bars[0] + 1, grip, C.steelDark);
put(-1, bars[3] - 1, grip, C.steelDark);
if (bars[1] - bars[0] > 2) put(-1, bars[1] - 1, grip, C.steelDark);
// Rust running down from the roof rail.
for (let n = 0; n < 9; n++) {
const u = F + 1 + Math.floor(rand() * (L - 2 * F - 2));
if (u % 3 === 0) continue;
const v = rand() < 0.5 ? 0 : W - 1;
for (let k = 0; k < 2 + Math.floor(rand() * 3); k++) put(u, v, H - 1 - F - k, k ? C.rust : C.rust2);
}
}
const L = 42, W = 17, H = 19;
const X0 = 16, Y0 = 3;
container((u, v, w, c) => set(X0 + v, Y0 + u, w, c), L, W, H, 2, RED, [4, 6, 10, 12]);import { draw } from "./assets/voxel";
import { shippingContainer } from "./assets/shipping-container";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, shippingContainer, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: its longest side, in px
// angle: turn on the floor, in radians
// t: seconds; if it moves, that animates it# In a terminal, in the game's folder
fogon assets add shipping-container
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["shipping-container"] })
# It lands in client/assets/shipping-container.ts
# https://fogon.gg/object/shipping-container