← MedievalObjeto 3Dfogon/casa-de-entramado
Casa de entramado
Arrastrá para girarlo// «Casa de entramado» · gpt-6-sol (medium)
// A medieval half-timbered house: a grey stone ground floor with an arched wooden door, an upper floor that juts out a little over the street, cream plaster walls crossed by dark brown timber beams in vertical, horizontal and diagonal X patterns, small windows with wooden shutters and a flower box, a steep red clay tiled roof with a stone chimney.
const stone = ["#928d80", "#a49f91", "#817d72", "#b5afa0"];
const plaster = ["#e9d9b5", "#f0e2c4", "#dfcda8"];
const wood = "#493023";
const woodLight = "#67452d";
const roof = ["#a84e39", "#b75a40", "#994331", "#c36b49"];
function roofHeight(x) {
return 29 + Math.floor((19 - Math.abs(x - 24)) * 0.79);
}
// Stone ground floor and foundation.
box(8, 10, 0, 39, 39, 15, stone[0]);
box(7, 9, 0, 40, 40, 1, "#777469");
for (let x = 8; x <= 39; x++) {
for (let z = 2; z <= 15; z++) {
set(x, 9, z, stone[Math.floor(rand() * stone.length)]);
set(x, 40, z, stone[Math.floor(rand() * stone.length)]);
}
}
for (let y = 10; y <= 39; y++) {
for (let z = 2; z <= 15; z++) {
set(7, y, z, stone[Math.floor(rand() * stone.length)]);
set(40, y, z, stone[Math.floor(rand() * stone.length)]);
}
}
// Uneven stone courses and occasional moss.
for (let z = 3; z <= 14; z += 3) {
for (let x = 9 + (z % 2) * 2; x < 39; x += 6) {
set(x, 8, z, "#706e65");
if (rand() < 0.22) set(x + 1, 8, z, "#69735b");
}
}
for (let i = 0; i < 85; i++) {
const x = 8 + Math.floor(rand() * 32);
const z = 2 + Math.floor(rand() * 14);
set(x, 8, z, rand() < 0.3 ? "#68745b" : "#bbb5a5");
}
box(7, 8, 14, 40, 40, 16, "#777164");
box(8, 8, 15, 39, 40, 15, "#b4aa95");
// Stoop and recessed arched doorway.
box(17, 5, 0, 30, 9, 0, "#aaa392");
box(19, 7, 1, 28, 9, 1, "#c2b8a3");
for (let z = 1; z <= 10; z++)
box(19, 9, z, 28, 12, z, null);
box(21, 9, 11, 26, 12, 11, null);
box(23, 9, 12, 24, 12, 12, null);
box(20, 9, 1, 27, 9, 9, woodLight);
box(21, 9, 10, 26, 9, 10, woodLight);
box(23, 9, 11, 24, 9, 11, woodLight);
for (let x = 21; x <= 27; x += 2)
box(x, 8, 2, x, 8, 9, wood);
for (const z of [3, 8]) {
box(20, 7, z, 27, 7, z, "#242522");
for (const x of [21, 24, 27]) set(x, 6, z, "#c4b99a");
}
set(26, 6, 5, "#d1a85b");
box(18, 8, 1, 19, 9, 10, "#b5ad9c");
box(28, 8, 1, 29, 9, 10, "#b5ad9c");
for (let x = 19; x <= 28; x++) {
const h = x < 21 || x > 26 ? 10 : x < 23 || x > 24 ? 11 : 12;
set(x, 8, h, x % 2 ? "#c2baaa" : "#827d70");
}
// Small ground-floor windows with heavy stone surrounds.
for (const [a, b] of [[11, 15], [32, 36]]) {
box(a, 8, 5, b, 9, 10, "#262f34");
box(a + 1, 7, 6, b - 1, 7, 9, "#52717b");
box(a, 6, 4, b, 8, 4, "#c2b9a6");
box(a, 6, 11, b, 8, 11, "#c2b9a6");
box(a - 1, 7, 5, a - 1, 8, 10, "#b2aa99");
box(b + 1, 7, 5, b + 1, 8, 10, "#b2aa99");
box(Math.floor((a + b) / 2), 6, 5, Math.floor((a + b) / 2), 6, 10, wood);
}
// Projecting upper floor, cream plaster and timber undercarriage.
box(6, 7, 16, 41, 40, 29, plaster[0]);
for (let x = 6; x <= 41; x++)
for (let z = 17; z <= 29; z++)
if (rand() < 0.17) set(x, 6, z, plaster[1 + Math.floor(rand() * 2)]);
box(5, 6, 16, 42, 41, 17, wood);
box(6, 7, 18, 41, 40, 18, woodLight);
box(6, 6, 28, 41, 41, 29, wood);
for (const x of [8, 15, 24, 33, 40]) {
box(x, 7, 13, x + 1, 10, 16, wood);
line(x, 7, 13, x, 5, 17, 0, woodLight);
}
// Front half-timbering.
box(6, 6, 17, 41, 6, 18, wood);
box(6, 6, 27, 41, 6, 28, wood);
for (const x of [6, 10, 20, 28, 39, 41])
box(x, 6, 18, x, 6, 28, wood);
line(20, 6, 19, 28, 6, 27, 0, wood);
line(28, 6, 19, 20, 6, 27, 0, wood);
line(6, 6, 19, 10, 6, 26, 0, wood);
line(39, 6, 19, 41, 6, 25, 0, wood);
// Side framing, visible from an angle.
for (const side of [5, 42]) {
for (const y of [8, 17, 26, 39])
box(side, y, 18, side, y, 28, wood);
for (const z of [18, 27])
box(side, 8, z, side, 39, z, wood);
line(side, 18, 19, side, 25, 26, 0, wood);
line(side, 25, 19, side, 18, 26, 0, wood);
line(side, 27, 19, side, 38, 26, 0, wood);
line(side, 38, 19, side, 27, 26, 0, wood);
}
// Two leaded-glass upper windows and their open shutters.
for (const [a, b] of [[12, 18], [30, 36]]) {
box(a, 5, 21, b, 7, 26, "#302b26");
box(a + 1, 5, 22, b - 1, 5, 25, "#547782");
for (const x of [a + 2, a + 4]) box(x, 4, 22, x, 4, 25, wood);
box(a + 1, 4, 23, b - 1, 4, 23, wood);
set(a + 1, 3, 25, "#a8b9b2");
box(a - 1, 4, 20, b + 1, 5, 20, woodLight);
box(a - 1, 4, 26, b + 1, 5, 26, wood);
for (const [s, e] of [[a - 3, a - 1], [b + 1, b + 3]]) {
box(s, 4, 21, e, 4, 26, woodLight);
box(s, 3, 22, e, 3, 22, wood);
box(s, 3, 25, e, 3, 25, wood);
}
}
// Flower box on the left window.
box(11, 3, 19, 19, 5, 20, "#69452d");
box(11, 2, 20, 19, 2, 20, "#3e3026");
for (let x = 12; x <= 18; x++) {
set(x, 3, 21, "#527445");
set(x, 3, 22, "#648846");
if (x % 2 === 0) {
set(x, 2, 22, x % 4 ? "#e9ae62" : "#c65b67");
set(x, 3, 23, "#edcb80");
}
}
// Plastered triangular gables beneath the steep roof.
for (let x = 7; x <= 41; x++) {
for (let z = 30; z <= roofHeight(x) - 2; z++) {
box(x, 7, z, x, 9, z, plaster[Math.floor(rand() * 3)]);
box(x, 39, z, x, 40, z, plaster[0]);
}
}
box(23, 6, 29, 24, 6, 41, wood);
line(9, 6, 30, 23, 6, 41, 0, wood);
line(39, 6, 30, 24, 6, 41, 0, wood);
line(15, 6, 31, 23, 6, 39, 0, wood);
line(32, 6, 31, 24, 6, 39, 0, wood);
line(15, 6, 31, 23, 6, 33, 0, wood);
line(32, 6, 31, 24, 6, 33, 0, wood);
box(21, 5, 35, 26, 6, 38, wood);
box(22, 4, 36, 25, 4, 37, "#587580");
box(23, 3, 36, 23, 3, 37, wood);
// Layered red clay roof, with staggered rows of individual tiles.
for (let x = 4; x <= 44; x++) {
const h = roofHeight(x);
for (let y = 4; y <= 43; y++) {
for (let z = h - 2; z <= h; z++) {
const stagger = (Math.floor(y / 3) + Math.floor(x / 3)) % 3;
const c = z === h
? roof[(stagger + (rand() < 0.15 ? 1 : 0)) % 4]
: "#743c31";
set(x, y, z, c);
}
if (y % 3 === 0 && x % 4 === (Math.floor(y / 3) % 2) * 2)
set(x, y, h + 1, "#d17a52");
}
}
for (let y = 4; y <= 43; y++)
box(23, y, 44, 25, y, 44, y % 3 ? "#7b3e32" : "#a4543d");
// Stone chimney piercing the right-hand slope.
box(32, 29, 36, 36, 34, 44, "#928d82");
for (let z = 37; z <= 44; z++)
for (let y = 29; y <= 34; y++)
set(32, y, z, stone[Math.floor(rand() * stone.length)]);
box(31, 28, 43, 37, 35, 44, "#b7afa0");
box(32, 29, 45, 36, 34, 45, "#777268");
box(33, 30, 45, 35, 33, 45, "#353331");
for (const z of [38, 41])
box(31, 29, z, 32, 34, z, "#746f66");
// Hanging heraldic sign beside the entrance.
box(34, 7, 11, 34, 9, 15, wood);
box(34, 5, 14, 39, 6, 14, "#272726");
box(37, 4, 8, 41, 4, 13, "#c6a35a");
box(38, 3, 9, 40, 3, 12, "#263d70");
set(39, 2, 11, "#e4c371");
set(39, 2, 10, "#e4c371");
set(38, 2, 10, "#e4c371");
set(40, 2, 10, "#e4c371");import { draw } from "./assets/voxel";
import { casaDeEntramado } from "./assets/casa-de-entramado";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, casaDeEntramado, 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 casa-de-entramado
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["casa-de-entramado"] })
# Queda en client/assets/casa-de-entramado.ts
# https://fogon.page/object/casa-de-entramado