← Casa completaObjeto 3Dfogon/puff
Puff
Arrastrá para girarlo// «Puff» · gpt-6-sol (medium)
// A round soft pouf (ottoman): a fat cylinder of knitted fabric in coral pink with a chunky braided texture made of alternating shades, a slightly domed top with a button in the center.
const cx = 24, cy = 24;
const radii = [
14.8, 15.9, 16.5, 17.0, 17.1, 17.1, 17.1, 17.1,
17.1, 17.1, 17.1, 17.1, 17.05, 16.95, 16.8, 16.55,
16.2, 15.6, 14.9, 13.9, 12.4, 10.5, 7.7, 3.9
];
const coral = ["#d87875", "#e38a83", "#ec9990", "#f4aaa0"];
const yarnLight = ["#f6aaa0", "#ffc0af"];
const tau = Math.PI * 2;
for (let z = 0; z < radii.length; z++) {
for (let y = 5; y <= 43; y++) {
for (let x = 5; x <= 43; x++) {
const dx = x - cx, dy = y - cy;
const d = Math.hypot(dx, dy);
const a = Math.atan2(dy, dx);
const around = (a + Math.PI) * 25 / tau;
// Paired, slanting loops make a chunky knitted V on the barrel.
const row = Math.floor((z - 2) / 4);
const rise = ((z - 2) % 4 + 4) % 4 / 4;
const stitch = around + (row & 1) * 0.5;
const across = ((stitch % 1) + 1) % 1;
const v = Math.abs(across - 0.5);
const raised = z >= 2 && z <= 16 &&
Math.abs(v - (0.08 + 0.32 * rise)) < 0.13;
const outer = radii[z] + (raised ? 0.42 : 0);
if (d > outer) continue;
const side = d > radii[z] - 2.3;
const top = z >= 17 && d > (radii[z + 1] ?? -1);
let color = coral[1];
if (z <= 2) {
color = z === 0 ? "#bd6869" : "#d17b76";
} else if (side && z <= 16) {
const alternate = (Math.floor(stitch) + row) & 1;
color = alternate ? coral[1] : coral[2];
if (raised) color = yarnLight[alternate];
else if (Math.abs(v - (0.08 + 0.32 * rise)) < 0.22)
color = "#cb706e";
} else if (top) {
color = "#efa097";
// Soft concentric rows of little knitted loops on the domed seat.
const ring = Math.floor(d / 2.5);
const loop = (a + Math.PI) * (12 + ring * 3) / tau + (ring & 1) * 0.5;
const phase = ((loop % 1) + 1) % 1;
if (Math.abs(phase - 0.5) < 0.22)
color = ring & 1 ? "#f8b0a4" : "#f5a79e";
if (d > 12.5) color = "#e68d86";
} else if (z > 14) {
color = "#e9948b";
}
if (side && !raised && rand() < 0.055)
color = z < 12 ? "#da807b" : "#e99991";
set(x, y, z, color);
}
}
}
// A thick, tidy piping seam where the rounded top meets the sides.
for (let i = 0; i < 360; i++) {
const a = i * tau / 360;
set(cx + Math.cos(a) * 16.0, cy + Math.sin(a) * 16.0, 16, "#f6aaa0");
if (i % 9 < 5)
set(cx + Math.cos(a) * 15.5, cy + Math.sin(a) * 15.5, 17, "#e2837d");
}
// Small recessed tuft and a plump fabric-covered button.
ellipsoid(cx, cy, 23, 3.5, 3.5, 0.8, "#d47776");
ellipsoid(cx, cy, 24, 2.6, 2.6, 1.3, "#ffc3af");
ellipsoid(cx, cy, 25, 1.8, 1.8, 0.6, "#ffd1ba");
set(23, 24, 25, "#be7773");
set(25, 24, 25, "#be7773");import { draw } from "./assets/voxel";
import { puff } from "./assets/puff";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, puff, 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 puff
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["puff"] })
# Queda en client/assets/puff.ts
# https://fogon.page/object/puff