← FantasíaObjeto 3Dfogon/pila-de-oro
Pila de oro
Arrastrá para girarlo// «Pila de oro» · gpt-6-sol (medium)
// A big treasure pile: a mound of shiny gold coins in several shades of yellow, with a jeweled crown, a red ruby, a green emerald, a golden goblet and the hilt of a sword sticking out of it.
const gold = ["#a86512", "#c48619", "#e8ad26", "#ffd34a", "#ffe477"];
const coinBright = ["#f5c63d", "#ffdc55", "#ffe77a"];
const stone = ["#484b49", "#626661", "#797d73"];
function moundTop(x, y) {
const dx = (x - 24) / 19.5;
const dy = (y - 24) / 18;
const d = dx * dx + dy * dy;
if (d > 1) return -1;
return Math.floor(3 + 16 * Math.sqrt(1 - d) + Math.sin(x * 0.8 + y * 0.5) * 0.6);
}
// A low, worn stone base beneath the treasure.
for (let x = 2; x <= 46; x++)
for (let y = 3; y <= 45; y++) {
const d = ((x - 24) / 21.5) ** 2 + ((y - 24) / 20.5) ** 2;
if (d <= 1) {
for (let z = 0; z <= 2; z++)
set(x, y, z, stone[rand() < 0.12 ? 0 : rand() < 0.72 ? 1 : 2]);
if (d > 0.83 && rand() < 0.28) set(x, y, 2, "#688650");
}
}
// Solid, gently irregular hill of gold.
for (let x = 4; x <= 44; x++)
for (let y = 5; y <= 43; y++) {
const top = moundTop(x, y);
if (top < 3) continue;
for (let z = 3; z <= top; z++) {
let shade = z === top ? 3 : z < 8 ? 1 : 2;
if (rand() < 0.16) shade = Math.max(0, shade - 1);
if (rand() < 0.13) shade = Math.min(4, shade + 1);
set(x, y, z, gold[shade]);
}
}
// Individual coins catch the light across the mound.
for (let i = 0; i < 145; i++) {
const x = 6 + Math.floor(rand() * 37);
const y = 7 + Math.floor(rand() * 35);
const z = moundTop(x, y);
if (z < 5) continue;
const r = rand() < 0.22 ? 2 : 1;
const c = coinBright[Math.floor(rand() * coinBright.length)];
for (let dx = -r; dx <= r; dx++)
for (let dy = -r; dy <= r; dy++)
if (dx * dx + dy * dy <= r * r && moundTop(x + dx, y + dy) >= z - 2)
set(x + dx, y + dy, z + 1, c);
if (r === 2) set(x, y, z + 2, "#fff0a0");
}
// A few conspicuous stacks spill toward the viewer.
for (const [cx, cy, layers] of [[10, 15, 4], [20, 9, 3], [38, 18, 3]]) {
const base = moundTop(cx, cy);
for (let k = 0; k < layers; k++) {
cylinder(cx, cy, base + 1 + k, 2, 1, k % 2 ? "#c88d20" : "#ffdb54");
set(cx - 1, cy - 2, base + 1 + k, "#fff09a");
}
}
// Crown: purple velvet within a thick, golden circlet.
const crownX = 15, crownY = 27;
ellipsoid(crownX, crownY, 21, 4, 4, 2, "#783a9b");
ellipsoid(crownX, crownY, 23, 3, 3, 1, "#a854ba");
for (let x = 9; x <= 21; x++)
for (let y = 21; y <= 33; y++) {
const d = Math.hypot(x - crownX, y - crownY);
if (d >= 4.2 && d <= 6) {
for (let z = 19; z <= 22; z++)
set(x, y, z, z === 22 ? "#ffe36c" : z === 19 ? "#a76c18" : "#e9ae2e");
if (d > 5.3 && rand() < 0.48) set(x, y, 23, "#ffd153");
}
}
for (const [dx, dy] of [[-5, 0], [-4, -4], [0, -5], [4, -4], [5, 0], [4, 4], [0, 5], [-4, 4]]) {
const px = crownX + dx, py = crownY + dy;
box(px - 1, py - 1, 23, px + 1, py + 1, 25, "#e9ad2b");
sphere(px, py, 26, 1.5, "#ffda54");
set(px, py, 28, "#fff0a1");
}
// Large gems on the crown's front band.
sphere(15, 21, 22, 2, "#da306e");
set(15, 19, 23, "#ff88b6");
sphere(11, 23, 22, 1.5, "#39dbdc");
sphere(19, 23, 22, 1.5, "#61e784");
// Oversized faceted ruby, resting on the front-left slope.
for (let z = 10; z <= 21; z++) {
const width = z < 14 ? 2 + Math.floor((z - 10) / 2) : z < 18 ? 5 : Math.max(1, 5 - (z - 17));
const depth = Math.min(3, Math.max(1, width - 1));
for (let x = 12 - width; x <= 12 + width; x++)
for (let y = 12 - depth; y <= 12 + depth; y++) {
if (Math.abs(x - 12) / (width + 0.5) + Math.abs(y - 12) / (depth + 0.5) > 1.35) continue;
set(x, y, z, y <= 11 ? "#f34067" : x < 12 ? "#a51746" : "#cf2550");
}
}
box(10, 9, 16, 12, 9, 18, "#ff8797");
set(11, 9, 19, "#ffd1cc");
line(9, 12, 11, 15, 12, 11, 0, "#ffd65d");
// Bright green emerald on the right.
for (let z = 13; z <= 23; z++) {
const width = z < 16 ? z - 12 : z > 20 ? 24 - z : 4;
for (let x = 34 - width; x <= 34 + width; x++)
for (let y = 12 - Math.min(3, width); y <= 12 + Math.min(3, width); y++) {
if (Math.abs(x - 34) + Math.abs(y - 12) > width + 2) continue;
set(x, y, z, y <= 11 ? "#43e99a" : x < 34 ? "#168c68" : "#25bd78");
}
}
box(32, 9, 17, 33, 9, 20, "#a5ffd1");
set(33, 9, 21, "#e0ffdf");
// Golden goblet, with a wide hollow-looking bowl and glowing teal contents.
cylinder(38, 28, 16, 3, 2, "#a8751e");
cylinder(38, 28, 18, 2, 1, "#ffda59");
cylinder(38, 28, 19, 1, 6, "#d69d27");
sphere(38, 28, 24, 2, "#f5c743");
for (let z = 25; z <= 31; z++) {
const r = Math.min(5, 2 + Math.floor((z - 24) * 0.65));
for (let x = 38 - r; x <= 38 + r; x++)
for (let y = 28 - r; y <= 28 + r; y++) {
const d = Math.hypot(x - 38, y - 28);
if (d <= r && (z <= 26 || d >= r - 1.4))
set(x, y, z, y < 28 ? "#ffda58" : "#c58b1f");
}
}
cylinder(38, 28, 30, 3, 1, "#33c9bc");
cylinder(38, 28, 31, 4, 1, "#ffe079");
set(37, 24, 31, "#fff3aa");
set(35, 27, 28, "#fff3aa");
// The sword is buried blade-first; its ornate hilt leans out of the coins.
line(25, 35, 17, 28, 35, 27, 1, "#aab9bd");
line(25, 34, 19, 27, 34, 26, 0, "#e2eaeb");
sphere(28, 35, 27, 2, "#ba8124");
line(22, 35, 27, 34, 35, 27, 1, "#d59a2b");
line(22, 35, 27, 24, 35, 29, 1, "#ffdb63");
line(32, 35, 29, 34, 35, 27, 1, "#ffdb63");
set(28, 33, 28, "#49e9e5");
line(28, 35, 29, 31, 35, 36, 1, "#61475b");
for (let z = 30; z <= 35; z += 2)
line(28 + Math.floor((z - 29) * 3 / 7), 33, z,
29 + Math.floor((z - 29) * 3 / 7), 33, z + 1, 0, "#edbd55");
sphere(31, 35, 37, 2, "#f4c047");
sphere(31, 33, 37, 1, "#bb5ce0");
set(31, 32, 37, "#f2b8ff");
// A few tiny magical glints among the treasure.
for (const [x, y, z, c] of [
[7, 22, 8, "#fff3a8"], [19, 14, 17, "#fff4a9"],
[27, 15, 17, "#fff3a8"], [41, 22, 10, "#ffe78a"],
[23, 26, 20, "#ffffff"], [32, 21, 18, "#fff4ad"]
]) {
set(x, y, z, c);
set(x - 1, y, z, "#ffe277");
set(x + 1, y, z, "#ffe277");
}import { draw } from "./assets/voxel";
import { pilaDeOro } from "./assets/pila-de-oro";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, pilaDeOro, 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 pila-de-oro
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["pila-de-oro"] })
# Queda en client/assets/pila-de-oro.ts
# https://fogon.page/object/pila-de-oro