← FantasíaObjeto 3Dfogon/hongo-gigante
Hongo gigante
Arrastrá para girarlo// «Hongo gigante» · gpt-6-sol (medium)
// A giant fairy-tale mushroom: a thick slightly curved cream-white stem with a ring (skirt) near the top, and a big wide dome cap, bright red with chunky white round spots, pale pink gills visible under the rim. Two tiny mushrooms of the same kind at its foot on a small patch of green grass and moss.
const soil = "#514c48";
const moss = ["#466747", "#568055", "#67935b", "#779e62", "#385e48"];
const cream = ["#e2d5b8", "#f1e6d0", "#fff3df"];
const red = ["#a82535", "#ca3041", "#e43b49", "#f04b53"];
const pink = ["#a96b7b", "#d69aa5", "#f2c5c7"];
// An uneven little island of grass and moss.
for (let x = 2; x <= 46; x++) {
for (let y = 6; y <= 43; y++) {
const a = Math.atan2(y - 24, x - 24);
const edge = 1 + 0.055 * Math.sin(7 * a) + 0.04 * Math.sin(13 * a);
const d = Math.hypot((x - 24) / 21, (y - 24) / 17);
if (d > edge || (d > edge - 0.035 && rand() < 0.35)) continue;
set(x, y, 0, soil);
set(x, y, 1, moss[Math.floor(rand() * moss.length)]);
if (rand() < 0.14) set(x, y, 2, moss[Math.floor(rand() * moss.length)]);
}
}
// Thick stem, with its center gently wandering as it grows.
function stemCenter(z) {
return [22.7 + 0.115 * z + 0.35 * Math.sin(z / 5), 24.5 - 0.025 * z];
}
for (let z = 2; z <= 30; z++) {
const [cx, cy] = stemCenter(z);
const radius = z < 7 ? 6.4 - z * 0.12 : 5.55 - (z - 7) * 0.038;
for (let x = 16; x <= 33; x++) for (let y = 17; y <= 32; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d > radius) continue;
let color = y < cy - 1 ? cream[2] : cream[1];
if (x > cx + 2 || y > cy + 2) color = cream[0];
if (rand() < 0.055) color = cream[Math.floor(rand() * 3)];
set(x, y, z, color);
}
}
// Soft vertical folds in the stem.
for (let z = 5; z < 23; z++) {
const [cx, cy] = stemCenter(z);
for (const angle of [0.45, 1.6, 2.9, 4.15, 5.5]) {
const r = z < 7 ? 5.8 : 5.1 - (z - 7) * 0.038;
const x = Math.round(cx + r * Math.cos(angle));
const y = Math.round(cy + r * Math.sin(angle));
if (get(x, y, z) && rand() < 0.7) set(x, y, z, "#d9c9ab");
}
}
// The pale, radiating gills beneath the enormous cap.
for (let x = 5; x <= 43; x++) for (let y = 5; y <= 43; y++) {
const dx = x - 24, dy = y - 24;
const q = Math.hypot(dx / 18.6, dy / 18.1);
if (q > 1) continue;
const angle = Math.atan2(dy, dx);
const rib = Math.abs(Math.sin(angle * 30));
set(x, y, 28, rib < 0.27 ? pink[0] : pink[1]);
set(x, y, 29, rib < 0.19 ? pink[1] : pink[2]);
if (q > 0.38 && q < 0.94 && rib < 0.16) {
set(x, y, 27, pink[0]);
}
}
// A flared, drooping skirt around the upper stem.
for (let z = 23; z <= 27; z++) {
const [cx, cy] = stemCenter(z);
const outer = [7.6, 8.5, 8.6, 7.7, 6.2][z - 23];
for (let x = 16; x <= 35; x++) for (let y = 15; y <= 34; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d < 3.8 || d > outer) continue;
const scallop = 0.35 * Math.sin(Math.atan2(y - cy, x - cx) * 12);
if (d > outer - 0.4 + scallop) continue;
set(x, y, z, z <= 24 ? "#d8bfae" : z === 25 ? "#f0dbc5" : "#fff0d8");
}
}
// Rounded red rim: the lip hides the edge of the gills.
for (let z = 29; z <= 31; z++) {
for (let x = 4; x <= 44; x++) for (let y = 4; y <= 44; y++) {
const q = Math.hypot((x - 24) / 19.3, (y - 24) / 18.8);
if (q < (z === 29 ? 0.92 : 0.88) || q > 1) continue;
set(x, y, z, z === 29 ? red[0] : red[1]);
}
}
// Solid, broad storybook dome.
for (let z = 30; z <= 44; z++) {
const t = (z - 30) / 14;
const profile = Math.sqrt(Math.max(0, 1 - t * t));
for (let x = 4; x <= 44; x++) for (let y = 4; y <= 44; y++) {
const q = Math.hypot((x - 24) / 19.2, (y - 24) / 18.7);
if (q > profile) continue;
let color = z < 33 ? red[1] : z > 39 ? red[3] : red[2];
if (y > 29 && rand() < 0.18) color = red[1];
if (rand() < 0.065) color = red[Math.floor(rand() * 4)];
set(x, y, z, color);
}
}
// Plump ivory spots follow the curved surface rather than floating above it.
const spots = [
[12, 15, 2.6, 2.5], [24, 10, 3.0, 2.3], [35, 14, 2.7, 2.4],
[17, 9, 1.5, 1.5], [29, 7, 1.6, 1.3],
[8, 23, 2.0, 2.7], [40, 23, 2.0, 2.5],
[16, 25, 2.3, 2.0], [30, 22, 2.5, 2.2],
[22, 18, 1.5, 1.7], [36, 30, 2.1, 2.0],
[12, 34, 2.0, 2.0], [25, 33, 2.9, 2.3],
[19, 39, 1.5, 1.3], [32, 38, 1.7, 1.4]
];
for (const [sx, sy, rx, ry] of spots) {
for (let x = Math.floor(sx - rx - 1); x <= sx + rx + 1; x++)
for (let y = Math.floor(sy - ry - 1); y <= sy + ry + 1; y++) {
const s = ((x - sx) / rx) ** 2 + ((y - sy) / ry) ** 2;
if (s > 1) continue;
const q = ((x - 24) / 19.2) ** 2 + ((y - 24) / 18.7) ** 2;
if (q >= 0.99) continue;
const top = Math.floor(30 + 14 * Math.sqrt(1 - q));
if (top < 31) continue;
set(x, y, top + 1, s > 0.72 ? "#ead9d1" : "#fff5e8");
if (s < 0.38) set(x, y, top + 2, "#fffaf0");
}
}
// Two little matching mushrooms nestled in the foreground grass.
function littleMushroom(cx, cy, base, r, height) {
const capZ = base + height;
for (let z = base; z <= capZ; z++) {
const stemR = z === base ? 1.9 : 1.35;
for (let x = cx - 2; x <= cx + 2; x++)
for (let y = cy - 2; y <= cy + 2; y++)
if (Math.hypot(x - cx, y - cy) <= stemR)
set(x, y, z, y < cy ? "#fff0d9" : "#ddc9b1");
}
for (let x = Math.floor(cx - r); x <= cx + r; x++)
for (let y = Math.floor(cy - r); y <= cy + r; y++) {
const q = ((x - cx) / r) ** 2 + ((y - cy) / (r * 0.9)) ** 2;
if (q > 1) continue;
set(x, y, capZ, "#e7acb0");
if (q > 0.75) set(x, y, capZ + 1, "#b82d41");
const domeHeight = Math.floor((r * 0.8 + 0.5) * Math.sqrt(1 - q));
for (let dz = 1; dz <= domeHeight + 1; dz++)
set(x, y, capZ + dz, dz === 1 ? "#ce3545" : "#eb4550");
}
for (const [ox, oy, size] of [[-0.46, -0.28, 1.1], [0.43, -0.12, 0.9], [0.1, 0.38, 0.7]]) {
const sx = Math.round(cx + ox * r), sy = Math.round(cy + oy * r);
for (let x = sx - 1; x <= sx + 1; x++)
for (let y = sy - 1; y <= sy + 1; y++) {
if (Math.hypot(x - sx, y - sy) > size) continue;
let top = capZ;
for (let z = capZ; z <= capZ + Math.ceil(r) + 2; z++)
if (get(x, y, z)) top = z;
set(x, y, top + 1, "#fff5e7");
}
}
}
littleMushroom(10, 15, 2, 4.5, 5);
littleMushroom(38, 17, 2, 3.6, 4);
// Tufts, mossy mounds, tiny flowers and luminous fairy-tale dew.
for (let i = 0; i < 105; i++) {
const x = 4 + Math.floor(rand() * 41);
const y = 8 + Math.floor(rand() * 34);
if (!get(x, y, 1) || (x > 17 && x < 32 && y > 17 && y < 32)) continue;
if (rand() < 0.65) {
set(x, y, 2, rand() < 0.5 ? "#79a965" : "#4b7851");
if (rand() < 0.28) set(x, y, 3, "#8db76c");
} else {
set(x, y, 2, "#527f73");
set(x, y, 3, rand() < 0.5 ? "#73e5d2" : "#bc84db");
}
}
for (const [x, y] of [[7, 26], [16, 12], [34, 11], [42, 28], [29, 37]]) {
set(x, y, 2, "#46826a");
set(x, y, 3, "#e0ac58");
set(x - 1, y, 3, "#f7d47a");
set(x + 1, y, 3, "#f7d47a");
set(x, y - 1, 3, "#f7d47a");
set(x, y + 1, 3, "#f7d47a");
}import { draw } from "./assets/voxel";
import { hongoGigante } from "./assets/hongo-gigante";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, hongoGigante, 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 hongo-gigante
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["hongo-gigante"] })
# Queda en client/assets/hongo-gigante.ts
# https://fogon.page/object/hongo-gigante