← Fiestas y NavidadObjeto 3Dfogon/torta-de-cumpleanos
Torta de cumpleaños
Arrastrá para girarlo// «Torta de cumpleaños» · gpt-6-sol (medium)
// A three-tier birthday cake on a white plate: pink frosting with white cream drips, colorful sprinkles, a ring of strawberries on the top tier, and five striped candles with small flames on top.
const cx = 24, cy = 24;
const TAU = Math.PI * 2;
// A broad, shiny white serving plate.
cylinder(cx, cy, 0, 21, 1, "#dfe8ed");
cylinder(cx, cy, 1, 20, 1, "#ffffff");
cylinder(cx, cy, 2, 18, 1, "#f5f9fa");
for (let x = 3; x <= 45; x++) {
for (let y = 3; y <= 45; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d >= 19.3 && d <= 21) set(x, y, 1, "#edf3f6");
if (d >= 18.5 && d < 19.3) set(x, y, 2, "#ffffff");
}
}
const tiers = [
{ r: 18, bottom: 3, top: 13 },
{ r: 14, bottom: 15, top: 23 },
{ r: 10, bottom: 25, top: 32 }
];
const sprinkleColors = [
"#51d8ce", "#f9e36b", "#b895ed", "#ffffff",
"#71d478", "#ff805e", "#62b9f4"
];
for (const tier of tiers) {
const { r, bottom, top } = tier;
// Solid pink sponge, with a softly shaded exterior.
for (let x = cx - r; x <= cx + r; x++) {
for (let y = cy - r; y <= cy + r; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d > r) continue;
for (let z = bottom; z <= top; z++) {
let color = "#f58db1";
if (z <= bottom + 2) color = "#e876a0";
if (z >= top - 3) color = "#ffa7c4";
if (d >= r - 1.4 && y > cy + 3) color = "#e983a9";
if (d >= r - 2 && rand() < 0.075) color = "#ffc0d0";
set(x, y, z, color);
}
}
}
// A little pastel piping around the foot of each tier.
for (let i = 0; i < Math.round(r * 5); i++) {
const a = TAU * i / Math.round(r * 5);
const x = Math.round(cx + (r - 0.5) * Math.cos(a));
const y = Math.round(cy + (r - 0.5) * Math.sin(a));
set(x, y, bottom + 1, i % 3 === 0 ? "#fff0f3" : "#f7bed1");
}
// Thick cream top, with uneven drips running down the pink sides.
cylinder(cx, cy, top + 1, r, 1, "#fffdf4");
for (let x = cx - r; x <= cx + r; x++) {
for (let y = cy - r; y <= cy + r; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d < r - 1.7 || d > r) continue;
const a = Math.atan2(y - cy, x - cx);
const wave = Math.sin(11 * a + r) + 0.55 * Math.sin(19 * a - r);
const length = wave > 0.75 ? 4 : wave > 0.05 ? 2 : 1;
for (let k = 0; k < length; k++) {
set(x, y, top - k, k === length - 1 ? "#f6f5ee" : "#fffdf4");
}
}
}
// Individually piped cream beads make a rounded, toy-like rim.
const beads = Math.round(r * 3.1);
for (let i = 0; i < beads; i++) {
const a = TAU * i / beads;
const x = Math.round(cx + (r - 0.8) * Math.cos(a));
const y = Math.round(cy + (r - 0.8) * Math.sin(a));
sphere(x, y, top + 1, 1, i % 4 === 0 ? "#f1f4ef" : "#ffffff");
}
// Bright, short sprinkles across the visible pink walls.
for (let i = 0; i < r * 5; i++) {
const a = TAU * i / (r * 5) + (rand() - 0.5) * 0.17;
const x = Math.round(cx + (r - 0.15) * Math.cos(a));
const y = Math.round(cy + (r - 0.15) * Math.sin(a));
const z = bottom + 3 + Math.floor(rand() * Math.max(1, top - bottom - 6));
const color = sprinkleColors[Math.floor(rand() * sprinkleColors.length)];
set(x, y, z, color);
if (rand() < 0.6) set(x, y, z + 1, color);
}
}
// A ring of plump red strawberries on the top tier.
for (let i = 0; i < 12; i++) {
const a = TAU * i / 12;
const x = Math.round(cx + 7.2 * Math.cos(a));
const y = Math.round(cy + 7.2 * Math.sin(a));
ellipsoid(x, y, 35, 1.55, 1.55, 1.8, "#e92743");
set(x, y - 1, 35, "#ff5860");
set(x, y, 37, "#55b94e");
set(x - 1, y, 37, "#399b4a");
set(x + 1, y, 37, "#399b4a");
set(x, y - 1, 37, "#55b94e");
set(x, y + 1, 37, "#399b4a");
set(x, y - 1, 34, "#ffe29a");
}
// Five striped candles, each with its own flickering flame.
const candles = [
[24, 24, "#66d9d1"],
[20, 21, "#b99ae9"],
[28, 21, "#f8d85e"],
[21, 28, "#83d977"],
[27, 28, "#ff9caa"]
];
candles.forEach(([x, y, color], i) => {
box(x, y, 34, x + 1, y + 1, 41, color);
for (let z = 35; z <= 40; z += 3) {
set(x, y, z, "#ffffff");
set(x + 1, y + 1, z + 1, "#ffffff");
set(x + 1, y, z, "#fff8df");
}
box(x, y, 42, x + 1, y + 1, 42, "#fff5de");
set(x, y, 43, "#555563");
const flame = `flame${i}`;
part(flame, [x, y, 43]);
set(x, y, 44, "#ffad37");
set(x + 1, y, 44, "#ffe36c");
set(x, y, 45, "#fff9d6");
animate(flame, {
type: "colors",
palette: ["#ffe26b", "#ff9c35", "#fff9df"],
pattern: "flicker",
glow: 1
});
part("body");
});import { draw } from "./assets/voxel";
import { tortaDeCumpleanos } from "./assets/torta-de-cumpleanos";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, tortaDeCumpleanos, 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 torta-de-cumpleanos
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["torta-de-cumpleanos"] })
# Queda en client/assets/torta-de-cumpleanos.ts
# https://fogon.page/object/torta-de-cumpleanos