← NaturalezaObjeto 3Dfogon/laguna
Laguna
Arrastrá para girarlo// «Laguna» · gpt-6-sol (medium)
// A small irregular pond in the ground: a shallow basin of blue water in 3 shades bordered by brown mud and grey rocks, with two green lily pads and a reed clump on one side. Low and flat.
const cx = 24, cy = 24;
function distance(x, y) {
const dx = x - cx, dy = y - cy;
const a = Math.atan2(dy, dx);
const wobble = 1
+ 0.065 * Math.sin(3 * a + 0.5)
+ 0.045 * Math.sin(5 * a - 1)
+ 0.035 * Math.cos(8 * a + 0.3);
return Math.sqrt((dx / 19) ** 2 + (dy / 16) ** 2) / wobble;
}
// Solid, uneven mud basin. The rim rises gently above the water.
for (let x = 3; x <= 45; x++) {
for (let y = 5; y <= 43; y++) {
const d = distance(x, y);
if (d > 1.055) continue;
set(x, y, 0, d < 0.82 ? "#765339" : "#8e603b");
if (d > 0.79) {
set(x, y, 1, rand() < 0.22 ? "#a67447" : "#96643d");
if (d > 0.89 || (d > 0.85 && rand() < 0.55)) {
set(x, y, 2, rand() < 0.28 ? "#b5814d" : "#a36d40");
}
if (d > 0.97 && rand() < 0.17) set(x, y, 3, "#b7844f");
}
}
}
// Rounded stones embedded in the shoreline.
const rocks = [
[7, 22, 2.5], [10, 15, 2], [17, 10, 2.3],
[27, 9, 2], [37, 14, 2.6], [41, 22, 2],
[39, 32, 2.4], [31, 39, 2.1], [21, 40, 2.5],
[11, 35, 2], [5, 28, 1.7]
];
for (const [rx, ry, r] of rocks) {
ellipsoid(rx, ry, 2, r, r * 0.8, 1.55, "#87949a");
for (let x = Math.floor(rx - r); x <= Math.ceil(rx + r); x++) {
for (let y = Math.floor(ry - r); y <= Math.ceil(ry + r); y++) {
if (get(x, y, 3) === "#87949a") {
set(x, y, 3, rand() < 0.3 ? "#aebbb9" : "#9ca9aa");
}
if (get(x, y, 4) === "#87949a") set(x, y, 4, "#bdc8c3");
if (get(x, y, 3) && rand() < 0.09) set(x, y, 4, "#6b9c61");
}
}
}
// The water is its own animated part.
part("water", [24, 24, 1]);
for (let x = 5; x <= 43; x++) {
for (let y = 7; y <= 41; y++) {
const d = distance(x, y);
if (d > 0.815) continue;
set(x, y, 1, "#287db6");
set(x, y, 2, d > 0.73 ? "#55b4df" :
rand() < 0.17 ? "#81d8e8" :
rand() < 0.43 ? "#399bd2" : "#48a9dc");
}
}
for (const [x, y, length] of [
[19, 15, 4], [27, 19, 3], [35, 24, 4],
[21, 29, 4], [26, 34, 3], [12, 26, 2]
]) {
for (let i = 0; i < length; i++) {
if (distance(x + i, y) < 0.77) set(x + i, y, 3, "#a3ebef");
}
}
animate("water", {
type: "colors",
palette: ["#287db6", "#399bd2", "#55b4df", "#a3ebef"],
pattern: "wave",
glow: 0.1
});
part("body");
// Two broad, notched lily pads floating on the surface.
function lilyPad(px, py, r) {
for (let dx = -4; dx <= 4; dx++) {
for (let dy = -4; dy <= 4; dy++) {
const radial = Math.sqrt((dx / r) ** 2 + (dy / (r * 0.87)) ** 2);
const notch = dx >= 1 && dy <= 0 && dy >= -Math.ceil(dx * 0.48);
if (radial > 1 || notch) continue;
const x = px + dx, y = py + dy;
set(x, y, 3, radial > 0.75 ? "#378b48" :
rand() < 0.28 ? "#8bd957" : "#61bd49");
if (radial < 0.57 && rand() < 0.33) set(x, y, 4, "#a4e86b");
}
}
}
lilyPad(16, 21, 3.6);
lilyPad(31, 28, 3.4);
// A little water-lily blossom on one pad.
set(30, 29, 4, "#ffe18a");
for (const [dx, dy] of [[1, 0], [-1, 0], [0, 1], [0, -1]]) {
set(30 + dx, 29 + dy, 4, "#ffafd0");
}
set(30, 29, 5, "#fff3a4");
// Reeds and grassy leaves on the back-left bank.
const stems = [
[11, 34, 9], [13, 35, 11], [14, 33, 8],
[12, 32, 7], [15, 35, 9]
];
for (const [x, y, top] of stems) {
for (let z = 3; z <= top; z++) {
set(x, y, z, z > top - 2 ? "#91b753" : "#448b47");
}
if (top >= 9) {
box(x, y, top - 1, x, y, top + 1, "#b98742");
set(x, y, top + 2, "#d3ac61");
}
}
for (const [x, y, dx, dy] of [
[11, 34, -2, 0], [13, 35, 2, 1], [14, 33, 2, -1],
[12, 32, -1, -2], [15, 35, 1, 2]
]) {
line(x, y, 3, x + dx, y + dy, 6, 0, "#58aa4b");
set(x + dx, y + dy, 6, "#8bd45f");
}
// Small fresh-green tufts soften the mud between stones.
for (const [x, y] of [[18, 38], [25, 40], [35, 36], [38, 17], [9, 18], [7, 29]]) {
set(x, y, 3, "#4b9c48");
set(x, y, 4, "#80cb59");
set(x + 1, y, 3, "#73be51");
}import { draw } from "./assets/voxel";
import { laguna } from "./assets/laguna";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, laguna, 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 laguna
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["laguna"] })
# Queda en client/assets/laguna.ts
# https://fogon.page/object/laguna