← NaturalezaObjeto 3Dfogon/pino-nevado
Pino nevado
Arrastrá para girarlo// «Pino nevado» · gpt-6-sol (medium)
// A tall pine tree with 4 stacked cone tiers of dark green needles, each tier capped with thick white snow on its upper surface and a few snow drips over the edges, a little snow mound around the base of the brown trunk.
const cx = 24, cy = 24;
const greenDark = "#176b37";
const greenMid = "#208746";
const greenLight = "#2fa254";
const greenSun = "#43b664";
const snowWhite = "#ffffff";
const snowLight = "#f2faff";
const snowShade = "#dcecf2";
// Warm, chunky trunk with a few vertical bark grooves.
cylinder(cx, cy, 0, 3.2, 17, "#94603a");
for (let z = 0; z <= 16; z++) {
for (let x = 20; x <= 28; x++) {
for (let y = 20; y <= 28; y++) {
const c = get(x, y, z);
if (!c) continue;
if (rand() < 0.13) set(x, y, z, "#ac7244");
}
}
}
line(22, 21, 1, 22, 21, 12, 0, "#68442c");
line(25, 21, 3, 25, 21, 15, 0, "#70482d");
line(27, 23, 0, 27, 23, 10, 0, "#754b30");
// Soft snow piled around the foot of the tree.
for (let x = 16; x <= 32; x++) {
for (let y = 16; y <= 32; y++) {
for (let z = 0; z <= 4; z++) {
const dx = (x - cx) / 8;
const dy = (y - cy) / 7;
const dz = (z - 0.2) / 3.5;
if (dx * dx + dy * dy + dz * dz <= 1) {
set(x, y, z, z === 0 ? snowShade : (rand() < 0.16 ? snowLight : snowWhite));
}
}
}
}
const tiers = [
{ base: 6, top: 19, radius: 16.0 },
{ base: 15, top: 28, radius: 13.6 },
{ base: 24, top: 37, radius: 11.1 },
{ base: 33, top: 44, radius: 8.5 }
];
for (let t = 0; t < tiers.length; t++) {
const tier = tiers[t];
const height = tier.top - tier.base;
// Give each tier a gently scalloped, rounded outline.
function limit(x, y, z) {
const angle = Math.atan2(y - cy, x - cx);
const scallop = 0.48 * Math.sin(angle * 9 + t * 1.7)
+ 0.22 * Math.sin(angle * 15 - t);
const climb = (z - tier.base) / height;
return Math.max(0.7, tier.radius * (1 - climb) + scallop);
}
// Solid dark-green cone, with sunlit upper branches.
for (let z = tier.base; z <= tier.top; z++) {
for (let x = cx - 17; x <= cx + 17; x++) {
for (let y = cy - 17; y <= cy + 17; y++) {
const d = Math.hypot(x - cx, y - cy);
if (d > limit(x, y, z)) continue;
let color = z < tier.base + 3 ? greenDark
: z < tier.base + 7 ? greenMid : greenLight;
if (y < cy && z > tier.base + 3 && rand() < 0.22) color = greenSun;
else if (rand() < 0.09) color = greenDark;
set(x, y, z, color);
}
}
}
// A thick snow blanket follows the upper surface, leaving a broad
// green skirt visible beneath each white cap.
for (let x = cx - 16; x <= cx + 16; x++) {
for (let y = cy - 16; y <= cy + 16; y++) {
let top = -1;
for (let z = tier.base; z <= tier.top; z++) {
if (Math.hypot(x - cx, y - cy) <= limit(x, y, z)) top = z;
}
if (top < tier.base + 4) continue;
set(x, y, top, snowShade);
set(x, y, top + 1, rand() < 0.12 ? snowLight : snowWhite);
if (rand() < 0.22 && top > tier.base + 5) {
set(x, y, top - 1, snowLight);
}
}
}
// Sparse, rounded icelike snow drips spilling over the green rim.
const dripCount = t === 0 ? 11 : t === 1 ? 9 : 7;
for (let i = 0; i < dripCount; i++) {
const a = i * Math.PI * 2 / dripCount + t * 0.53;
const r = tier.radius - 2.7;
const x = Math.round(cx + Math.cos(a) * r);
const y = Math.round(cy + Math.sin(a) * r);
const lip = tier.base + 4;
const drop = 2 + Math.floor(rand() * 3);
box(x, y, lip - drop, x, y, lip, snowLight);
set(x, y, lip - drop, snowWhite);
if (rand() < 0.5) set(x + 1, y, lip - 1, snowWhite);
}
}import { draw } from "./assets/voxel";
import { pinoNevado } from "./assets/pino-nevado";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, pinoNevado, 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 pino-nevado
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["pino-nevado"] })
# Queda en client/assets/pino-nevado.ts
# https://fogon.page/object/pino-nevado