← BásicoObjeto 3Dfogon/farolito-de-papel
Farolito de papel
Arrastrá para girarlo// «Farolito de papel» · gpt-6-sol (medium)
// Paper lantern («Farolito de papel»).
const cx = 24, cy = 24;
const radius = {
10: 5, 11: 8, 12: 10, 13: 12, 14: 14,
15: 15, 16: 16, 17: 16.5, 18: 17,
19: 17, 20: 17, 21: 17, 22: 17,
23: 17, 24: 17, 25: 17, 26: 16.5,
27: 16, 28: 15.5, 29: 15, 30: 14,
31: 13, 32: 12, 33: 10, 34: 8
};
const reds = ["#ae3926", "#bf4428", "#cf4c2b", "#dd5830"];
const warm = ["#bb4527", "#d1502b", "#e16431", "#ec7536"];
// Solid, gently ribbed paper body.
for (let z = 10; z <= 34; z++) {
const r = radius[z];
for (let x = Math.ceil(cx - r); x <= Math.floor(cx + r); x++) {
for (let y = Math.ceil(cy - r); y <= Math.floor(cy + r); y++) {
const d = Math.hypot(x - cx, y - cy);
if (d > r) continue;
const front = y < cy + 2;
const palette = front ? reds : warm;
let shade = z > 28 ? 2 : z < 15 ? 0 : 1;
if (z % 3 === 0) shade--;
if (z % 3 === 1 && d > r - 2) shade++;
if (rand() < 0.13) shade += rand() < 0.5 ? -1 : 1;
shade = Math.max(0, Math.min(3, shade));
set(x, y, z, palette[shade]);
}
}
}
// Short horizontal folds, visible along the curved paper surface.
for (let z = 15; z <= 32; z += 3) {
const r = radius[z];
for (let x = cx - Math.floor(r); x <= cx + Math.floor(r); x++) {
const dx = x - cx;
const reach = Math.sqrt(Math.max(0, r * r - dx * dx));
for (const side of [-1, 1]) {
const y = Math.round(cy + side * reach);
if (Math.abs(dx) < r - 1 && rand() > 0.18) {
set(x, y, z, side < 0 ? "#e66a35" : "#ed7838");
}
}
}
}
// Golden bamboo-like ribs running from the crown to the base.
const ribAngles = [
-2.45, -1.85, -1.3, -0.68, 0, 0.68, 1.3, 1.85, 2.45
];
for (const a of ribAngles) {
for (let z = 12; z <= 33; z++) {
const r = radius[z] + 0.45;
const x = Math.round(cx + Math.sin(a) * r);
const y = Math.round(cy - Math.cos(a) * r);
const gold = z % 4 === 0 ? "#f2c35f" :
z % 4 === 1 ? "#d9a647" : "#bb8535";
set(x, y, z, gold);
if (z > 15 && z < 31 && z % 3 !== 0) {
set(x + (Math.sin(a) >= 0 ? 1 : -1), y, z, "#d9a448");
}
}
}
// Gold trim circling the shoulders and lower edge.
for (const z of [12, 31, 33]) {
const r = radius[z] + 0.5;
for (let i = 0; i < 100; i++) {
const a = i * Math.PI * 2 / 100;
set(
Math.round(cx + Math.sin(a) * r),
Math.round(cy - Math.cos(a) * r),
z,
i % 7 === 0 ? "#f3c568" : "#c79239"
);
}
}
// Small gold decorative strokes on the right-hand panel.
for (let z = 18; z <= 27; z++) {
const r = radius[z];
for (let x = 34; x <= 40; x++) {
const dx = x - cx;
if (dx >= r) continue;
const y = Math.round(cy - Math.sqrt(r * r - dx * dx));
const stroke =
(z === 19 && x >= 36 && x <= 39) ||
(z === 24 && x >= 35 && x <= 39) ||
(z === 27 && x >= 35 && x <= 38) ||
(x === 38 && z >= 19 && z <= 24) ||
(x === 35 && z >= 24 && z <= 27);
if (stroke) set(x, y - 1, z, "#efbd58");
}
}
// Reinforced opening at the crown.
cylinder(cx, cy, 34, 6, 2, "#b78131");
cylinder(cx, cy, 36, 5, 1, "#efbd60");
cylinder(cx, cy, 37, 4, 1, "#493024");
for (let i = 0; i < 48; i++) {
const a = i * Math.PI * 2 / 48;
const x = Math.round(cx + 5 * Math.cos(a));
const y = Math.round(cy + 5 * Math.sin(a));
set(x, y, 37, i % 5 === 0 ? "#ffe08a" : "#c9933d");
}
// Angular dark hanging handle.
line(19, 24, 37, 19, 24, 40, 0, "#493029");
line(19, 24, 40, 23, 24, 43, 0, "#493029");
line(23, 24, 43, 27, 24, 43, 0, "#392923");
line(27, 24, 43, 29, 24, 40, 0, "#392923");
line(29, 24, 40, 29, 24, 37, 0, "#493029");
set(20, 23, 40, "#785038");
set(22, 23, 42, "#785038");
// Bottom fitting, cord, and little red paper tassel.
cylinder(cx, cy, 8, 4, 3, "#bd8737");
cylinder(cx, cy, 7, 2, 2, "#edbb58");
box(23, 23, 4, 25, 25, 7, "#b83f28");
box(22, 23, 2, 26, 25, 4, "#d64c2c");
box(23, 22, 1, 25, 26, 3, "#e65c32");
box(21, 24, 0, 22, 25, 2, "#bd4129");
box(26, 23, 0, 27, 24, 2, "#c7472b");
box(23, 22, 0, 24, 23, 2, "#a93a28");
box(24, 26, 0, 25, 27, 2, "#d4522e");
set(24, 22, 4, "#f2ba4d");import { draw } from "./assets/voxel";
import { farolitoDePapel } from "./assets/farolito-de-papel";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, farolitoDePapel, 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 farolito-de-papel
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["farolito-de-papel"] })
# Queda en client/assets/farolito-de-papel.ts
# https://fogon.page/object/farolito-de-papel