← Whole house3D assetfogon/hogar
Hogar
Drag to turn it// «Hogar» · gpt-6-sol (medium)
// A cozy brick fireplace: a wall-mounted hearth of warm red bricks with a dark arched opening, a stone mantel shelf on top with two candles and a small framed picture, and inside the opening a pile of logs with bright flames and glowing embers. A small iron tool set leaning beside it.
const brick = ["#ad5948", "#bc6650", "#c9785d", "#a95145"];
const mortar = "#dfaa90";
const stone = "#e8d8c4";
const stoneLight = "#f7e9d5";
const stoneShadow = "#b9a996";
function opening(x, z) {
if (z < 3 || z > 27) return false;
const span = z <= 17 ? 11 : Math.floor(11 * Math.sqrt(1 - ((z - 17) / 11) ** 2));
return Math.abs(x - 24) <= span;
}
// Solid brickwork, with a recessed firebox.
box(7, 19, 0, 41, 33, 29, "#8e483d");
box(7, 17, 0, 41, 19, 29, mortar);
for (let row = 0; row < 8; row++) {
const z = row * 4;
for (let x0 = 7 - (row % 2) * 3; x0 <= 41; x0 += 6) {
const shade = brick[Math.floor(rand() * brick.length)];
box(Math.max(7, x0), 17, z + 1, Math.min(41, x0 + 4), 19, Math.min(29, z + 3), shade);
if (rand() < 0.28) {
set(Math.max(7, x0) + 1, 16, z + 2, "#d48468");
}
}
for (let y0 = 20 - (row % 2) * 3; y0 <= 33; y0 += 6) {
const shade = brick[Math.floor(rand() * brick.length)];
box(7, Math.max(20, y0), z + 1, 7, Math.min(33, y0 + 4), Math.min(29, z + 3), shade);
box(41, Math.max(20, y0), z + 1, 41, Math.min(33, y0 + 4), Math.min(29, z + 3), shade);
}
}
// Cut out the tall opening; keep a dark, solid back wall.
for (let z = 3; z <= 27; z++) {
for (let x = 12; x <= 36; x++) {
if (opening(x, z)) {
box(x, 17, z, x, 29, z, null);
set(x, 30, z, z < 9 ? "#322827" : "#251f23");
if (z < 8 && rand() < 0.16) set(x, 29, z, "#7c3929");
}
}
}
// Chunky stone arch around the opening.
for (let z = 2; z <= 29; z++) {
for (let x = 10; x <= 38; x++) {
if (opening(x, z)) continue;
let nearOpening = false;
for (let dz = -2; dz <= 2; dz++) {
for (let dx = -2; dx <= 2; dx++) {
if (opening(x + dx, z + dz)) nearOpening = true;
}
}
if (nearOpening) {
box(x, 15, z, x, 18, z, rand() < 0.2 ? "#d0bcaa" : stone);
set(x, 15, z, rand() < 0.18 ? stoneLight : stone);
}
}
}
// Raised hearth, sill, and overhanging mantel.
box(7, 14, 0, 41, 35, 1, "#ad9684");
box(9, 13, 1, 39, 19, 2, "#d3bea8");
box(11, 13, 2, 37, 20, 3, stoneLight);
box(6, 15, 29, 42, 35, 30, stoneShadow);
box(5, 13, 31, 43, 36, 32, stone);
box(6, 13, 32, 42, 35, 32, stoneLight);
box(8, 14, 29, 40, 14, 30, "#fff0dc");
// A little brick chimney breast above the shelf.
box(13, 28, 33, 35, 33, 36, mortar);
for (let row = 0; row < 2; row++) {
for (let x = 13 - row * 3; x <= 35; x += 6) {
box(Math.max(13, x), 27, 33 + row * 2,
Math.min(35, x + 4), 28, 34 + row * 2,
brick[Math.floor(rand() * brick.length)]);
}
}
// Glowing coals and a criss-cross pile of walnut logs.
for (let i = 0; i < 25; i++) {
const x = 16 + Math.floor(rand() * 17);
const y = 20 + Math.floor(rand() * 9);
set(x, y, 4 + Math.floor(rand() * 3),
["#f16b2d", "#ffb33c", "#d34829"][Math.floor(rand() * 3)]);
}
line(16, 21, 5, 31, 27, 6, 2, "#70432d");
line(31, 20, 5, 17, 27, 7, 2, "#845039");
line(20, 19, 6, 30, 25, 7, 1, "#a96b42");
for (let x = 18; x <= 30; x += 4) {
set(x, 19 + Math.floor(rand() * 3), 6, "#d1995d");
set(x, 20, 7, "#4f3328");
}
// The flames are the only animated part.
part("flames", [24, 24, 7]);
const tongues = [
[19, 24, 13], [22, 25, 18], [25, 24, 15],
[28, 25, 17], [31, 24, 11]
];
for (const [x, y, top] of tongues) {
const height = top - 6;
for (let z = 7; z <= top; z++) {
const taper = 1 - (z - 7) / height;
const sway = Math.round(Math.sin(z * 0.85 + x) * (1 - taper) * 2);
const radius = z < 10 ? 2 : taper > 0.4 ? 1 : 0;
for (let dx = -radius; dx <= radius; dx++) {
for (let dy = -radius; dy <= radius; dy++) {
if (Math.abs(dx) + Math.abs(dy) <= radius + 1) {
set(x + sway + dx, y + dy, z,
z > top - 4 ? "#ffdb4b" : z < 10 ? "#ed512b" : "#ff9e30");
}
}
}
}
}
animate("flames", {
type: "colors",
palette: ["#ffdc50", "#ffad36", "#f2552c"],
pattern: "flicker",
glow: 0.9
});
part("body");
// Two candles on the mantel, with tiny warm wicks.
for (const x of [12, 37]) {
box(x - 2, 17, 33, x + 2, 20, 33, "#bd9f75");
box(x - 1, 17, 34, x + 1, 19, 37, "#fff2db");
box(x - 1, 17, 37, x + 1, 19, 37, "#fffbec");
set(x, 18, 38, "#59433c");
set(x, 18, 39, "#ffc64c");
}
// Small walnut picture frame with a cheerful pastel landscape.
box(19, 25, 33, 29, 26, 40, "#754b35");
box(20, 24, 34, 28, 24, 39, "#d79b5b");
box(21, 23, 35, 27, 23, 38, "#a8d9df");
box(21, 22, 35, 27, 22, 36, "#8bbd91");
box(23, 22, 37, 25, 22, 38, "#ffe6aa");
set(24, 21, 38, "#fff5d9");
// Compact iron tool stand beside the fireplace.
box(43, 17, 0, 46, 22, 1, "#383943");
box(44, 18, 2, 45, 21, 2, "#65616a");
line(44, 19, 2, 44, 19, 23, 0, "#3c3b43");
box(43, 18, 22, 45, 20, 23, "#56525a");
line(45, 18, 2, 46, 17, 19, 0, "#34343b");
line(43, 20, 2, 42, 19, 18, 0, "#34343b");
box(45, 16, 17, 46, 18, 19, "#55525a");
box(41, 18, 16, 43, 20, 18, "#55525a");
box(45, 16, 1, 46, 18, 3, "#45434b");
box(41, 18, 1, 43, 20, 2, "#45434b");import { draw } from "./assets/voxel";
import { hogar } from "./assets/hogar";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, hogar, 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 hogar
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["hogar"] })
# It lands in client/assets/hogar.ts
# https://fogon.page/object/hogar