← Medieval3D assetfogon/capilla
Capilla
Drag to turn it// «Capilla» · gpt-6-sol (medium)
// A small medieval stone chapel: warm grey stone walls, a steep dark slate roof, a square bell tower at the front with an open arched belfry holding a bronze bell and a small pointed spire with a gold cross on top, a round rose window above a tall arched wooden double door, and narrow arched stained glass windows (blue, red, yellow) along the sides.
// Stone chapel, centered on x=24. The front faces toward -y.
const stone = "#a99f8d", stoneLight = "#c6bcaa", stoneDark = "#807b70";
const mortar = "#938b7c", moss = "#69775a";
const slate = "#303b49", slateLight = "#485563", slateDark = "#252d38";
const wood = "#593929", woodLight = "#805337", iron = "#25282a";
const gold = "#d4a743";
// Foundations and solid stone walls.
box(9, 15, 0, 39, 42, 2, stoneDark);
box(10, 16, 3, 38, 40, 24, stone);
box(17, 4, 0, 31, 19, 2, stoneDark);
box(18, 5, 3, 30, 18, 28, stone);
// Vary exposed stone, leaving the large volumes solid.
forEach((x, y, z, color) => {
if (color !== stone) return;
if (get(x - 1, y, z) !== undefined &&
get(x + 1, y, z) !== undefined &&
get(x, y - 1, z) !== undefined &&
get(x, y + 1, z) !== undefined) return;
const r = rand();
if (r < 0.075) set(x, y, z, stoneLight);
else if (r < 0.13) set(x, y, z, mortar);
else if (r < 0.143 && z < 11) set(x, y, z, moss);
});
// Stone courses, corners, and projecting sill bands.
for (let z = 5; z <= 24; z += 5) {
for (let y = 16; y <= 40; y++) {
if (y % 5 !== 0) {
set(10, y, z, mortar);
set(38, y, z, mortar);
}
}
for (let x = 18; x <= 30; x++)
if (x % 4 !== 0) set(x, 5, z, mortar);
}
for (const x of [10, 38])
for (const y of [16, 40])
box(x, y, 3, x, y, 24, stoneLight);
for (const x of [18, 30])
for (const y of [5, 18])
box(x, y, 3, x, y, 28, stoneLight);
box(17, 4, 16, 31, 4, 16, stoneLight);
box(17, 4, 27, 31, 19, 28, stoneDark);
box(18, 4, 28, 30, 4, 28, stoneLight);
// Nave's steep, tiled slate roof.
for (let x = 8; x <= 40; x++) {
const height = 36 - Math.ceil(Math.abs(x - 24) * 0.72);
for (let y = 15; y <= 42; y++) {
const tile = (y % 4 === 0 || (x + 2 * y) % 13 === 0)
? slateLight : slate;
set(x, y, height, tile);
set(x, y, height - 1, slateDark);
if (y % 4 === 1 && x % 3 === 0)
set(x, y, height, slateLight);
}
}
box(24, 14, 36, 24, 43, 36, slateLight);
for (let y = 16; y <= 42; y += 4) {
set(8, y, 24, slateDark);
set(40, y, 24, slateDark);
}
// Three narrow pointed stained-glass windows on each side.
for (const x of [9, 39]) {
for (const cy of [22, 30, 38]) {
for (let z = 10; z <= 20; z++) {
for (let y = cy - 3; y <= cy + 3; y++) {
const d = Math.abs(y - cy);
if (z <= 17 ? d <= 3 : d <= Math.max(0, 20 - z))
set(x, y, z, stoneLight);
}
}
for (let z = 12; z <= 19; z++) {
const half = z <= 17 ? 1 : Math.max(0, 19 - z);
for (let y = cy - half; y <= cy + half; y++) {
const glass = z < 15 ? "#284e91"
: z < 18 ? "#a43a43" : "#edc461";
set(x, y, z, glass);
}
}
for (let z of [14, 17])
for (let y = cy - 1; y <= cy + 1; y++)
set(x, y, z, iron);
box(x, cy - 2, 10, x, cy + 2, 10, stoneDark);
set(x, cy, 18, gold);
}
}
// Tall double door and its stone pointed arch.
for (let z = 1; z <= 15; z++) {
const half = z <= 10 ? 4 : Math.max(0, 15 - z);
for (let x = 24 - half; x <= 24 + half; x++)
set(x, 4, z, stoneLight);
}
for (let z = 1; z <= 14; z++) {
const half = z <= 10 ? 3 : Math.max(0, 14 - z);
for (let x = 24 - half; x <= 24 + half; x++) {
if (half > 0 || x === 24)
set(x, 3, z, x === 24 ? wood : woodLight);
}
}
box(24, 3, 1, 24, 3, 12, wood);
for (const z of [3, 8])
box(21, 2, z, 27, 2, z, iron);
for (const x of [22, 26]) {
set(x, 2, 5, gold);
set(x, 2, 9, iron);
}
box(20, 2, 0, 28, 4, 0, stoneLight);
box(21, 0, 0, 27, 2, 0, stoneDark);
// Round rose window above the door: pale rim and colored radial panes.
for (let x = 19; x <= 29; x++) {
for (let z = 17; z <= 27; z++) {
const dx = x - 24, dz = z - 22;
const d2 = dx * dx + dz * dz;
if (d2 <= 25 && d2 >= 13) set(x, 4, z, stoneLight);
else if (d2 < 13) {
const glass = Math.abs(dx) <= 1 && Math.abs(dz) <= 1 ? gold
: dx * dz > 0 ? "#a73547" : "#3463a0";
set(x, 3, z, glass);
}
}
}
for (let d = -3; d <= 3; d++) {
set(24 + d, 2, 22, gold);
set(24, 2, 22 + d, gold);
}
set(24, 2, 22, "#f4d986");
// Open belfry: four stout corner piers and pointed stone arches.
for (const x of [18, 28])
for (const y of [5, 16])
box(x, y, 29, x + 2, y + 2, 35, stone);
for (let z = 33; z <= 36; z++) {
const inset = Math.max(0, 36 - z);
for (let x = 18; x <= 30; x++) {
if (x <= 20 + inset || x >= 28 - inset) {
set(x, 5, z, stoneLight);
set(x, 18, z, stoneLight);
}
}
for (let y = 5; y <= 18; y++) {
if (y <= 7 + inset || y >= 16 - inset) {
set(18, y, z, stoneLight);
set(30, y, z, stoneLight);
}
}
}
box(17, 4, 36, 31, 19, 37, stoneDark);
box(18, 5, 37, 30, 18, 37, stoneLight);
// Bell beam remains fixed; the bell itself pivots beneath it.
box(20, 10, 34, 28, 12, 35, wood);
box(20, 9, 34, 28, 9, 34, iron);
// Pointed slate spire above the square tower.
for (let z = 38; z <= 44; z++) {
const half = Math.max(0, 6 - (z - 38));
for (let x = 24 - half; x <= 24 + half; x++)
for (let y = 11 - half; y <= 11 + half; y++)
set(x, y, z, (x + y + z) % 5 === 0 ? slateLight : slate);
}
for (let x = 17; x <= 31; x++) {
set(x, 4, 38, slateDark);
set(x, 18, 38, slateDark);
}
for (let y = 4; y <= 18; y++) {
set(17, y, 38, slateDark);
set(31, y, 38, slateDark);
}
// Gilded cross at the very top.
box(24, 11, 44, 24, 11, 47, gold);
box(22, 11, 46, 26, 11, 46, gold);
set(24, 10, 47, "#ffe49a");
set(22, 10, 46, "#ffe49a");
set(26, 10, 46, "#ffe49a");
// Bronze bell: only this assembly swings.
part("bell", [24, 11, 34]);
box(23, 10, 33, 25, 12, 34, iron);
box(23, 10, 32, 25, 12, 33, "#a96c30");
box(22, 9, 30, 26, 13, 32, "#b67b38");
box(21, 9, 29, 27, 13, 30, "#d39b4c");
box(21, 9, 29, 27, 9, 29, "#edb966");
box(23, 10, 28, 25, 12, 28, iron);
animate("bell", { type: "swing", axis: "x", speed: 2, amplitude: 0.4 });
part("body");import { draw } from "./assets/voxel";
import { capilla } from "./assets/capilla";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, capilla, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: its longest side, in px
// angle: turn on the floor, in radians
// t: seconds; if it moves, that animates it# In a terminal, in the game's folder
fogon assets add capilla
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["capilla"] })
# It lands in client/assets/capilla.ts
# https://fogon.page/object/capilla