← Medieval3D assetfogon/panaderia-medieval
Panadería medieval
Drag to turn it// «Panadería medieval» · gpt-6-sol (medium)
// A small medieval bakery house: cream plaster walls with dark brown timber framing, a steep red clay tile roof with a fat stone chimney, a wooden door and a front shop window with a hinged wooden counter showing round brown bread loaves and a pretzel, a hanging wooden sign with a golden bread shape, and a round stone bread oven bulging out of one side wall glowing orange inside.
const plaster = "#e9d9b5";
const plasterLight = "#f4e6c9";
const plasterShade = "#d6c39f";
const timber = "#493024";
const timberLight = "#67432b";
const timberDark = "#301f1b";
const stone = "#89877d";
const stoneLight = "#aaa89a";
const stoneDark = "#66665e";
const iron = "#252527";
const gold = "#e5b74f";
// Stone footing and solid plaster house.
box(9, 11, 0, 38, 38, 2, stoneDark);
box(10, 12, 3, 37, 37, 24, plaster);
forEach((x, y, z, color) => {
if (color === plaster && rand() < 0.075)
set(x, y, z, rand() < 0.55 ? plasterLight : plasterShade);
if (color === stoneDark && z < 3 && rand() < 0.12)
set(x, y, z, stoneLight);
});
// Heavy timber frame, with the front facing -y.
for (const x of [10, 22, 37]) {
box(x, 11, 3, x + 1, 12, 25, timber);
box(x, 37, 3, x + 1, 38, 25, timber);
}
for (const y of [12, 37]) {
box(10, y, 3, 11, y + 1, 25, timber);
box(36, y, 3, 37, y + 1, 25, timber);
}
for (const z of [4, 22]) {
box(10, 11, z, 37, 12, z + 1, timber);
box(10, 37, z, 37, 38, z + 1, timber);
box(10, 12, z, 11, 37, z + 1, timber);
box(36, 12, z, 37, 37, z + 1, timber);
}
line(11, 12, 5, 21, 12, 21, 0, timberLight);
line(22, 12, 21, 36, 12, 5, 0, timberLight);
line(11, 37, 5, 21, 37, 21, 0, timberLight);
// Steep filled gable beneath the roof.
for (let x = 10; x <= 37; x++) {
const top = Math.floor(39 - Math.abs(x - 24) * 0.9);
box(x, 12, 25, x, 37, top - 2, plasterShade);
}
box(23, 11, 25, 24, 12, 38, timber);
line(10, 11, 26, 24, 11, 39, 0, timber);
line(24, 11, 39, 37, 11, 27, 0, timber);
// Broad clay-tile roof, in overlapping courses.
for (let y = 8; y <= 41; y++) {
for (let x = 7; x <= 40; x++) {
const z = Math.floor(39 - Math.abs(x - 24) * 0.9);
const course = Math.floor(y / 3);
const tile = (Math.floor((x + (course % 2) * 2) / 3) + course) % 4;
const c = ["#a84632", "#bd5840", "#973c30", "#cb6346"][tile];
set(x, y, z - 1, "#723329");
set(x, y, z, c);
if (y % 3 === 0) set(x, y, z, "#79392e");
}
}
box(23, 8, 39, 24, 41, 40, "#78372d");
for (let y = 8; y <= 41; y += 4)
box(23, y, 40, 24, Math.min(y + 2, 41), 40, "#b8533c");
// Chimney rising through the rear roof slope.
box(30, 28, 30, 37, 35, 42, stone);
for (let z = 31; z <= 41; z += 3) {
for (let x = 30; x <= 37; x++)
if ((x + z) % 3 === 0) set(x, 27, z, stoneDark);
box(30, 28, z, 37, 28, z, stoneLight);
}
for (const x of [30, 34, 37])
box(x, 27, 33, x, 28, 35, stoneDark);
box(29, 27, 42, 38, 36, 43, stoneLight);
box(31, 29, 44, 36, 34, 44, stoneDark);
box(32, 30, 44, 35, 33, 44, "#292927");
// Front door and chunky iron fittings.
box(13, 11, 3, 20, 13, 18, timberDark);
box(14, 10, 3, 19, 10, 17, timberLight);
for (const x of [15, 17, 19])
box(x, 9, 4, x, 10, 16, x === 17 ? "#70482e" : timber);
box(12, 9, 18, 21, 12, 19, timber);
box(15, 9, 7, 19, 9, 7, iron);
box(15, 9, 14, 19, 9, 14, iron);
for (const x of [15, 19])
for (const z of [7, 14]) set(x, 8, z, stoneLight);
set(19, 8, 10, gold);
box(12, 8, 0, 21, 11, 1, stoneLight);
// Shop window: dark glass behind thick wooden mullions.
box(24, 11, 11, 35, 13, 21, timberDark);
box(25, 10, 12, 34, 10, 20, "#354849");
for (let x = 26; x <= 33; x += 3)
line(x, 9, 19, x + 1, 9, 20, 0, "#9da89a");
for (const x of [24, 29, 35])
box(x, 9, 11, x, 11, 21, timberLight);
for (const z of [11, 16, 21])
box(24, 9, z, 35, 11, z, timber);
box(23, 8, 10, 36, 12, 10, stoneLight);
// Hinged shop counter and its stout legs.
box(24, 7, 6, 35, 10, 9, timber);
for (const x of [25, 34])
box(x, 6, 2, x + 1, 8, 7, timberDark);
box(23, 4, 9, 36, 10, 10, timberLight);
for (let x = 24; x <= 35; x += 2)
box(x, 3, 9, x, 4, 10, "#825635");
box(23, 4, 9, 36, 4, 9, iron);
for (const x of [24, 35]) set(x, 3, 9, stoneLight);
// Round crusty loaves displayed on the counter.
for (const [x, y, r] of [[26, 6, 2], [32, 7, 2], [28, 9, 1]]) {
ellipsoid(x, y, 12, r, 1.5, 2, "#9d592c");
ellipsoid(x, y, 13, r - 0.3, 1, 0.8, "#c58443");
line(x - 1, y - 1, 14, x, y - 1, 14, 0, "#efc580");
line(x, y, 14, x + 1, y, 14, 0, "#e5ae68");
}
// An open, crossed pretzel beside the loaves.
for (const [x, z] of [[33, 13], [34, 14], [35, 13], [35, 12],
[34, 11], [33, 12], [32, 13], [32, 14]]) {
set(x, 5, z, "#a66330");
if ((x + z) % 3 === 0) set(x, 4, z, "#f1d18e");
}
line(32, 5, 12, 35, 5, 14, 0, "#b97737");
line(35, 5, 12, 32, 5, 14, 0, "#b97737");
// Hanging bakery sign, suspended just ahead of the roof.
for (const x of [27, 34]) {
box(x, 7, 28, x, 8, 31, iron);
box(x, 5, 27, x, 7, 27, iron);
}
box(26, 5, 23, 35, 6, 27, timberDark);
box(27, 4, 24, 34, 4, 26, timberLight);
for (const x of [27, 34])
for (const z of [24, 26]) set(x, 3, z, gold);
ellipsoid(30.5, 3, 25, 2.8, 0.5, 1.3, gold);
for (const x of [29, 31, 33]) set(x, 2, 26, "#fff0a6");
// Round bread oven bulging from the right wall.
ellipsoid(39, 27, 8, 6, 8, 7, stone);
forEach((x, y, z, color) => {
if (color === stone && x >= 38 && x <= 45 && y >= 19 &&
z >= 3 && z <= 15 && rand() < 0.16)
set(x, y, z, rand() < 0.65 ? stoneLight : stoneDark);
});
for (let z = 4; z <= 13; z += 3)
for (let y = 21 + (z % 2); y <= 34; y += 5)
for (let x = 41; x <= 45; x++)
if (get(x, y, z) && rand() < 0.7) set(x, y, z, stoneDark);
box(39, 20, 2, 44, 33, 3, stoneDark);
// Hollow out the arched, front-facing oven mouth.
for (let x = 35; x <= 43; x++)
for (let z = 3; z <= 12; z++) {
const d = ((x - 39) / 3.1) ** 2 + ((z - 7) / 4.2) ** 2;
if (d < 1)
for (let y = 17; y <= 22; y++) set(x, y, z, null);
if (d >= 0.78 && d < 1.65)
set(x, 18, z, (x + z) % 3 === 0 ? stoneLight : stoneDark);
}
box(36, 17, 3, 42, 19, 4, stoneLight);
box(37, 20, 5, 41, 21, 9, "#321d1b");
// The firelight is the only animated part.
part("oven_glow", [39, 21, 7]);
box(37, 19, 5, 41, 20, 7, "#a6301b");
box(38, 18, 6, 40, 19, 8, "#eb7424");
set(39, 18, 9, "#ffd05d");
set(38, 18, 8, "#ffae38");
set(40, 18, 8, "#ffae38");
animate("oven_glow", {
type: "colors",
palette: ["#8e241b", "#e35a1c", "#ffb335", "#ffd36a"],
pattern: "flicker",
glow: 0.7
});
part("body", [24, 24, 0]);import { draw } from "./assets/voxel";
import { panaderiaMedieval } from "./assets/panaderia-medieval";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, panaderiaMedieval, 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 panaderia-medieval
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["panaderia-medieval"] })
# It lands in client/assets/panaderia-medieval.ts
# https://fogon.page/object/panaderia-medieval