← Whole house3D assetfogon/secarropas
Secarropas
Drag to turn it// «Secarropas» · gpt-6-sol (medium)
// A clothes dryer: a white cube similar to a washing machine but with a light grey round door with a solid lid, a big dial and two buttons on top, and a vent tube coming out of the back.
// Cozy toy-sized clothes dryer, facing -y.
const white = "#f7f6f0";
const shadow = "#d9dedc";
const trim = "#c4cccd";
const chrome = "#aeb9bb";
// Feet and solid cabinet.
for (const x of [10, 36]) {
for (const y of [12, 35]) box(x - 2, y - 2, 0, x + 2, y + 2, 3, "#9ba6a7");
}
box(7, 9, 2, 40, 39, 32, white);
box(7, 9, 2, 8, 39, 31, "#e7ebe8");
box(39, 9, 2, 40, 39, 31, "#e1e6e4");
box(8, 8, 3, 39, 9, 31, "#f3f4ef");
box(8, 9, 32, 39, 38, 33, "#ffffff");
box(8, 8, 30, 39, 9, 31, shadow);
box(8, 8, 3, 9, 9, 29, "#e2e7e4");
box(38, 8, 3, 39, 9, 29, "#dce2df");
// Subtle speckles on the broad white panels.
for (let i = 0; i < 170; i++) {
const x = 10 + Math.floor(rand() * 28);
const z = 4 + Math.floor(rand() * 25);
if (rand() < 0.65) set(x, 8, z, "#f9faf5");
}
for (let i = 0; i < 85; i++) {
const y = 12 + Math.floor(rand() * 25);
const z = 5 + Math.floor(rand() * 24);
set(40, y, z, rand() < 0.5 ? "#e7ebe8" : "#edf0ec");
}
// The dark recess remains open so the rotating drum is visible.
const cx = 24, cz = 17;
for (let x = 12; x <= 36; x++) {
for (let z = 5; z <= 29; z++) {
const d = Math.hypot(x - cx, z - cz);
if (d <= 9) {
for (let y = 8; y <= 12; y++) set(x, y, z, null);
set(x, 13, z, d > 7.7 ? "#667779" : "#34474a");
}
}
}
// Rotating drum and its chunky, colorful laundry.
part("drum", [24, 12, 17]);
for (let x = 17; x <= 31; x++) {
for (let z = 10; z <= 24; z++) {
const d = Math.hypot(x - cx, z - cz);
if (d <= 7.3) {
set(x, 11, z, d > 6.3 ? "#9baaaa" : "#71888a");
if (d > 5.3 && d < 6.2) set(x, 10, z, "#b5c1bf");
}
}
}
ellipsoid(21, 9, 19, 3, 1, 2, "#eeb89f");
ellipsoid(27, 9, 20, 3, 1, 2, "#a8d8ca");
ellipsoid(25, 9, 14, 4, 1, 2, "#f2ce79");
box(19, 8, 19, 21, 8, 20, "#f7d4bf");
box(27, 8, 20, 29, 8, 21, "#c5e9dc");
box(24, 8, 13, 27, 8, 14, "#ffe3a0");
animate("drum", { type: "spin", axis: "y", speed: 3 });
part("body");
// Round light-grey door: broad solid lid surrounding a small drum window.
for (let x = 11; x <= 37; x++) {
for (let z = 4; z <= 30; z++) {
const d = Math.hypot(x - cx, z - cz);
if (d <= 12.5 && d >= 7.5) {
set(x, 7, z, d > 11.3 ? "#aab5b7" : "#d7dedd");
set(x, 6, z, d > 11.2 ? "#b9c3c3" : "#e5e9e6");
if (d >= 8 && d <= 10.7) set(x, 5, z, "#dce3e1");
}
if (d >= 7 && d < 8.2) set(x, 4, z, "#899b9d");
}
}
// Small glass glints leave the spinning clothes clearly visible.
line(18, 3, 21, 20, 3, 23, 0, "#dceceb");
line(19, 3, 22, 22, 3, 24, 0, "#eaf4f0");
set(29, 3, 13, "#c4d9d9");
// Hinge and substantial chrome pull.
box(36, 5, 13, 38, 8, 21, chrome);
box(37, 4, 15, 39, 6, 19, "#e3e9e7");
box(10, 4, 14, 12, 6, 21, "#aebabb");
box(9, 3, 15, 11, 4, 20, "#edf0eb");
box(10, 2, 16, 11, 3, 19, "#c6d0cf");
// Raised control panel and its soft-grey top lip.
box(8, 9, 33, 39, 15, 38, "#e8ece9");
box(9, 8, 34, 38, 9, 37, "#f5f6f1");
box(8, 9, 38, 39, 16, 39, "#ffffff");
box(8, 8, 33, 39, 9, 33, "#bec9c8");
// Big circular dial, with a pointer.
for (let x = 12; x <= 20; x++) {
for (let z = 32; z <= 40; z++) {
const d = Math.hypot(x - 16, z - 36);
if (d <= 4) set(x, 7, z, "#b8c3c2");
if (d <= 3.2) set(x, 6, z, "#f6f6ef");
if (d <= 2.4) set(x, 5, z, "#d3ddda");
}
}
line(16, 4, 36, 17, 4, 38, 0, "#788b8b");
for (const x of [11, 13, 19, 21]) set(x, 8, 34, "#91a3a1");
// Two big, friendly buttons.
for (const [x, face] of [[29, "#aedacb"], [35, "#efc995"]]) {
for (let dx = -2; dx <= 2; dx++) {
for (let dz = -2; dz <= 2; dz++) {
if (dx * dx + dz * dz <= 5) {
set(x + dx, 7, 36 + dz, "#aebcba");
set(x + dx, 6, 36 + dz, face);
}
}
}
set(x - 1, 5, 37, "#f4f5ed");
}
// Short silver exhaust duct rising at the back, then projecting rearward.
cylinder(32, 40, 27, 3, 11, "#aebabb", "z");
cylinder(32, 40, 37, 3, 7, "#c3cccb", "y");
for (const y of [41, 44, 46]) {
cylinder(32, y, 37, 3.4, 1, "#929fa0", "y");
}
box(30, 40, 40, 33, 44, 40, "#e0e6e3");import { draw } from "./assets/voxel";
import { secarropas } from "./assets/secarropas";
// Every frame: standing on (x, y), the centre of its base.
draw(ctx, secarropas, 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 secarropas
# With Fogón's tools (connector)
add_assets({ slug: "<your-game>", ids: ["secarropas"] })
# It lands in client/assets/secarropas.ts
# https://fogon.page/object/secarropas