← AsiáticoObjeto 3Dfogon/shishi-odoshi
Fuente de bambú
Arrastrá para girarlo// «Fuente de bambú» · gpt-6-sol (medium)
// A Japanese bamboo water fountain (shishi-odoshi): a small stone basin with blue water, a green bamboo pipe pouring into a pivoting bamboo tube on a small wooden frame, surrounded by a few rounded pebbles and moss.
// Stone basin and its thick, softly irregular rim
const cx = 24, cy = 23;
for (let z = 0; z <= 9; z++) {
const rx = z < 2 ? 14.5 : z < 7 ? 16.5 : 15.8;
const ry = z < 2 ? 10.8 : z < 7 ? 13.2 : 12.5;
for (let x = 6; x <= 42; x++) for (let y = 8; y <= 38; y++) {
const d = ((x - cx) / rx) ** 2 + ((y - cy) / ry) ** 2;
const inner = ((x - cx) / 13.1) ** 2 + ((y - cy) / 9.8) ** 2;
if (d > 1 || (z >= 5 && inner < 1)) continue;
let c = z >= 8 ? "#c8c9bb" : z >= 4 ? "#aeb3a8" : "#898e83";
if (rand() < 0.19) c = z >= 7 ? "#e0dfcb" : "#979e96";
if (rand() < 0.08) c = "#777e77";
set(x, y, z, c);
}
}
// Moss around the footing and creeping onto the stone
for (const [x, y, rx, ry] of [
[9, 17, 4, 3], [39, 18, 4, 3], [14, 36, 4, 3],
[34, 35, 4, 3], [23, 9, 5, 2]
]) {
ellipsoid(x, y, 0, rx, ry, 1, "#486b3b");
for (let i = 0; i < 19; i++) {
const px = x + Math.round((rand() * 2 - 1) * rx);
const py = y + Math.round((rand() * 2 - 1) * ry);
if (((px-x)/rx)**2 + ((py-y)/ry)**2 < 1)
set(px, py, 1, rand() < 0.5 ? "#65964c" : "#789b51");
}
}
for (let i = 0; i < 75; i++) {
const x = 8 + Math.floor(rand() * 33), y = 10 + Math.floor(rand() * 27);
const d = ((x-cx)/16)**2 + ((y-cy)/12.7)**2;
if (d > 0.76 && d < 1.03)
set(x, y, 9, rand() < 0.6 ? "#61834b" : "#85a45a");
}
// Smooth garden pebbles at the front and sides
for (const [x, y, r] of [
[7, 14, 2.5], [10, 9, 2], [38, 10, 2.6],
[41, 17, 2], [15, 7, 1.8], [34, 8, 1.8]
]) {
ellipsoid(x, y, 1.4, r, r * 0.78, 1.7, "#9ca59a");
ellipsoid(x - 0.3, y - 0.3, 2, r * 0.69, r * 0.48, 0.8, "#d2d1bd");
}
// Blue water in the basin, and the two little falling streams
part("water", [24, 23, 5]);
for (let x = 10; x <= 38; x++) for (let y = 13; y <= 33; y++) {
const d = ((x-cx)/13)**2 + ((y-cy)/9.7)**2;
if (d < 1) {
set(x, y, 5, rand() < 0.18 ? "#58bbcb" : "#247d9c");
if (d < 0.93)
set(x, y, 6, rand() < 0.15 ? "#8cdddd" :
rand() < 0.4 ? "#368eac" : "#247d9c");
}
}
for (let z = 22; z <= 25; z++)
set(24, 32, z, z % 2 ? "#92dce3" : "#43abc5");
for (let z = 10; z <= 14; z++)
set(24, 14, z, z % 2 ? "#a0e5e5" : "#4eb4cf");
for (const [x,y] of [[22,15],[26,16],[23,17],[25,13]])
set(x,y,7,"#a1e2df");
animate("water", {
type: "colors", palette: ["#176c98", "#268daf", "#54b8ce", "#91dce0"],
pattern: "wave", glow: 0.16
});
part("body");
// Red lacquered wooden pivot frame
for (const x of [16, 32]) {
box(x-2, 20, 7, x+2, 27, 8, "#61352d"); // feet
box(x-1, 22, 9, x+1, 24, 19, "#9e3d30");
box(x-1, 22, 10, x-1, 24, 18, "#ca5940");
box(x-1, 21, 10, x+1, 21, 11, "#d19a43");
box(x-1, 21, 17, x+1, 21, 18, "#d19a43");
}
box(16, 26, 11, 32, 27, 13, "#71382c");
box(17, 26, 13, 31, 26, 13, "#d0833c");
for (const x of [14, 34]) {
cylinder(x, 23, 18, 1.7, 1, "#b98a47", "x");
set(x, 23, 18, "#5b4735");
}
// Fixed upright bamboo supply pipe behind the basin
cylinder(24, 40, 1, 2.4, 27, "#338454");
for (let z = 2; z <= 27; z++) {
set(23, 38, z, "#67ae64");
set(26, 40, z, "#236b48");
}
for (const z of [5, 13, 21, 27]) {
cylinder(24, 40, z, 2.8, 1, "#276544");
set(23, 38, z, "#a4c378");
}
// Bent spout pointing toward the receiving tube
for (let y = 32; y <= 40; y++) {
for (let x = 22; x <= 26; x++) for (let z = 25; z <= 29; z++) {
const d = (x-24)**2 + (z-27)**2;
if (d <= 6.3) set(x,y,z, z >= 28 ? "#72b96a" : "#358753");
}
set(23,y,29,"#a0cf79");
}
for (const y of [35, 39]) {
for (let x = 22; x <= 26; x++) for (let z = 25; z <= 29; z++)
if ((x-24)**2 + (z-27)**2 >= 3.5 &&
(x-24)**2 + (z-27)**2 <= 7)
set(x,y,z,"#266a47");
}
for (let x = 22; x <= 26; x++) for (let z = 25; z <= 29; z++)
if ((x-24)**2 + (z-27)**2 < 2.5) set(x,32,z,"#193f37");
// The rocking, open-ended bamboo clapper
part("clapper", [24, 23, 18]);
for (let y = 13; y <= 34; y++) {
for (let x = 20; x <= 28; x++) for (let z = 14; z <= 22; z++) {
const d = (x-24)**2 + (z-18)**2;
if (d > 12.3) continue;
const openEnd = y <= 14 || y >= 33;
if (openEnd && d < 5.1) continue;
let c = z >= 20 ? "#86bd65" : z <= 16 ? "#286f45" : "#4a9b58";
if (x <= 22 && z >= 17) c = "#a4cf79";
if (rand() < 0.045) c = "#387d4c";
if ([17, 24, 30].includes(y) && d >= 5.1) c = "#2a7148";
if ((y === 13 || y === 34) && d >= 5.1) c = "#b9c878";
set(x, y, z, c);
}
}
// Dark visible interiors of the cut bamboo ends
for (const y of [14, 33])
for (let x = 23; x <= 25; x++) for (let z = 17; z <= 19; z++)
if ((x-24)**2 + (z-18)**2 <= 2)
set(x, y, z, "#244f3e");
animate("clapper", { type: "swing", axis: "x", speed: 1.5, amplitude: 0.4 });
part("body");import { draw } from "./assets/voxel";
import { shishiOdoshi } from "./assets/shishi-odoshi";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, shishiOdoshi, 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 shishi-odoshi
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["shishi-odoshi"] })
# Queda en client/assets/shishi-odoshi.ts
# https://fogon.page/object/shishi-odoshi