← Whole house3D assetfogon/zapatero
Zapatero
Drag to turn it// «Zapatero» · gpt-6-sol (medium)
// A shoe rack: a low open wooden rack with three slanted shelves holding pairs of shoes (red sneakers, brown boots, black shoes, pink slippers).
// Three slanted wooden shelves in a chunky, toy-like frame.
const wood = "#c88947";
const woodLight = "#e5ad67";
const woodDark = "#986033";
const walnut = "#78482e";
function shelfZ(level, y) {
return 5 + level * 11 + Math.floor((y - 11) / 7);
}
// Four sturdy corner posts.
for (const x of [4, 40]) {
box(x, 9, 0, x + 3, 12, 32, wood);
box(x, 34, 0, x + 3, 37, 36, wood);
box(x, 9, 0, x + 3, 12, 2, walnut);
box(x, 34, 0, x + 3, 37, 2, walnut);
// Lighter outer edges catch the light.
box(x, 9, 3, x, 11, 31, woodLight);
box(x, 34, 3, x, 36, 35, woodLight);
}
for (let level = 0; level < 3; level++) {
// Solid planks rise gently toward the back.
for (let y = 11; y <= 35; y++) {
const z = shelfZ(level, y);
box(7, y, z - 2, 40, y, z - 1, woodDark);
box(7, y, z, 40, y, z, y % 5 === 0 ? woodLight : wood);
set(23, y, z, woodDark); // subtle join between planks
}
const front = shelfZ(level, 11);
box(7, 10, front - 2, 40, 11, front, woodDark);
box(8, 10, front, 39, 10, front, woodLight);
box(8, 35, shelfZ(level, 35), 39, 36, shelfZ(level, 35) + 1, walnut);
// Small side lips keep the shoes on the tilted shelf.
for (let y = 12; y <= 34; y++) {
const z = shelfZ(level, y);
box(7, y, z + 1, 8, y, z + 2, woodLight);
box(39, y, z + 1, 40, y, z + 2, woodLight);
}
// Brass pegs on the front apron.
for (const x of [9, 38]) set(x, 9, front - 1, "#edc779");
}
// A shoe follows the slope of its shelf. Each pair has two separate shoes.
function shoe(cx, level, kind) {
for (let y = 14; y <= 29; y++) {
const end = y === 14 || y === 29;
const half = end ? 1 : 2;
const z = shelfZ(level, y) + 1;
for (let x = cx - half; x <= cx + half; x++) {
if (kind === "red") {
set(x, y, z, "#eee8d8"); // thick cream sole
set(x, y, z + 1, "#bd4340");
if (y >= 16 && y <= 27) {
set(x, y, z + 2, y < 19 ? "#e8645b" : "#d74e4a");
if (y >= 21 && y <= 26) set(x, y, z + 3, "#e8645b");
}
} else if (kind === "boot") {
set(x, y, z, "#694530");
set(x, y, z + 1, "#945d39");
if (y >= 16 && y <= 28) {
set(x, y, z + 2, "#ae7648");
if (y >= 21) set(x, y, z + 3, "#b77f50");
}
if (y >= 23 && y <= 28) {
for (let h = 4; h <= 8; h++)
set(x, y, z + h, h >= 7 ? "#815035" : "#a96e42");
}
} else if (kind === "black") {
set(x, y, z, "#55545a");
set(x, y, z + 1, "#26272e");
if (y >= 16 && y <= 28) {
set(x, y, z + 2, "#393a43");
if (y >= 21 && y <= 27) set(x, y, z + 3, "#42434b");
}
} else { // soft pink house slippers
set(x, y, z, "#a96a77");
set(x, y, z + 1, "#e7a8ae");
if (y >= 15 && y <= 20) set(x, y, z + 2, "#f5c7c6");
if (y >= 21 && y <= 28) set(x, y, z + 2, "#bc818b");
if (y >= 23 && y <= 27) set(x, y, z + 3, "#efb8b9");
}
}
}
if (kind === "red" || kind === "black") {
const lace = kind === "red" ? "#fff0d9" : "#b6b4ae";
for (const y of [21, 23, 25]) {
const z = shelfZ(level, y) + (kind === "red" ? 5 : 5);
for (let x = cx - 1; x <= cx + 1; x++) set(x, y, z, lace);
}
// Readable white toe cap on the red sneakers.
if (kind === "red") {
const z = shelfZ(level, 15);
box(cx - 1, 15, z + 2, cx + 1, 15, z + 2, "#fff0df");
}
}
if (kind === "boot") {
// Two little golden eyelets and a warm cuff.
for (const y of [21, 23]) {
set(cx, y, shelfZ(level, y) + 4, "#dfae6c");
}
for (let y = 23; y <= 28; y++) {
const z = shelfZ(level, y);
for (let x = cx - 2; x <= cx + 2; x++)
set(x, y, z + 9, "#71452f");
}
}
if (kind === "pink") {
// Plush strap over the front of each slipper.
for (const y of [18, 19, 20]) {
const z = shelfZ(level, y);
for (let x = cx - 2; x <= cx + 2; x++)
set(x, y, z + 3, "#f6cbd0");
}
}
}
function pair(level, kind, leftSide) {
const centers = leftSide ? [11, 17] : [30, 36];
for (const cx of centers) shoe(cx, level, kind);
}
// Two pairs per shelf, with all four styles easy to spot.
pair(0, "red", true);
pair(0, "black", false);
pair(1, "pink", true);
pair(1, "boot", false);
pair(2, "boot", true);
pair(2, "red", false);import { draw } from "./assets/voxel";
import { zapatero } from "./assets/zapatero";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, zapatero, 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 zapatero
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["zapatero"] })
# It lands in client/assets/zapatero.ts
# https://fogon.page/object/zapatero