← Antiguo y prehistoriaObjeto 3Dfogon/menhires
Menhires
Arrastrá para girarlo// «Menhires» · gpt-6-sol (medium)
// A small Stonehenge-like circle of tall grey standing stones on a patch of grass: about six upright rough stone slabs in a ring, with two of them joined on top by a flat horizontal lintel stone, plus one fallen stone lying on the grass. Stones in several greys with green moss spots.
// Uneven, grassy patch of earth.
for (let x = 3; x <= 44; x++) {
for (let y = 3; y <= 44; y++) {
const dx = x - 24, dy = y - 24;
const angle = Math.atan2(dy, dx);
const edge = 19.5 + 0.8 * Math.sin(7 * angle) + 0.6 * Math.sin(13 * angle);
if (Math.hypot(dx, dy) > edge) continue;
set(x, y, 0, rand() < 0.2 ? "#594e3a" : "#695a40");
set(x, y, 1, rand() < 0.25 ? "#695b3e" : "#756543");
set(x, y, 2, ["#647b40", "#71884a", "#7c9150", "#829453"][Math.floor(rand() * 4)]);
if (rand() < 0.045) set(x, y, 3, "#829653");
}
}
// Chunky, slightly crooked slabs, with chipped edges and patchy moss.
function standingStone(cx, cy, w, d, height, lean) {
for (let z = 3; z < 3 + height; z++) {
const level = z - 3;
const shift = Math.round(lean * level / height + 0.55 * Math.sin(level * 0.38 + cx));
const narrowing = level > height - 5 ? 1 : 0;
const x0 = Math.round(cx - w / 2) + shift;
const x1 = x0 + w - 1 - narrowing;
const y0 = Math.round(cy - d / 2);
const y1 = y0 + d - 1;
for (let x = x0; x <= x1; x++) {
for (let y = y0; y <= y1; y++) {
const edge = x === x0 || x === x1 || y === y0 || y === y1;
const corner = (x === x0 || x === x1) && (y === y0 || y === y1);
if (corner && rand() < 0.48) continue;
if (edge && (level === 0 || level === height - 1) && rand() < 0.13) continue;
let color = y === y0 ? "#9da49d" : "#878f89";
if (x === x1 || y === y1) color = "#6f7974";
if (level === height - 1) color = "#b0b5a8";
if (rand() < 0.11) color = rand() < 0.5 ? "#777f79" : "#a5aaa0";
// Moss gathers in broad, irregular patches on the lower faces.
const mossPatch = Math.sin(x * 1.7 + z * 0.55 + cy) +
Math.cos(y * 2.1 - z * 0.34 + cx);
if (edge && level < height * 0.72 &&
mossPatch > 1.05 && rand() < 0.73)
color = rand() < 0.45 ? "#667d4a" : "#778a54";
set(x, y, z, color);
}
}
}
}
// Six stones around an open center; the paired front stones support a lintel.
standingStone(16, 13, 6, 5, 23, -1);
standingStone(32, 13, 6, 5, 23, 1);
standingStone(10, 25, 5, 7, 20, -1);
standingStone(39, 25, 5, 7, 22, 1);
standingStone(17, 35, 7, 5, 21, 1);
standingStone(32, 35, 6, 5, 24, -1);
// Broad, flat lintel, with an uneven silhouette and a sunlit top.
for (let z = 26; z <= 30; z++) {
for (let x = 12; x <= 36; x++) {
for (let y = 10; y <= 16; y++) {
const corner = (x < 14 || x > 34) && (y === 10 || y === 16);
if (corner && rand() < 0.6) continue;
if (z === 30 && (x === 12 || x === 36) && rand() < 0.7) continue;
let color = z === 30 ? "#b2b5a7" :
y === 10 ? "#969d94" :
y === 16 ? "#747e78" : "#898f87";
if (rand() < 0.09) color = "#a5aa9f";
if ((y === 10 || z === 30) &&
Math.sin(x * 0.8 + z) > 0.8 && rand() < 0.45)
color = "#748651";
set(x, y, z, color);
}
}
}
// One long fallen slab in the clearing, lying across the grass.
for (let x = 21; x <= 34; x++) {
for (let y = 20; y <= 25; y++) {
for (let z = 3; z <= 7; z++) {
if ((x === 21 || x === 34) && (y === 20 || y === 25) && rand() < 0.8) continue;
if (z === 7 && (y === 20 || y === 25) && rand() < 0.55) continue;
let color = z === 7 ? "#a9aea3" :
y === 20 ? "#999f96" : "#767f79";
if (rand() < 0.12) color = "#8a9189";
if (z >= 6 && Math.sin(x * 0.9 + y * 1.2) > 1.1)
color = "#738650";
set(x, y, z, color);
}
}
}
// Sparse grass tufts and little stones around the monument.
for (let i = 0; i < 140; i++) {
const x = 5 + Math.floor(rand() * 38);
const y = 5 + Math.floor(rand() * 38);
if (!get(x, y, 2) || get(x, y, 3)) continue;
if (rand() < 0.78) {
set(x, y, 3, rand() < 0.5 ? "#92a55a" : "#587642");
if (rand() < 0.25) set(x, y, 4, "#869c55");
} else {
set(x, y, 3, rand() < 0.5 ? "#a0a39a" : "#777e76");
}
}import { draw } from "./assets/voxel";
import { menhires } from "./assets/menhires";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, menhires, 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 menhires
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["menhires"] })
# Queda en client/assets/menhires.ts
# https://fogon.page/object/menhires