← Asian3D assetfogon/casa-de-te
Casa de té
Drag to turn it// «Casa de té» · gpt-6-sol (medium)
// A small Japanese tea house on stilts: light wooden frame, paper sliding doors in a grid pattern, a veranda around it, a dark grey thatched or tiled hip roof, and a stone path with a small stone basin in front.
const red = "#8f302b", redLight = "#b74838", redDark = "#682826";
const gold = "#d5ae63", wood = "#b98755", woodDark = "#79543c";
const paper = "#f5ebd3", paperShade = "#e6d9ba";
const stone = "#b6b6aa", stoneDark = "#858b84";
// Irregular stone path leading to the veranda.
for (let y = 0; y <= 9; y += 2) {
const shift = Math.round((rand() - 0.5) * 2);
box(21 + shift, y, 0, 27 + shift, Math.min(y + 1, 9), 0,
rand() < 0.45 ? "#d0cec0" : stone);
for (let x = 21 + shift; x <= 27 + shift; x++)
if (rand() < 0.16) set(x, y, 0, stoneDark);
}
// Stone pads and red-lacquered stilts.
for (const x of [11, 20, 29, 38])
for (const y of [12, 23, 35]) {
box(x - 1, y - 1, 0, x + 1, y + 1, 1, stoneDark);
box(x, y, 2, x + 1, y + 1, 10, redDark);
box(x, y, 8, x + 1, y + 1, 9, gold);
}
// Thick raised veranda and its warm plank decking.
box(9, 10, 9, 39, 38, 10, redDark);
box(9, 10, 11, 39, 38, 11, wood);
for (let x = 9; x <= 39; x += 3)
box(x, 10, 11, x, 38, 11, woodDark);
box(9, 10, 9, 39, 10, 10, redLight);
box(9, 38, 9, 39, 38, 10, redLight);
box(9, 10, 9, 9, 38, 10, redLight);
box(39, 10, 9, 39, 38, 10, redLight);
// Broad central stairs.
for (let i = 0; i < 4; i++) {
const y = 6 + i;
box(20, y, 1, 28, y, 2 + i * 2, redDark);
box(20, y, 3 + i * 2, 28, y, 3 + i * 2, wood);
box(20, y, 3 + i * 2, 28, y, 3 + i * 2, "#d0a872");
}
box(20, 10, 9, 28, 11, 11, wood);
// Low veranda railings, interrupted at the stairway.
for (const x of [10, 15, 34, 39]) {
box(x, 10, 12, x, 10, 17, red);
box(x, 10, 16, x, 10, 16, gold);
}
for (const [a, b] of [[10, 19], [29, 39]]) {
box(a, 10, 14, b, 10, 14, redLight);
box(a, 10, 17, b, 10, 17, red);
box(a, 10, 17, b, 10, 17, gold);
}
for (const x of [9, 39]) {
for (const y of [15, 23, 31, 37]) {
box(x, y, 12, x, y, 17, red);
set(x, y, 16, gold);
}
box(x, 15, 14, x, 37, 14, redLight);
box(x, 15, 17, x, 37, 17, gold);
}
box(9, 38, 14, 39, 38, 14, redLight);
box(9, 38, 17, 39, 38, 17, gold);
// The enclosed room: dark interior behind the sliding screens.
box(15, 16, 12, 34, 33, 12, woodDark);
box(15, 16, 13, 34, 33, 27, "#443b35");
box(15, 16, 27, 34, 33, 28, redDark);
// Corner pillars, lintels and gilded brackets.
for (const x of [14, 35])
for (const y of [15, 34]) {
box(x, y, 12, x + 1, y + 1, 29, red);
box(x, y, 26, x + 1, y + 1, 26, gold);
}
for (const y of [15, 34]) {
box(14, y, 13, 36, y, 14, redDark);
box(14, y, 27, 36, y, 29, red);
box(14, y, 27, 36, y, 27, gold);
}
for (const x of [14, 35]) {
box(x, 15, 27, x, 35, 29, red);
box(x, 15, 27, x, 35, 27, gold);
}
// Front shoji: two bright screens framing a recessed entrance.
for (const [a, b] of [[16, 21], [29, 34]]) {
box(a, 14, 15, b, 14, 26, paper);
for (let x = a; x <= b; x++)
if (rand() < 0.08) set(x, 14, 18 + Math.floor(rand() * 7), paperShade);
for (let x = a; x <= b; x += 3) box(x, 13, 15, x, 13, 26, redDark);
for (let z = 15; z <= 26; z += 3) box(a, 13, z, b, 13, z, woodDark);
box(a, 13, 15, b, 13, 15, red);
box(a, 13, 26, b, 13, 26, red);
}
box(22, 14, 15, 28, 14, 25, "#45332e");
box(22, 13, 15, 22, 13, 27, red);
box(28, 13, 15, 28, 13, 27, red);
box(22, 13, 26, 28, 13, 27, redLight);
box(24, 14, 22, 26, 14, 24, "#efd195");
set(25, 13, 21, gold);
// Paper-panelled side and rear walls.
for (const x of [14, 36]) {
for (let y = 17; y <= 32; y += 5) {
box(x, y, 15, x, y + 3, 26, paper);
for (let z = 18; z <= 24; z += 3)
box(x + (x === 14 ? -1 : 1), y, z,
x + (x === 14 ? -1 : 1), y + 3, z, woodDark);
box(x + (x === 14 ? -1 : 1), y + 2, 15,
x + (x === 14 ? -1 : 1), y + 2, 26, woodDark);
}
}
for (let x = 17; x <= 32; x += 5) {
box(x, 35, 15, x + 3, 35, 26, paperShade);
box(x + 2, 36, 15, x + 2, 36, 26, redDark);
for (let z = 18; z <= 24; z += 3)
box(x, 36, z, x + 3, 36, z, woodDark);
}
// Exposed red rafters and a gold line beneath the deep eaves.
box(8, 9, 29, 41, 40, 29, redDark);
for (let x = 10; x <= 40; x += 4) {
box(x, 8, 27, x + 1, 12, 29, red);
box(x, 37, 27, x + 1, 41, 29, red);
}
box(8, 9, 29, 41, 9, 29, gold);
box(8, 40, 29, 41, 40, 29, gold);
box(8, 9, 29, 8, 40, 29, gold);
box(41, 9, 29, 41, 40, 29, gold);
// Stepped hip roof, with alternating dark glazed tile courses.
for (let k = 0; k <= 8; k++) {
const xl = 8 + Math.floor(k * 1.2), xr = 41 - Math.floor(k * 1.2);
const yf = 9 + Math.floor(k * 1.8), yb = 40 - Math.floor(k * 1.8);
const z = 30 + k;
for (let x = xl; x <= xr; x++)
for (let y = yf; y <= yb; y++) {
let c = (k % 2) ? "#343e3d" : "#46514d";
if ((x + 1) % 4 === 0) c = "#57635b";
if (rand() < 0.065) c = "#626c62";
set(x, y, z, c);
}
}
box(18, 23, 39, 31, 26, 39, "#303a39");
box(18, 23, 40, 31, 23, 40, "#59645e");
box(18, 26, 40, 31, 26, 40, "#59645e");
// Tile-capped, upturned roof corners.
for (const x of [8, 41])
for (const y of [9, 40]) {
box(x, y, 30, x, y, 32, "#58635e");
set(x, y, 33, gold);
const ox = x === 8 ? -1 : 1, oy = y === 9 ? -1 : 1;
set(x + ox, y, 32, "#4b5753");
set(x, y + oy, 32, "#4b5753");
}
// A small white-stone water basin beside the approach.
box(34, 4, 0, 38, 8, 0, stoneDark);
box(35, 5, 1, 37, 7, 2, stone);
for (let z = 3; z <= 5; z++)
for (let x = 33; x <= 39; x++)
for (let y = 3; y <= 9; y++) {
const d = (x - 36) ** 2 + (y - 6) ** 2;
if (d >= 6 && d <= 12) set(x, y, z, z === 5 ? "#d2d1c3" : stone);
}
for (let x = 34; x <= 38; x++)
for (let y = 4; y <= 8; y++)
if ((x - 36) ** 2 + (y - 6) ** 2 < 6) set(x, y, 4, "#568f87");
set(35, 5, 4, "#a8c6ad");
// Compact garden lantern and a few cherry blossoms.
box(7, 4, 0, 9, 6, 1, stoneDark);
box(8, 5, 2, 8, 5, 5, stone);
box(6, 3, 6, 10, 7, 6, "#d4d1bd");
box(7, 4, 7, 9, 6, 9, stoneDark);
set(8, 3, 8, "#f1c586");
box(6, 3, 10, 10, 7, 10, "#c4c3b4");
box(8, 5, 11, 8, 5, 12, stone);
for (const [x, y] of [[4, 15], [5, 18], [43, 17], [44, 20]]) {
box(x, y, 0, x, y, 2, "#426a4d");
for (let i = 0; i < 8; i++) {
const dx = Math.floor(rand() * 5) - 2;
const dy = Math.floor(rand() * 5) - 2;
set(x + dx, y + dy, 2 + Math.floor(rand() * 3),
rand() < 0.65 ? "#e9a8ae" : "#f5c7c4");
}
}import { draw } from "./assets/voxel";
import { casaDeTe } from "./assets/casa-de-te";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, casaDeTe, 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 casa-de-te
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["casa-de-te"] })
# It lands in client/assets/casa-de-te.ts
# https://fogon.page/object/casa-de-te