← NaturalezaObjeto 3Dfogon/baobab
Baobab
Arrastrá para girarlo// «Baobab» · gpt-6-sol (medium)
// A baobab tree: an enormously thick bottle-shaped grey-brown trunk with a short flat crown of stubby bare branches ending in small tufts of green leaves.
// A squat, bottle-trunked baobab with a sparse, flat crown.
const cx = 24, cy = 24;
const bark = ["#776d60", "#897a68", "#988773", "#a8957d"];
const groove = "#5e584f";
const leafDark = "#398b49";
const leafMid = "#55ac51";
const leafLight = "#78c966";
const leafSun = "#9cdd76";
function trunkRadius(z) {
const profile = [
[0, 10.5], [3, 11.7], [10, 12.3], [17, 11.4],
[23, 9.4], [28, 7.1], [32, 5.6], [35, 5.1]
];
for (let i = 1; i < profile.length; i++) {
if (z <= profile[i][0]) {
const a = profile[i - 1], b = profile[i];
return a[1] + (b[1] - a[1]) * (z - a[0]) / (b[0] - a[0]);
}
}
return 5.1;
}
// Solid, gently uneven bottle-shaped trunk.
for (let z = 0; z <= 35; z++) {
const rx = trunkRadius(z);
const ry = rx * 0.89;
for (let x = Math.floor(cx - rx - 1); x <= Math.ceil(cx + rx + 1); x++) {
for (let y = Math.floor(cy - ry - 1); y <= Math.ceil(cy + ry + 1); y++) {
const dx = x - cx, dy = y - cy;
const angle = Math.atan2(dy, dx);
const edge = 0.17 * Math.sin(angle * 7 + z * 0.18)
+ 0.13 * Math.sin(angle * 11 - z * 0.11);
if ((dx * dx) / (rx * rx) + (dy * dy) / (ry * ry) <= 1 + edge / rx) {
const shade = rand();
const color = z < 5 ? bark[0]
: shade < 0.12 ? bark[0]
: shade < 0.69 ? bark[1]
: shade < 0.94 ? bark[2] : bark[3];
set(x, y, z, color);
}
}
}
}
// Chunky roots flowing out from the foot of the trunk.
for (let i = 0; i < 9; i++) {
const a = i * Math.PI * 2 / 9 + 0.12;
const reach = 12.5 + (i % 3);
const ux = Math.cos(a), uy = Math.sin(a);
line(cx + ux * 7, cy + uy * 6, 5,
cx + ux * reach, cy + uy * reach * 0.88, 0, 2.1, "#796d5d");
line(cx + ux * 9, cy + uy * 8, 3,
cx + ux * reach, cy + uy * reach * 0.88, 0, 1.2, "#998772");
}
// Broken, wandering vertical bark furrows around the trunk.
for (let i = 0; i < 17; i++) {
const angle = i * Math.PI * 2 / 17;
const bottom = 2 + i % 5;
const top = 22 + i % 9;
for (let z = bottom; z <= top; z++) {
if ((z + 3 * i) % 13 === 0 || (z + i) % 17 === 0) continue;
const a = angle + 0.045 * Math.sin(z * 0.35 + i);
const rx = trunkRadius(z), ry = rx * 0.89;
const x = Math.round(cx + (rx - 0.3) * Math.cos(a));
const y = Math.round(cy + (ry - 0.3) * Math.sin(a));
if (get(x, y, z)) set(x, y, z, groove);
if (z % 3 !== 0) {
const hx = Math.round(cx + (rx - 0.5) * Math.cos(a + 0.075));
const hy = Math.round(cy + (ry - 0.5) * Math.sin(a + 0.075));
if (get(hx, hy, z)) set(hx, hy, z, "#ab9880");
}
}
}
function tuft(x, y, z) {
// Several small overlapping pom-poms, rather than a continuous canopy.
ellipsoid(x, y, z, 2.8, 2.5, 2.1, leafDark);
ellipsoid(x - 0.8, y - 0.5, z + 0.7, 2.2, 2.1, 1.8, leafMid);
ellipsoid(x + 0.7, y + 0.3, z + 0.9, 1.8, 1.8, 1.4, leafLight);
ellipsoid(x - 0.6, y - 0.8, z + 1.6, 1.3, 1.1, 0.8, leafSun);
}
const branches = [
[18, 0, 36], [-18, 0, 36],
[ 0, 17, 36], [ 0,-17, 36],
[14, 13, 36], [-15,-12, 36],
[15,-13, 35], [-14, 14, 35]
];
branches.forEach(([dx, dy, height], i) => {
const sx = cx + dx * 0.23, sy = cy + dy * 0.23;
const mx = cx + dx * 0.65, my = cy + dy * 0.65;
line(sx, sy, 31, mx, my, 34, 2.5, "#837360");
line(mx, my, 34, cx + dx, cy + dy, height, 1.65, "#766856");
// Exposed little fork at each leafy tip.
line(cx + dx * 0.81, cy + dy * 0.81, 35,
cx + dx * 0.92 - dy * 0.1,
cy + dy * 0.92 + dx * 0.1, height + 1, 0.8, "#897761");
tuft(cx + dx, cy + dy, height + 1);
});
// A few short upright shoots fill out the center without hiding the bare limbs.
line(22, 23, 34, 19, 21, 38, 1.3, "#837360");
tuft(19, 21, 38);
line(26, 25, 34, 29, 27, 38, 1.3, "#837360");
tuft(29, 27, 38);import { draw } from "./assets/voxel";
import { baobab } from "./assets/baobab";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, baobab, 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 baobab
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["baobab"] })
# Queda en client/assets/baobab.ts
# https://fogon.page/object/baobab