← FantasíaObjeto 3Dfogon/caliz
Cáliz
Arrastrá para girarlo// «Cáliz» · gpt-6-sol (medium)
// An ornate golden chalice: a wide cup on a slim stem with a round foot, decorated with a ring of red and blue gems, sitting on a small purple velvet cushion with gold tassels.
const cx = 24, cy = 24;
const gold = ["#a56a20", "#be8229", "#d79d36", "#efbd55", "#ffe08a"];
function disk(z, r, color) {
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++)
if ((x - cx) ** 2 + (y - cy) ** 2 <= r * r)
set(x, y, z, typeof color === "function" ? color(x, y) : color);
}
// A plump velvet cushion, with a darker lower edge.
ellipsoid(cx, cy, 2, 19, 16, 3, "#52216f");
ellipsoid(cx, cy, 3, 18, 15, 3, "#79289b");
ellipsoid(23, 22, 4, 16, 13, 2, "#9a40b6");
forEach((x, y, z, c) => {
if (z >= 4 && c === "#9a40b6" && rand() < 0.065)
set(x, y, z, rand() < 0.5 ? "#b158c4" : "#84319d");
});
// Gold piping follows the softly rounded cushion edge.
for (let i = 0; i < 112; i++) {
const a = i * Math.PI * 2 / 112;
const x = Math.round(cx + 18 * Math.cos(a));
const y = Math.round(cy + 15 * Math.sin(a));
set(x, y, 3, "#bd842e");
if (i % 3 !== 0) set(x, y, 4, "#f0c45f");
}
// Four dangling corner tassels.
for (const dx of [-1, 1]) for (const dy of [-1, 1]) {
const x = cx + dx * 15, y = cy + dy * 12;
sphere(x, y, 4, 1.7, "#f5ce68");
for (let k = -1; k <= 1; k++) {
line(x + k, y, 3, x + k, y, 0, 0, k === 0 ? "#ffdf82" : "#b97928");
}
set(x, y, 0, "#ffe493");
}
// The broad, tiered foot of the chalice.
disk(6, 8.5, "#925c1d");
disk(7, 10.5, (x, y) => y < cy ? "#e4ab41" : "#ad7123");
disk(8, 11, (x, y) => y < cy ? "#f5c55f" : "#c88d2d");
disk(9, 9.5, "#c78c2e");
disk(10, 7, "#f0b94b");
disk(11, 4.5, "#b77a24");
disk(12, 3.2, "#edb84c");
// Slim stem with a rounded ornamental knop.
cylinder(cx, cy, 12, 2.5, 9, "#ca8d2e");
sphere(cx, cy, 15, 3.8, "#dda443");
disk(14, 3.3, "#f6c962");
disk(17, 3.4, "#a66b20");
disk(18, 3, "#f5c45d");
disk(20, 4.2, "#ac711f");
// A solid rounded bowl below, opening into a deep hollow cup above.
const outer = [
4.0, 5.3, 6.7, 8.0, 9.0, 10.0, 10.8, 11.6, 12.2, 12.8,
13.2, 13.6, 14.0, 14.3, 14.5, 14.6, 14.7, 14.7, 14.8
];
const inner = {
24: 0, 25: 3, 26: 5, 27: 7, 28: 8.1, 29: 9.1,
30: 10.0, 31: 10.9, 32: 11.6, 33: 12.0, 34: 12.4,
35: 12.7, 36: 13.0, 37: 13.2
};
for (let z = 19; z <= 37; z++) {
const r = outer[z - 19];
for (let x = cx - 15; x <= cx + 15; x++)
for (let y = cy - 15; y <= cy + 15; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d > r || (inner[z] !== undefined && d < inner[z])) continue;
let color;
if (z >= 24 && d < inner[z] + 1.5)
color = z < 29 ? "#a87229" : (x < cx ? "#dba545" : "#bd812c");
else if (z <= 22)
color = "#bf8127";
else if (y < cy - 5)
color = x < cx ? "#f4c35b" : "#dfa43e";
else
color = x < cx ? "#dfaa43" : "#bf8027";
if (d > r - 1.2 && x < cx - 3 && y < cy && z > 25)
color = "#ffdb78";
if (rand() < 0.035 && z < 36) color = "#ecc05c";
set(x, y, z, color);
}
}
// Thick, bright rolled lip makes the open mouth legible.
for (let x = cx - 15; x <= cx + 15; x++)
for (let y = cy - 15; y <= cy + 15; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d >= 12.8 && d <= 14.9)
set(x, y, 38, y < cy ? "#ffe08a" : "#e6ac43");
}
// Engraved bands, with alternating large ruby and sapphire gems.
for (let i = 0; i < 96; i++) {
const a = i * Math.PI * 2 / 96;
for (const z of [26, 33]) {
const r = outer[z - 19] + 0.15;
set(cx + Math.cos(a) * r, cy + Math.sin(a) * r, z,
z === 33 ? "#fbd16d" : "#ad7022");
}
}
for (let i = 0; i < 18; i++) {
const a = i * Math.PI * 2 / 18;
const x = Math.round(cx + 14 * Math.cos(a));
const y = Math.round(cy + 14 * Math.sin(a));
sphere(x, y, 30, 2, "#e9b54f");
sphere(x, y, 30, 1.45, i % 2 ? "#2568bd" : "#b52b52");
set(x - 1, y - 1, 31, i % 2 ? "#83e2f0" : "#ff98a3");
}
// Tiny curled flourishes beneath the jewel band on the visible front.
for (const x of [16, 24, 32]) {
line(x - 2, 12, 26, x, 11, 24, 0, "#ffe080");
line(x, 11, 24, x + 2, 12, 26, 0, "#ffe080");
}import { draw } from "./assets/voxel";
import { caliz } from "./assets/caliz";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, caliz, 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 caliz
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["caliz"] })
# Queda en client/assets/caliz.ts
# https://fogon.page/object/caliz