← Fantasy3D assetfogon/fuente-de-los-deseos
Fuente de los deseos
Drag to turn it// «Fuente de los deseos» · gpt-6-sol (medium)
// A round magical wishing fountain: a circular stone basin with mossy rim, a central pillar with a small statue of a fish spouting water, the water glowing soft teal, and a few gold coins at the bottom.
const C = {
stone: ["#59646a", "#667178", "#758188", "#879198"],
shadow: "#46535b",
light: "#9aa4a5",
moss: ["#486d58", "#59866a", "#79a77a"],
brass: "#a87539",
gold: "#edbf59",
goldLight: "#ffe29a",
teal: "#48e4d4"
};
const cx = 24, cy = 24;
const stone = (z, top = false) => {
const n = rand();
if (top) return n < 0.13 ? C.moss[0] : n < 0.36 ? C.light : C.stone[3];
return n < 0.12 ? C.shadow : C.stone[Math.min(3, Math.floor(z / 5) + (n > 0.84 ? 1 : 0))];
};
// Solid, circular foundation and the bowl's rounded outer wall.
for (let x = 3; x <= 45; x++) {
for (let y = 3; y <= 45; y++) {
const d = Math.hypot(x - cx, y - cy);
for (let z = 0; z <= 12; z++) {
let inside = false;
if (z <= 2) inside = d <= 20;
else if (z === 3) inside = d <= 19.5;
else if (z <= 7) inside = d >= 15.8 && d <= 20;
else if (z === 8) inside = d >= 15.8 && d <= 20.4;
else if (z === 9) inside = d >= 15.5 && d <= 20.8;
else if (z === 10) inside = d >= 15.7 && d <= 21;
else if (z === 11) inside = d >= 16.4 && d <= 20.7;
else inside = d >= 17.3 && d <= 19.8;
if (inside) set(x, y, z, stone(z, z >= 11));
}
if (d <= 15.8) set(x, y, 3, "#53676d");
}
}
// Dark mortar courses and a few broad, uneven stone joints.
for (let x = 4; x <= 44; x++) for (let y = 4; y <= 44; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d > 19 && d < 20.5 && (x + 2 * y) % 13 === 0) {
for (let z = 4; z <= 7; z++) if (get(x, y, z)) set(x, y, z, "#4b585d");
}
if (d > 18.5 && d < 20.3 && rand() < 0.17)
set(x, y, 12, C.moss[Math.floor(rand() * 3)]);
}
// A mossy, slightly irregular crown to the rim.
for (let x = 4; x <= 44; x++) for (let y = 4; y <= 44; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d >= 17.1 && d <= 20.1 && rand() < 0.19)
set(x, y, 13, C.moss[Math.floor(rand() * 3)]);
if (d >= 18 && d <= 20 && rand() < 0.045)
set(x, y, 14, C.moss[1]);
}
// Little brass dedication plaque on the front of the bowl.
box(21, 4, 5, 27, 4, 8, C.brass);
box(22, 3, 6, 26, 3, 7, C.gold);
set(24, 2, 6, "#3b8b91");
set(24, 2, 7, "#9effe6");
set(23, 3, 8, C.goldLight);
set(25, 3, 8, C.goldLight);
// Chunky carved pedestal rising out of the basin.
cylinder(24, 24, 4, 6, 3, "#59676a");
cylinder(24, 24, 7, 4.5, 12, "#737f7d");
cylinder(24, 24, 19, 5.2, 2, "#929c96");
cylinder(24, 24, 21, 4.2, 2, "#626e70");
for (let z = 9; z <= 18; z++) {
set(20, 22, z, z % 4 === 0 ? "#a4aaa0" : "#88958d");
set(28, 25, z, z % 4 === 0 ? "#4e645e" : "#667b71");
}
for (let i = 0; i < 22; i++) {
const a = rand() * Math.PI * 2;
const z = 8 + Math.floor(rand() * 12);
set(Math.round(24 + Math.cos(a) * 4.3),
Math.round(24 + Math.sin(a) * 4.3), z,
C.moss[Math.floor(rand() * 3)]);
}
// The friendly little brass fish, facing the viewer (-y).
ellipsoid(24, 23, 26, 4, 5, 3, "#a87539");
ellipsoid(24, 21, 27, 3.5, 3.5, 3, "#d7a14c");
ellipsoid(24, 19, 26, 3, 2.5, 2.5, "#efbf67");
for (let x of [20, 28]) {
ellipsoid(x, 24, 25, 2, 2, 1, "#bd8340");
set(x < 24 ? 18 : 30, 23, 25, C.goldLight);
}
// Fanned tail and tall, soft triangular dorsal fin.
for (let y = 27; y <= 32; y++) {
const spread = Math.max(1, y - 27);
for (let z = 26 - Math.floor(spread / 2); z <= 27 + spread; z++)
if (Math.abs(z - 27) <= spread + 1)
set(24, y, z, (z + y) % 3 ? "#c68b42" : C.gold);
}
for (let z = 29; z <= 34; z++) {
const half = Math.max(0, 3 - Math.floor((z - 29) / 2));
box(24 - half, 23, z, 24 + half, 25, z, z === 34 ? C.goldLight : "#dca550");
}
// Oversized bright eyes and a small puckered spout.
for (const x of [21, 27]) {
box(x - 1, 16, 27, x, 17, 28, "#fff2d1");
set(x, 15, 27, "#253d43");
set(x, 15, 28, "#253d43");
set(x - 1, 15, 28, "#ffffff");
}
box(23, 16, 24, 25, 17, 25, C.gold);
set(24, 15, 24, "#745536");
set(23, 16, 23, "#f4c777");
set(25, 16, 23, "#f4c777");
// Tiny mushrooms growing from the old stone rim.
function mushroom(x, y, z, cap) {
box(x, y, z, x, y, z + 2, "#eee6c4");
ellipsoid(x, y, z + 3, 2, 2, 1, cap);
set(x - 1, y - 1, z + 4, "#fff3cf");
set(x + 1, y, z + 4, "#fff3cf");
}
mushroom(8, 15, 12, "#c775a4");
mushroom(40, 17, 12, "#a27bd0");
mushroom(35, 39, 12, "#cc817c");
// All animated water belongs to one part: pool, ripples, jet and droplets.
part("water", [24, 24, 6]);
for (let x = 8; x <= 40; x++) for (let y = 8; y <= 40; y++) {
const d = Math.hypot(x - 24, y - 24);
if (d <= 15.4) {
set(x, y, 6, rand() < 0.18 ? "#50d7c9" : "#278f98");
if (rand() < 0.055) set(x, y, 7, "#8bf8e4");
}
}
// Soft concentric glints around the pedestal and where the jet lands.
for (const [ox, oy, radius] of [[24, 24, 7], [24, 10, 3], [24, 10, 5]]) {
for (let a = 0; a < Math.PI * 2; a += 0.16) {
if (rand() < 0.22) continue;
set(Math.round(ox + Math.cos(a) * radius),
Math.round(oy + Math.sin(a) * radius), 7,
rand() < 0.45 ? "#b8fff1" : "#51eadb");
}
}
line(24, 14, 24, 24, 10, 26, 1, "#86f9eb");
line(24, 10, 26, 24, 7, 22, 1, "#74eee5");
line(24, 7, 22, 24, 7, 15, 1, "#52dcd7");
line(24, 7, 15, 24, 10, 8, 1, "#9affee");
for (const [x, y, z] of [[23, 9, 23], [25, 8, 19], [23, 8, 13],
[26, 11, 9], [21, 10, 8], [24, 12, 9]]) {
sphere(x, y, z, 1, "#b9fff0");
}
animate("water", {
type: "colors",
palette: ["#218f9b", "#36c8c8", "#65eadf", "#a7fff0", "#f0fffa"],
pattern: "wave",
glow: 0.6
});
// Coins sit visibly on top of the enchanted water.
part("body");
for (const [x, y] of [[16, 17], [19, 13], [29, 14], [34, 20],
[14, 25], [19, 34], [30, 33], [34, 29]]) {
cylinder(x, y, 8, 1.4, 1, C.gold);
set(x, y, 9, C.goldLight);
set(x - 1, y, 9, "#d69b3e");
}import { draw } from "./assets/voxel";
import { fuenteDeLosDeseos } from "./assets/fuente-de-los-deseos";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, fuenteDeLosDeseos, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: its longest side, in px
// angle: turn on the floor, in radians
// t: seconds; if it moves, that animates it# In a terminal, in the game's folder
fogon assets add fuente-de-los-deseos
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["fuente-de-los-deseos"] })
# It lands in client/assets/fuente-de-los-deseos.ts
# https://fogon.page/object/fuente-de-los-deseos