← BásicoObjeto 3Dfogon/aljibe
Aljibe
Arrastrá para girarlo// «Aljibe» · gpt-6-sol (medium)
// Well («Aljibe»).
const stone = ["#9daaa5", "#aebbb4", "#87958f", "#bec7bd", "#788984"];
const mortar = "#64746f";
const roof = ["#a9472e", "#b95032", "#c65b39", "#d46a43", "#e0784d"];
function shade(colors) {
return colors[Math.floor(rand() * colors.length)];
}
// Irregular grassy island and pale cobblestones around the well.
for (let x = 7; x <= 41; x++) {
for (let y = 7; y <= 41; y++) {
const d = Math.hypot(x - 24, y - 24);
const edge = 15.6 + (rand() - 0.5) * 2.4;
if (d > edge) continue;
const grass = d > 12.7 || rand() < 0.16;
set(x, y, 0, shade(["#685b3d", "#786748", "#56573a"]));
set(x, y, 1, grass
? shade(["#688047", "#829450", "#526e3c", "#a0a366"])
: shade(["#9ca8a0", "#b9c3b8", "#d0d4c7", "#7c9088"]));
if (d < 12.8 && d > 10.5 && rand() < 0.56)
set(x, y, 2, shade(["#d6d9ca", "#bdc9bd", "#8f9d94"]));
if (d > 13 && rand() < 0.13)
set(x, y, 2, shade(["#476c38", "#72954a", "#a1a85b"]));
}
}
// Dark floor inside the well.
for (let x = 15; x <= 33; x++)
for (let y = 15; y <= 33; y++)
if (Math.hypot(x - 24, y - 24) < 8.1)
set(x, y, 4, shade(["#394a48", "#485b56", "#52625b"]));
// Staggered courses of stone: the middle remains open.
for (let z = 3; z <= 18; z++) {
for (let x = 12; x <= 36; x++) {
for (let y = 12; y <= 36; y++) {
const d = Math.hypot(x - 24, y - 24);
const rim = z >= 16;
if (d > (rim ? 11.4 : 10.3) || d < (rim ? 7.4 : 7.8)) continue;
const angle = Math.atan2(y - 24, x - 24);
const joint = ((Math.floor((angle + Math.PI) * 8) + (Math.floor(z / 3) % 2) * 2) % 5 === 0);
let c = shade(stone);
if (joint && z % 3 !== 0 && rand() < 0.72) c = mortar;
if (z % 4 === 3 && rand() < 0.34) c = "#72817c";
if (d < 8.6) c = shade(["#66746e", "#788681", "#89968e"]);
if (rim) c = shade(["#b6c2b7", "#d0d8c9", "#a1b0a6", "#e0dfce"]);
set(x, y, z, c);
}
}
}
// A broken, blocky pale lip on top.
for (let x = 12; x <= 36; x++)
for (let y = 12; y <= 36; y++) {
const d = Math.hypot(x - 24, y - 24);
if (d >= 7.5 && d <= 11.7)
set(x, y, 19, shade(["#cbd4c8", "#e3e3d3", "#aabbb0", "#d5dccf"]));
}
// Two square timber supports under the roof.
for (const x of [10, 37]) {
box(x, 29, 17, x + 2, 31, 32, "#754322");
box(x, 31, 18, x + 2, 31, 32, "#ad6c39");
box(x, 29, 18, x, 31, 32, "#55351f");
box(x - 1, 28, 31, x + 3, 32, 32, "#613820");
box(x, 29, 17, x + 2, 31, 18, "#654326");
}
// Little iron-and-wood crank fixed to the left post.
box(7, 30, 27, 10, 30, 28, "#60462d");
box(7, 29, 27, 8, 31, 29, "#506d74");
set(7, 28, 28, "#9da8a0");
set(6, 30, 28, "#b8874a");
// Roof plane: a broad terracotta gable with dark, thick eaves.
function roofHeight(y) {
return 43 - Math.floor(Math.abs(y - 21) * 0.64);
}
for (let y = 7; y <= 40; y++) {
const h = roofHeight(y);
for (let x = 4; x <= 44; x++) {
set(x, y, h - 2, "#5e3524");
set(x, y, h - 1, (x === 4 || x === 44 || y === 7 || y === 40) ? "#713824" : "#88412a");
set(x, y, h, shade(roof));
}
}
// Dark wood fascia below each eave.
box(4, 40, 30, 44, 40, roofHeight(40) - 1, "#6a3825");
box(4, 7, 31, 44, 7, roofHeight(7) - 1, "#704027");
box(4, 40, roofHeight(40) - 2, 44, 40, roofHeight(40) - 2, "#a44b2e");
// Raised, overlapping rows of small clay tiles.
for (let y = 8; y <= 39; y += 3) {
const h = roofHeight(y);
for (let x = 5; x <= 43; x++) {
set(x, y, h + 1, "#8b3b29");
if (y + 1 <= 39)
set(x, y + 1, roofHeight(y + 1) + 1,
shade(["#c45b38", "#d36b42", "#b64d31", "#e07549"]));
if (x % 4 === (Math.floor(y / 3) % 2 ? 1 : 3)) {
set(x, y, h + 1, "#673429");
if (y + 1 <= 39) set(x, y + 1, roofHeight(y + 1) + 1, "#97412d");
}
}
}
// Continuous ridge caps and darker end edges.
for (let x = 4; x <= 44; x++) {
set(x, 20, 44, x % 4 === 0 ? "#8c3c29" : "#cb6040");
set(x, 21, 44, x % 4 === 0 ? "#99432d" : "#dd7047");
set(x, 22, 44, x % 4 === 0 ? "#8b3c2a" : "#b95033");
}
for (const x of [4, 44])
for (let y = 7; y <= 40; y++)
set(x, y, roofHeight(y), "#824029");import { draw } from "./assets/voxel";
import { aljibe } from "./assets/aljibe";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, aljibe, 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 aljibe
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["aljibe"] })
# Queda en client/assets/aljibe.ts
# https://fogon.page/object/aljibe