← NaturalezaObjeto 3Dfogon/arroyo
Arroyo
Arrastrá para girarlo// «Arroyo» · gpt-6-sol (medium)
// A straight stream tile: a full 48-block-long channel of flowing blue water along y, with grassy banks and a few rocks at the edges, flat and low so pieces line up.
// Straight stream tile: both ends have the same open channel profile.
const grassTop = ["#68c94d", "#74d657", "#80de62"];
const grassSide = ["#4eaa3d", "#59b746", "#66c34c"];
const stone = ["#a9b5b1", "#bdc8c2", "#d0d8cf"];
// Solid ground, with raised grassy banks.
for (let y = 0; y < 48; y++) {
for (let x = 4; x <= 43; x++) {
set(x, y, 0, "#765b3d");
set(x, y, 1, x >= 13 && x <= 34 ? "#638f80" : "#785b3e");
if (x <= 12 || x >= 35) {
set(x, y, 2, grassSide[Math.floor(rand() * grassSide.length)]);
set(x, y, 3, grassTop[Math.floor(rand() * grassTop.length)]);
}
}
// A continuous pale rim makes the water's edges easy to read.
set(12, y, 3, "#b6c576");
set(35, y, 3, "#b6c576");
if (y > 3 && y < 44 && rand() < 0.24) {
set(11, y, 3, "#a9c76a");
set(36, y, 3, "#a9c76a");
}
}
// The uninterrupted water surface is its own animated part.
part("water", [24, 24, 2]);
for (let y = 0; y < 48; y++) {
for (let x = 13; x <= 34; x++) {
set(x, y, 2, "#51bde8");
// Sparse chunky ripples, kept away from the tile seams.
if (y > 2 && y < 45 && x > 14 && x < 33 &&
(x + Math.floor(y / 3)) % 9 < 3 && rand() < 0.22) {
set(x, y, 3, "#8cdef2");
}
}
}
animate("water", {
type: "colors",
palette: ["#43afe2", "#58c4ed", "#78d5f2", "#a1e5f5"],
pattern: "wave",
glow: 0.08
});
part("body", [24, 24, 0]);
// Rounded stones nestled along, rather than across, the shoreline.
const rocks = [
[9, 9, 2], [39, 16, 2], [10, 28, 2],
[38, 38, 2], [7, 42, 1], [41, 5, 1]
];
for (const [x, y, size] of rocks) {
ellipsoid(x, y, 3, size, size - 0.3, 1.5, "#9daaa5");
ellipsoid(x, y, 4, size - 0.5, size - 0.7, 0.8,
stone[Math.floor(rand() * stone.length)]);
set(x - 1, y, 4, "#88ad77");
}
// Little clumps of bright grass on the banks.
for (let i = 0; i < 43; i++) {
const left = rand() < 0.5;
const x = left ? 5 + Math.floor(rand() * 6) : 38 + Math.floor(rand() * 5);
const y = 2 + Math.floor(rand() * 44);
if (get(x, y, 3) && rand() < 0.8) {
set(x, y, 4, rand() < 0.5 ? "#4eae40" : "#87df5d");
if (rand() < 0.35) set(x + 1, y, 4, "#70ca4d");
}
}
// Small, spaced-out storybook flowers.
const flowers = [
[7, 14, "#ffe27a"], [40, 27, "#ff91b7"],
[8, 34, "#fff0a1"], [39, 44, "#ba9bef"],
[41, 11, "#ff9b83"], [6, 25, "#f5a1d1"]
];
for (const [x, y, color] of flowers) {
set(x, y, 4, "#419f48");
set(x, y, 5, color);
set(x + 1, y, 5, color);
set(x, y + 1, 5, color);
set(x, y, 6, "#fff2a6");
}import { draw } from "./assets/voxel";
import { arroyo } from "./assets/arroyo";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, arroyo, 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 arroyo
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["arroyo"] })
# Queda en client/assets/arroyo.ts
# https://fogon.page/object/arroyo