← BásicoObjeto 3Dfogon/mecedora
Mecedora
Arrastrá para girarlo// «Mecedora» · gpt-6-sol (medium)
// Rocking chair («Mecedora»).
// Rocking chair, with the back facing away from the viewer (-y is front).
const wood = {
dark: "#74431f",
shade: "#98602e",
mid: "#b87938",
warm: "#cb8c45",
light: "#dda458",
edge: "#edbb70"
};
function timber(x0, y0, z0, x1, y1, z1, base = "mid") {
for (let x = x0; x <= x1; x++)
for (let y = y0; y <= y1; y++)
for (let z = z0; z <= z1; z++) {
let c = wood[base];
if (z === z1) c = wood.light;
else if (y === y0) c = wood.warm;
else if (x === x1) c = wood.shade;
if (rand() < 0.055) c = z === z1 ? wood.edge : wood.shade;
set(x, y, z, c);
}
}
// Two long, upward-curving wooden runners.
function runnerHeight(y) {
if (y < 8) return Math.round((8 - y) * 0.8);
if (y < 14) return Math.round((14 - y) * 0.22);
if (y > 40) return Math.round((y - 40) * 0.9);
if (y > 34) return Math.round((y - 34) * 0.17);
return 0;
}
for (const x0 of [9, 35]) {
for (let y = 3; y <= 44; y++) {
const h = runnerHeight(y);
timber(x0, y, h, x0 + 5, y, h + 2, "mid");
if (y % 7 === 2 && y > 5 && y < 42)
timber(x0 + 1, y, h + 3, x0 + 4, y, h + 3, "light");
}
// Dark, squared-off grain at the curled tips.
for (const y of [3, 4, 43, 44]) {
const h = runnerHeight(y);
timber(x0 + 1, y, h, x0 + 4, y, h + 1, "shade");
}
}
// Legs are seated directly on the runners.
for (const x of [11, 37]) {
for (const y of [15, 33]) {
timber(x - 2, y - 2, 4, x + 2, y + 2, 20, "mid");
timber(x - 2, y - 2, 6, x + 2, y + 2, 7, "shade");
timber(x - 2, y - 2, 12, x + 2, y + 2, 13, "warm");
}
}
// Low stretchers leave open space beneath the seat.
for (const x of [11, 37])
timber(x - 1, 17, 10, x + 1, 32, 12, "warm");
timber(13, 32, 10, 35, 34, 12, "warm");
timber(13, 14, 11, 35, 16, 13, "shade");
// Square seat frame, with an especially visible front apron.
timber(11, 14, 18, 39, 17, 21, "mid");
timber(11, 31, 18, 39, 34, 21, "mid");
for (const x of [11, 37])
timber(x - 2, 17, 18, x + 2, 31, 21, "mid");
timber(14, 13, 16, 36, 15, 18, "shade");
timber(14, 14, 19, 36, 15, 20, "light");
// Thin upholstered cushion, set inside the wooden seat rails.
box(15, 18, 21, 35, 30, 22, "#619788");
box(16, 18, 23, 34, 29, 23, "#a4cbb7");
box(16, 17, 21, 34, 18, 22, "#79ad9b");
for (let x = 18; x <= 32; x += 5)
for (let y = 21; y <= 27; y += 5)
set(x, y, 24, "#bbd7c5");
for (let y = 19; y <= 29; y += 4) {
set(16, y, 24, "#b7d6c3");
set(34, y, 24, "#83b6a3");
}
// Rear posts rise above the arms to carry the high, open spindle back.
for (const x of [11, 37]) {
timber(x - 2, 31, 19, x + 2, 35, 40, "mid");
timber(x - 2, 32, 38, x + 2, 35, 41, "warm");
timber(x - 1, 31, 28, x + 1, 32, 34, "shade");
}
// Bottom rail, top rail, and a narrow raised cap.
timber(13, 32, 24, 35, 34, 26, "mid");
timber(13, 32, 37, 35, 34, 40, "mid");
timber(15, 33, 41, 34, 34, 41, "light");
for (const x of [17, 23, 29])
timber(x, 32, 41, x + 3, 34, 42, "warm");
// Turned spindles, visibly separated by open gaps.
for (const x of [17, 21, 25, 29, 33]) {
timber(x, 33, 26, x + 1, 34, 29, "shade");
timber(x - 1, 33, 29, x + 2, 34, 30, "warm");
timber(x, 33, 31, x + 1, 34, 34, "light");
timber(x - 1, 33, 34, x + 2, 34, 35, "mid");
timber(x, 33, 36, x + 1, 34, 37, "shade");
set(x, 32, 32, wood.edge);
}
// Upright arm supports and broad, flat armrests.
for (const x of [11, 37]) {
timber(x - 2, 14, 20, x + 2, 17, 27, "mid");
timber(x - 2, 29, 21, x + 2, 32, 28, "mid");
timber(x - 3, 13, 27, x + 3, 33, 29, "warm");
timber(x - 3, 13, 30, x + 3, 30, 30, "light");
timber(x - 3, 12, 27, x + 3, 14, 29, "mid");
// A small darker joint just beneath the front of each arm.
timber(x - 2, 15, 24, x + 2, 16, 25, "shade");
}
// Little square pegs at the exposed frame joints.
for (const x of [11, 37]) {
for (const y of [15, 33]) {
set(x, y - 2, 14, wood.edge);
set(x + 2, y, 12, wood.dark);
}
}import { draw } from "./assets/voxel";
import { mecedora } from "./assets/mecedora";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, mecedora, 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 mecedora
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["mecedora"] })
# Queda en client/assets/mecedora.ts
# https://fogon.page/object/mecedora