← Medieval3D assetfogon/cofre-de-mazmorra
Cofre de mazmorra
Drag to turn it// «Cofre de mazmorra» · gpt-6-sol (medium)
// A heavy dungeon chest: dark weathered wood with thick black iron bands, iron corner caps and studs, a big iron lock with a skull shape, a few cobwebs and a little green moss on the lid.
// Heavy dungeon chest
const wood = ["#39271e", "#493023", "#563927", "#63442c"];
const iron = "#191c1d";
const ironEdge = "#303437";
const ironLight = "#555b5b";
function plankColor(z) {
const n = rand();
if (n < 0.08) return wood[0];
if (n > 0.91) return wood[3];
return wood[z > 13 ? 2 : 1];
}
// Four squat feet and a heavy base.
for (const x of [6, 36]) for (const y of [11, 32]) {
box(x, y, 0, x + 5, y + 5, 4, "#29231f");
box(x + 1, y, 0, x + 4, y + 1, 1, "#3d3430");
}
box(6, 11, 3, 41, 37, 18, wood[1]);
// Weathered plank faces, with subtly varied blocks.
for (let z = 4; z <= 17; z++) {
for (let x = 6; x <= 41; x++) {
set(x, 10, z, plankColor(z));
set(x, 38, z, wood[z > 12 ? 1 : 0]);
}
for (let y = 11; y <= 37; y++) {
set(5, y, z, plankColor(z));
set(42, y, z, wood[1]);
}
}
for (const z of [7, 11, 15]) {
box(6, 10, z, 41, 10, z, "#30231d");
box(5, 11, z, 5, 37, z, "#30231d");
}
for (const x of [17, 30]) {
box(x, 10, 5, x, 10, 15, "#35251d");
for (const z of [6, 12, 16]) set(x + 1, 9, z, "#8a714f");
}
// Iron-bound bottom, upper lip, and vertical straps.
for (const z of [3, 17]) {
box(5, 9, z, 42, 39, z + 1, iron);
box(7, 9, z + 1, 40, 9, z + 1, ironEdge);
}
for (const x of [10, 35]) {
box(x, 9, 4, x + 2, 10, 18, iron);
box(x, 38, 4, x + 2, 39, 18, iron);
box(x, 11, 4, x + 2, 37, 4, iron);
for (const z of [6, 11, 16]) {
set(x + 1, 8, z, ironLight);
set(x + 1, 39, z, "#464b4b");
}
}
// Thick corner caps, with prominent square-headed rivets.
for (const x of [5, 38]) for (const y of [9, 36]) {
for (const z of [4, 14]) box(x, y, z, x + 4, y + 3, z + 3, iron);
for (const z of [5, 16]) {
set(x + 2, y - (y === 9 ? 1 : 0), z, ironLight);
set(x + 2, y - (y === 9 ? 1 : 0), z + 1, ironEdge);
}
}
// The skull-shaped lock plate stays on the chest.
box(18, 8, 9, 30, 9, 18, iron);
box(20, 7, 10, 28, 8, 18, ironEdge);
box(21, 6, 13, 27, 7, 17, "#777d79");
box(22, 6, 18, 26, 7, 19, "#777d79");
box(20, 7, 14, 28, 7, 16, "#727975");
box(22, 6, 11, 26, 7, 13, "#737a75");
set(22, 5, 15, "#171b1c");
set(23, 5, 15, "#171b1c");
set(25, 5, 15, "#171b1c");
set(26, 5, 15, "#171b1c");
set(24, 5, 13, "#292f2d");
for (const x of [22, 24, 26]) set(x, 5, 11, "#b2b5a5");
for (const x of [19, 29]) for (const z of [11, 17])
set(x, 7, z, ironLight);
// Rear hinge knuckles, beneath the pivoting lid.
for (const x of [10, 22, 35]) {
box(x, 37, 18, x + 2, 40, 21, iron);
set(x + 1, 40, 20, ironLight);
}
part("lid", [24, 38, 19]);
function roof(y) {
return 25 + Math.floor(4 * (1 - Math.abs(y - 24.5) / 15));
}
// Broad, gently arched wooden lid.
for (let y = 10; y <= 39; y++) {
const top = roof(y);
for (let x = 5; x <= 42; x++) {
for (let z = 20; z <= top; z++) {
let c = z >= top - 1 ? "#62452e" : "#493024";
if (rand() < 0.11) c = z >= top - 1 ? "#745237" : "#38271f";
set(x, y, z, c);
}
}
}
// Visible plank seams and a stout iron rim.
for (const y of [16, 23, 31]) {
for (let x = 6; x <= 41; x++) set(x, y, roof(y), "#3b2c24");
}
box(5, 9, 19, 42, 40, 20, iron);
box(7, 9, 21, 40, 9, 21, ironEdge);
box(6, 10, 21, 6, 39, 21, ironEdge);
box(41, 10, 21, 41, 39, 21, ironEdge);
// Two massive bands arch from front to back over the lid.
for (const x of [10, 35]) {
for (let y = 9; y <= 40; y++) {
const top = roof(Math.max(10, Math.min(39, y)));
box(x, y, 20, x + 2, y, top + 1, iron);
if (y >= 10 && y <= 39) set(x, y, top + 1, ironEdge);
}
for (const y of [13, 21, 29, 37]) {
set(x + 1, y, roof(y) + 2, ironLight);
}
for (const z of [22, 25]) set(x + 1, 8, z, ironLight);
}
// Capped lid corners and a short hasp above the skull.
for (const x of [5, 38]) for (const y of [9, 36]) {
box(x, y, 20, x + 4, y + 3, 23, iron);
set(x + 2, y - (y === 9 ? 1 : 0), 22, ironLight);
}
box(22, 8, 20, 26, 9, 25, iron);
box(23, 7, 21, 25, 8, 24, ironEdge);
set(24, 6, 23, ironLight);
// Moss clings to a few of the upper wooden planks.
for (const patch of [
[15, 19, 5, 3], [28, 26, 5, 4], [18, 35, 4, 2],
[31, 15, 3, 2]
]) {
const [cx, cy, rx, ry] = patch;
for (let x = cx - rx; x <= cx + rx; x++) {
for (let y = cy - ry; y <= cy + ry; y++) {
const d = ((x - cx) / rx) ** 2 + ((y - cy) / ry) ** 2;
if (d < 1 && rand() > 0.26 && x !== 10 && x !== 11 &&
x !== 12 && x !== 35 && x !== 36 && x !== 37) {
set(x, y, roof(y) + 1, rand() > 0.65 ? "#70804a" : "#435b38");
}
}
}
}
// Delicate cobwebs in two sheltered corners.
const web = "#a5a69a";
for (const [ax, ay, az, dx] of [
[6, 8, 26, 1],
[41, 8, 26, -1]
]) {
line(ax, ay, az, ax + dx * 8, ay, az, 0, web);
line(ax, ay, az, ax, ay - 2, az - 7, 0, web);
for (let i = 2; i <= 7; i += 2)
line(ax + dx * i, ay, az,
ax, ay - Math.round(i / 4), az - i, 0, web);
line(ax + dx * 3, ay - 1, az - 3,
ax + dx * 7, ay, az - 2, 0, "#797f75");
}
animate("lid", { type: "swing", axis: "x", speed: 1, amplitude: 0.25 });import { draw } from "./assets/voxel";
import { cofreDeMazmorra } from "./assets/cofre-de-mazmorra";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, cofreDeMazmorra, 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 cofre-de-mazmorra
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["cofre-de-mazmorra"] })
# It lands in client/assets/cofre-de-mazmorra.ts
# https://fogon.page/object/cofre-de-mazmorra