← Fiestas y NavidadObjeto 3Dfogon/rosca-de-reyes
Rosca de Reyes
Arrastrá para girarlo// «Rosca de Reyes» · gpt-6-sol (medium)
// A ring-shaped sweet bread on a round plate: a golden-brown glazed ring decorated on top with stripes of pastry cream, strips of red and green candied fruit and a sprinkle of sugar, with a small crown of gold paper resting on it.
const cx = 24, cy = 24;
// A round, pastel plate with a raised white rim.
for (let x = 2; x <= 46; x++) {
for (let y = 2; y <= 46; y++) {
const r = Math.hypot(x - cx, y - cy);
if (r <= 20.8) set(x, y, 0, "#badbd5");
if (r <= 21.5) {
set(x, y, 1, r > 20 ? "#d8e9e5" : "#c8f0e9");
set(x, y, 2, r > 19.7 ? "#fff9ed" : "#e6fffa");
}
if (r <= 19.4) set(x, y, 3, "#effff9");
if (r >= 19.4 && r <= 21.2) {
set(x, y, 3, r > 20.5 ? "#e1e9e3" : "#ffffff");
}
if (r >= 20 && r <= 21.1) set(x, y, 4, "#fffdf4");
if (r >= 19.45 && r < 19.9) set(x, y, 4, "#f5cc68");
}
}
// Solid sweet-bread ring, with a shiny upper crust.
const ringRadius = 13.35;
const tubeRadius = 5.7;
const centerZ = 9;
const tubeHeight = 5.3;
function breadTop(r) {
const t = (r - ringRadius) / tubeRadius;
return Math.abs(t) < 1
? centerZ + tubeHeight * Math.sqrt(1 - t * t)
: 0;
}
for (let x = 4; x <= 44; x++) {
for (let y = 4; y <= 44; y++) {
const r = Math.hypot(x - cx, y - cy);
const radial = (r - ringRadius) / tubeRadius;
if (Math.abs(radial) > 1) continue;
const top = breadTop(r);
for (let z = 4; z <= 15; z++) {
const shape = radial * radial +
Math.pow((z - centerZ) / tubeHeight, 2);
if (shape > 1) continue;
let color;
if (z >= top - 1.15 && z >= 10) {
color = rand() < 0.17 ? "#ffdf82" : "#e9a83d";
if (rand() < 0.12) color = "#f5bd54";
} else if (z <= 6) {
color = rand() < 0.2 ? "#a85b28" : "#bc712e";
} else {
color = rand() < 0.16 ? "#dc933b" : "#ca7c2e";
}
set(x, y, z, color);
}
}
}
// Thick, gently wavy stripes of pastry cream across the top.
for (let i = 0; i < 12; i++) {
const angle = i * Math.PI / 6;
let previous = null;
for (let j = 0; j <= 16; j++) {
const r = 9.3 + j * 0.5;
const a = angle + 0.022 * Math.sin(j * 0.7 + i);
const point = [
cx + r * Math.cos(a),
cy + r * Math.sin(a),
breadTop(r) + 0.9
];
if (previous) {
line(...previous, ...point, 0.7,
j % 4 === 0 ? "#fff9df" : "#f7e7bb");
}
previous = point;
}
}
// Glossy red and green candied-fruit strips between the cream stripes.
for (let i = 0; i < 12; i++) {
const angle = (i + 0.5) * Math.PI / 6;
const r = i % 3 === 0 ? 14.6 : 12.1;
const x = cx + r * Math.cos(angle);
const y = cy + r * Math.sin(angle);
const z = breadTop(r) + 1.35;
const tx = -Math.sin(angle);
const ty = Math.cos(angle);
const green = i % 2 === 0;
line(x - tx * 1.9, y - ty * 1.9, z,
x + tx * 1.9, y + ty * 1.9, z,
0.85, green ? "#278a45" : "#bd2538");
line(x - tx * 1.5, y - ty * 1.5, z + 0.65,
x + tx * 1.5, y + ty * 1.5, z + 0.65,
0.45, green ? "#67d56d" : "#ff6670");
}
// Sparkling sugar crystals, scattered over exposed glaze.
for (let i = 0; i < 135; i++) {
const angle = rand() * Math.PI * 2;
const r = 9 + rand() * 8.3;
const x = Math.round(cx + r * Math.cos(angle));
const y = Math.round(cy + r * Math.sin(angle));
const z = Math.round(breadTop(r) + 0.7);
if (z >= 11 && rand() < 0.78) {
set(x, y, z, rand() < 0.3 ? "#fff1c9" : "#ffffff");
}
}
// A little hollow gold-paper crown resting on the back of the bread.
const crownX = 24, crownY = 35;
for (let x = 19; x <= 29; x++) {
for (let y = 30; y <= 40; y++) {
const dx = x - crownX, dy = y - crownY;
const r = Math.hypot(dx, dy);
if (r < 3.35 || r > 4.8) continue;
const a = Math.atan2(dy, dx);
let nearestPoint = Math.PI;
for (let k = 0; k < 5; k++) {
const pointAngle = -Math.PI / 2 + k * Math.PI * 2 / 5;
const difference = Math.atan2(
Math.sin(a - pointAngle), Math.cos(a - pointAngle)
);
nearestPoint = Math.min(nearestPoint, Math.abs(difference));
}
const pointedTop = 18.2 + 4.5 *
Math.max(0, 1 - nearestPoint / (Math.PI / 5));
for (let z = 14; z <= 23; z++) {
if (z > pointedTop) continue;
let color = dy < 0 ? "#f9c747" : "#d99422";
if (z === 14 || z === 17) color = "#ffe477";
else if (z > 18 && rand() < 0.3) color = "#ffe076";
set(x, y, z, color);
}
}
}
// Rounded golden tips and bright jewels on the crown's front band.
for (let k = 0; k < 5; k++) {
const a = -Math.PI / 2 + k * Math.PI * 2 / 5;
sphere(
crownX + 4.1 * Math.cos(a),
crownY + 4.1 * Math.sin(a),
22,
0.8,
"#ffe67a"
);
}
sphere(24, 30.6, 16, 1, "#e94455");
set(24, 30, 17, "#ffb1a3");
sphere(21, 32, 16, 0.8, "#47c993");
sphere(27, 32, 16, 0.8, "#62d7e4");import { draw } from "./assets/voxel";
import { roscaDeReyes } from "./assets/rosca-de-reyes";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, roscaDeReyes, 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 rosca-de-reyes
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["rosca-de-reyes"] })
# Queda en client/assets/rosca-de-reyes.ts
# https://fogon.page/object/rosca-de-reyes