← Basics3D assetfogon/baul-de-viaje
Baúl de viaje
Drag to turn it// «Baúl de viaje» · gpt-6-sol (medium)
// Sea trunk («Baúl de viaje»).
const tealDark = "#123f43";
const teal = "#17666a";
const tealLight = "#27878a";
const tealBright = "#389b98";
const goldDark = "#79582d";
const gold = "#b78c49";
const goldLight = "#e4c479";
function roofHeight(y) {
const d = Math.abs(y - 23.5) / 12;
return Math.round(35 - 9 * d * d);
}
// An irregular patch of pale sand beneath the trunk.
for (let x = 3; x <= 46; x++) {
for (let y = 5; y <= 39; y++) {
const edge = ((x - 24) / 22) ** 2 + ((y - 22) / 17) ** 2;
if (edge < 0.88 + (rand() - 0.5) * 0.16) {
set(x, y, 0, rand() < 0.18 ? "#c6b493" : "#e0d0ac");
if (edge < 0.72 && rand() > 0.17)
set(x, y, 1, rand() < 0.2 ? "#f2e2bd" : "#ddcba4");
if (edge < 0.48 && rand() < 0.34)
set(x, y, 2, "#eddbb5");
}
}
}
// Solid, dark timber trunk. Its front faces the viewer at -y.
box(8, 12, 5, 41, 35, 23, tealDark);
for (let x = 9; x <= 40; x++) {
for (let y = 13; y <= 34; y++) {
for (let z = 7; z <= 22; z++) {
let c = z > 16 ? teal : "#17575a";
if (rand() < 0.055) c = tealLight;
set(x, y, z, c);
}
}
}
// Long recessed panels on the visible side.
for (let x = 10; x <= 39; x++) {
for (let z = 8; z <= 21; z++) {
const c = rand() < 0.09 ? "#24777a" : "#19585c";
set(x, 11, z, c);
if (z === 10 || z === 19) set(x, 11, z, "#123f43");
}
}
for (const x of [9, 23, 26, 40]) {
box(x, 10, 7, x + 1, 11, 22, "#174b4f");
box(x, 9, 9, x, 9, 20, "#287478");
}
box(10, 9, 6, 40, 11, 7, "#244d48");
box(10, 9, 7, 40, 9, 7, goldDark);
box(10, 11, 22, 40, 11, 23, "#102f34");
// Left end, framed around a large carrying handle.
box(7, 14, 8, 7, 33, 22, "#195257");
for (let y = 15; y <= 32; y++) {
for (let z = 10; z <= 20; z++)
set(6, y, z, rand() < 0.08 ? tealLight : "#20686b");
}
for (const y of [14, 33]) box(6, y, 7, 7, y, 23, "#123e43");
box(6, 15, 8, 6, 32, 9, "#123e43");
box(6, 15, 21, 6, 32, 22, "#123e43");
// Rounded, plank-built lid.
for (let y = 12; y <= 35; y++) {
const h = roofHeight(y);
for (let x = 8; x <= 41; x++) {
for (let z = 24; z <= h; z++) {
let c = "#176369";
if (z === h) c = rand() < 0.13 ? tealBright : tealLight;
if (z === h - 1) c = "#237e82";
if (y % 4 === 0 && z >= h - 1) c = "#15575c";
set(x, y, z, c);
}
}
}
for (const y of [15, 19, 23, 27, 31]) {
const h = roofHeight(y);
for (let x = 9; x <= 40; x++)
set(x, y, h + 1, rand() < 0.13 ? tealBright : "#1b777c");
}
// Heavy overhanging lid rim.
box(7, 11, 23, 42, 36, 24, "#123a3d");
box(8, 10, 23, 41, 11, 25, "#1d6667");
box(8, 10, 23, 41, 10, 23, goldDark);
box(8, 10, 25, 41, 10, 25, tealLight);
box(6, 13, 23, 7, 34, 25, "#145255");
for (const x of [8, 15, 24, 34, 41])
box(x, 10, 23, x + 1, 10, 24, gold);
// Two brass straps follow the curve of the lid from front to back.
for (const sx of [15, 35]) {
for (let y = 11; y <= 36; y++) {
const h = roofHeight(Math.max(12, Math.min(35, y)));
for (let dx = -1; dx <= 2; dx++) {
const x = sx + dx;
set(x, y, h + 1, dx === -1 || dx === 2 ? goldDark : gold);
if (dx === 0 && y % 5 === 0) set(x, y, h + 2, goldLight);
}
}
box(sx - 1, 9, 21, sx + 2, 10, 25, goldDark);
box(sx, 9, 22, sx + 1, 9, 25, goldLight);
set(sx, 8, 23, "#f3d790");
}
// Riveted corner brackets and hinge-like details.
for (const x of [9, 40]) {
box(x, 9, 7, x + 1, 10, 20, goldDark);
for (const z of [9, 15, 19])
set(x, 8, z, goldLight);
}
for (const x of [12, 21, 30, 39]) {
set(x, 9, 21, gold);
set(x, 8, 21, goldLight);
set(x, 9, 8, gold);
}
for (const y of [15, 32]) {
box(5, y, 18, 6, y + 2, 20, goldDark);
set(4, y + 1, 19, goldLight);
}
// U-shaped brass handle on the left end.
for (const y of [18, 29]) {
box(4, y, 13, 5, y + 1, 19, goldDark);
box(3, y, 14, 3, y + 1, 18, gold);
set(3, y, 19, goldLight);
}
box(3, 19, 12, 3, 29, 13, goldDark);
box(2, 19, 13, 2, 28, 13, goldLight);
set(2, 18, 14, goldLight);
set(2, 29, 14, goldLight);
// Prominent raised lock and stylized anchor on the front.
box(24, 7, 19, 29, 9, 23, goldDark);
box(25, 6, 20, 28, 7, 23, goldLight);
box(26, 5, 21, 27, 5, 22, "#f2d58d");
set(26, 5, 20, "#79582d");
box(26, 7, 10, 27, 8, 20, gold);
box(26, 6, 12, 26, 6, 19, goldLight);
box(20, 7, 12, 33, 8, 13, goldDark);
box(21, 6, 13, 32, 6, 13, goldLight);
box(19, 6, 13, 20, 8, 16, gold);
box(33, 6, 13, 34, 8, 16, gold);
for (let i = 0; i < 6; i++) {
set(20 + i, 7, 12 - Math.floor(i / 3), gold);
set(33 - i, 7, 12 - Math.floor(i / 3), gold);
}
box(24, 6, 9, 29, 7, 10, gold);
box(25, 5, 10, 28, 5, 10, goldLight);
for (const x of [19, 34]) set(x, 5, 15, goldLight);
// Small latch plates beside the central ornament.
for (const x of [12, 38]) {
box(x, 8, 14, x + 2, 9, 18, goldDark);
set(x + 1, 7, 17, goldLight);
set(x + 1, 7, 15, "#d5ad61");
}
// Top-mounted brass travel badge.
box(23, 21, 36, 30, 27, 36, goldDark);
box(24, 22, 37, 29, 26, 37, gold);
box(25, 23, 38, 28, 25, 38, goldLight);
for (const x of [24, 29])
for (const y of [22, 26]) set(x, y, 38, "#f0d891");
box(26, 20, 36, 27, 28, 36, goldLight);
// Shells, sea glass and little bits of coral in the sand.
for (const [x, y, c] of [
[12, 8, "#f6e8cb"], [14, 7, "#e8d7b9"],
[22, 6, "#e7aca5"], [24, 7, "#f5ddcf"],
[31, 7, "#72a89a"], [33, 6, "#9cc2ad"],
[38, 9, "#e4d8b9"]
]) {
box(x, y, 2, x + 1, y + 1, 2, c);
set(x, y, 3, c);
}
line(40, 8, 2, 44, 7, 3, 0, "#c77d5d");
line(42, 6, 2, 42, 11, 3, 0, "#d38c68");
line(41, 8, 2, 44, 10, 3, 0, "#e2a078");
set(43, 9, 4, "#eab08b");
// A small sprig of seaweed beside the handle.
for (const [x, y, z] of [
[5, 16, 2], [5, 16, 3], [4, 16, 4], [4, 16, 5],
[3, 15, 5], [3, 15, 6], [6, 17, 4], [7, 17, 5],
[6, 18, 6], [5, 16, 7]
]) set(x, y, z, rand() < 0.35 ? "#468d70" : "#327b62");import { draw } from "./assets/voxel";
import { baulDeViaje } from "./assets/baul-de-viaje";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, baulDeViaje, 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 baul-de-viaje
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["baul-de-viaje"] })
# It lands in client/assets/baul-de-viaje.ts
# https://fogon.page/object/baul-de-viaje