← City3D assetfogon/comisaria
Comisaría
Drag to turn it// «Comisaría» · gpt-6-sol (medium)
// A neighborhood police station: a sturdy two-story building in light grey and dark blue, a front door (-y) under a small canopy with a blue sign reading POLICIA, barred windows on the ground floor, a flag pole on the roof and a blue lamp next to the door.
const concrete = "#d9dde0";
const concreteLight = "#e9eceb";
const concreteShade = "#bec7cb";
const navy = "#193c68";
const blue = "#28649b";
const blueLight = "#4489bd";
const glass = "#79b9cf";
const glassLight = "#aed9df";
const iron = "#294351";
const brick = "#bd6c59";
// Pavement and a little street edge.
box(3, 4, 0, 44, 41, 0, "#b8bec0");
box(3, 4, 0, 44, 6, 0, "#696f73");
for (let x = 7; x < 42; x += 9) box(x, 5, 0, x + 4, 5, 0, "#e7ce71");
for (let x = 8; x <= 40; x += 8)
line(x, 7, 0, x, 10, 0, 0, "#a2a9aa");
// Solid, compact two-story building.
box(7, 11, 1, 40, 38, 31, concrete);
box(7, 11, 1, 40, 38, 3, brick);
box(7, 11, 4, 40, 11, 31, concreteLight);
// Gentle variation on exposed walls.
for (let x = 8; x < 40; x++) {
for (let z = 4; z <= 30; z++) {
if (rand() < 0.055) set(x, 11, z, concrete);
else if (rand() < 0.025) set(x, 11, z, "#f0f0ec");
}
}
for (let y = 12; y < 38; y++) {
for (let z = 4; z <= 30; z++) {
if (rand() < 0.045) {
const c = rand() < 0.5 ? concreteShade : concreteLight;
set(7, y, z, c);
set(40, y, z, c);
}
}
}
// Blue structural corners, floor band, and roof cornice.
box(7, 10, 3, 8, 11, 31, navy);
box(39, 10, 3, 40, 11, 31, navy);
box(7, 10, 13, 40, 11, 14, blue);
box(7, 10, 30, 40, 11, 31, blue);
box(6, 10, 32, 41, 39, 32, navy);
box(7, 11, 33, 40, 38, 33, "#aab8bd");
box(6, 10, 33, 41, 10, 34, blue);
box(6, 39, 33, 41, 39, 34, blue);
box(6, 11, 33, 6, 38, 34, blue);
box(41, 11, 33, 41, 38, 34, blue);
box(7, 10, 34, 40, 10, 34, blueLight);
// Warm brick accents along the ground floor.
for (let x of [9, 18, 29, 38]) {
box(x, 10, 4, x, 10, 12, brick);
box(x, 9, 4, x, 9, 4, "#d88a69");
}
// Front windows: dark frames, reflective panes, and stone sills.
function frontWindow(x0, x1, z0, z1, barred) {
box(x0 - 1, 9, z0 - 1, x1 + 1, 11, z1 + 1, navy);
box(x0, 8, z0, x1, 9, z1, glass);
box(x0, 7, z1 - 1, x1, 7, z1, glassLight);
box(x0 - 1, 7, z0 - 1, x1 + 1, 9, z0 - 1, concreteShade);
box(x0 - 1, 8, z1 + 1, x1 + 1, 9, z1 + 1, concreteLight);
if (barred) {
for (let x = x0 + 1; x <= x1; x += 3)
box(x, 7, z0, x, 7, z1, iron);
box(x0, 7, z0 + 2, x1, 7, z0 + 2, iron);
box(x0, 7, z1 - 1, x1, 7, z1 - 1, iron);
} else {
const mid = Math.floor((x0 + x1) / 2);
box(mid, 7, z0, mid, 7, z1, navy);
box(x0, 7, z0 + 3, x1, 7, z0 + 3, blue);
}
}
frontWindow(11, 16, 6, 11, true);
frontWindow(31, 36, 6, 11, true);
frontWindow(11, 16, 23, 28, false);
frontWindow(21, 26, 23, 28, false);
frontWindow(31, 36, 23, 28, false);
// Side windows keep the building legible from an angle.
for (let y of [18, 29]) {
for (let z of [7, 23]) {
box(6, y - 1, z - 1, 7, y + 4, z + 5, navy);
box(5, y, z, 5, y + 3, z + 4, glass);
box(4, y, z + 3, 4, y + 3, z + 4, glassLight);
box(4, y + 2, z, 4, y + 2, z + 4, iron);
box(5, y - 1, z - 1, 6, y + 4, z - 1, concreteShade);
box(40, y - 1, z - 1, 41, y + 4, z + 5, navy);
box(42, y, z, 42, y + 3, z + 4, glass);
box(43, y, z + 3, 43, y + 3, z + 4, glassLight);
box(43, y + 2, z, 43, y + 2, z + 4, iron);
box(41, y - 1, z - 1, 42, y + 4, z - 1, concreteShade);
}
}
// Recessed double front doors, steps, and a chunky canopy.
box(20, 9, 1, 27, 11, 11, navy);
box(21, 8, 1, 26, 9, 10, blue);
box(22, 7, 6, 25, 7, 9, glass);
box(22, 6, 8, 25, 6, 9, glassLight);
box(23, 6, 1, 23, 7, 10, navy);
box(24, 6, 4, 24, 6, 5, "#efd890");
box(20, 6, 0, 27, 10, 0, "#e1d9c9");
box(20, 7, 1, 27, 10, 1, concreteLight);
box(18, 6, 12, 29, 12, 13, navy);
box(18, 5, 13, 29, 6, 13, blueLight);
box(18, 5, 12, 29, 5, 12, blue);
box(19, 7, 11, 20, 8, 11, concreteLight);
box(27, 7, 11, 28, 8, 11, concreteLight);
// Oversized sign with hand-drawn block lettering.
box(9, 9, 15, 38, 11, 21, navy);
box(10, 8, 16, 37, 8, 20, blue);
box(9, 7, 15, 38, 8, 15, "#e8b86a");
box(9, 7, 21, 38, 8, 21, "#e8b86a");
const letters = {
P: ["111", "101", "111", "100", "100"],
O: ["111", "101", "101", "101", "111"],
L: ["100", "100", "100", "100", "111"],
I: ["111", "010", "010", "010", "111"],
C: ["111", "100", "100", "100", "111"],
A: ["111", "101", "111", "101", "101"]
};
const word = "POLICIA";
for (let i = 0; i < word.length; i++) {
const glyph = letters[word[i]];
for (let row = 0; row < 5; row++)
for (let col = 0; col < 3; col++)
if (glyph[row][col] === "1")
set(11 + i * 4 + col, 7, 20 - row, "#fff2d4");
}
// Blue beacon beside the entrance.
box(30, 8, 7, 32, 10, 8, navy);
box(30, 7, 9, 32, 9, 11, "#167bcc");
box(31, 6, 10, 31, 6, 11, "#82d8f2");
box(30, 7, 12, 32, 9, 12, navy);
// Roof equipment and the Argentine flag.
box(12, 25, 34, 17, 31, 35, concreteShade);
box(13, 26, 36, 16, 30, 36, concreteLight);
for (let x = 13; x <= 16; x++) box(x, 25, 34, x, 25, 35, navy);
box(35, 22, 34, 35, 22, 44, "#78898e");
box(34, 21, 34, 36, 23, 35, navy);
set(35, 22, 45, "#e9c66d");
for (let x = 25; x <= 34; x++) {
const y = 20 + Math.round(Math.sin((34 - x) * 0.8));
for (let z = 38; z <= 43; z++) {
const color = z === 40 || z === 41 ? "#f5f4e9" : "#76c9e3";
box(x, y, z, x, y + 1, z, color);
}
}
box(29, 18, 40, 30, 18, 41, "#eac34f");import { draw } from "./assets/voxel";
import { comisaria } from "./assets/comisaria";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, comisaria, 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 comisaria
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["comisaria"] })
# It lands in client/assets/comisaria.ts
# https://fogon.page/object/comisaria