← Piratas y marObjeto 3Dfogon/cabana-de-playa
Cabaña de playa
Arrastrá para girarlo// «Cabaña de playa» · gpt-6-sol (medium)
// A small beach hut on low stilts: walls of light bamboo, a thick straw thatched roof, an open front with a hammock hanging inside, a few steps down to the sand.
const sand = ["#f5dca0", "#efd194", "#ffe4ad"];
const bamboo = ["#edc774", "#f5d78d", "#dfaf60"];
const wood = "#986139";
const darkWood = "#70472f";
const straw = ["#e7b653", "#f6d276", "#d99c43", "#ffdf88"];
// A little island of sand, with a turquoise edge.
for (let x = 3; x <= 44; x++) {
for (let y = 3; y <= 44; y++) {
if (((x - 23.5) / 21) ** 2 + ((y - 23.5) / 21) ** 2 > 1.07) continue;
box(x, y, 0, x, y, 1, sand[Math.floor(rand() * sand.length)]);
if (rand() < 0.055) set(x, y, 2, "#fff0bd");
}
}
for (let x = 4; x <= 15; x++) {
for (let y = 4; y <= 9; y++) {
if (x + y < 20 && get(x, y, 1)) {
set(x, y, 1, rand() < 0.4 ? "#35bdbb" : "#54d2c7");
if (x + y >= 17) set(x, y, 2, "#eaffd7");
}
}
}
// Stilt posts and their cross-braces.
for (const x of [11, 36]) for (const y of [17, 36]) {
box(x, y, 2, x + 2, y + 2, 9, darkWood);
box(x, y, 3, x, y, 9, "#ae7948");
}
for (const x of [12, 37]) {
line(x, 18, 4, x, 35, 7, 0, wood);
line(x, 35, 4, x, 18, 7, 0, wood);
}
// Broad plank deck.
box(8, 11, 8, 40, 40, 9, darkWood);
for (let x = 8; x <= 40; x += 3) {
box(x, 11, 9, Math.min(x + 2, 40), 40, 9,
(x / 3) % 2 < 1 ? "#bc8350" : "#a97143");
box(x, 11, 10, x, 40, 10, "#d29b60");
}
box(8, 11, 7, 40, 11, 8, wood);
// Four chunky steps down toward the viewer.
for (const [y0, y1, top] of [[11, 13, 8], [9, 10, 6], [7, 8, 4], [5, 6, 2]]) {
box(20, y0, 2, 29, y1, top - 1, darkWood);
box(19, y0, top, 30, y1, top, "#bf8750");
for (let x = 21; x <= 29; x += 3)
box(x, y0, top, x, y1, top, "#e0aa68");
}
// Solid bamboo walls, leaving a generous open front.
box(10, 15, 10, 12, 38, 24, "#d9aa60");
box(36, 15, 10, 38, 38, 24, "#d9aa60");
box(13, 36, 10, 35, 38, 24, "#e7bc72");
box(13, 15, 10, 16, 16, 24, "#e7bc72");
box(32, 15, 10, 35, 16, 24, "#e7bc72");
box(10, 15, 23, 38, 17, 25, wood);
// Vertical bamboo poles and their dark joints.
for (const x of [10, 13, 16, 32, 35, 38]) {
box(x, 14, 10, x, 15, 25, bamboo[x % 3]);
for (const z of [13, 18, 23]) box(x, 14, z, x, 14, z, wood);
}
for (const y of [18, 22, 26, 30, 34, 38]) {
box(10, y, 11, 10, y, 24, bamboo[y % 3]);
box(38, y, 11, 38, y, 24, bamboo[(y + 1) % 3]);
}
for (const z of [12, 17, 22]) {
box(10, 17, z, 10, 37, z, "#b78146");
box(38, 17, z, 38, 37, z, "#b78146");
box(13, 38, z, 35, 38, z, "#c48d4d");
}
// Side shutters give the little hut a lived-in look.
box(9, 25, 16, 9, 31, 21, darkWood);
box(9, 26, 17, 9, 30, 20, "#55b9b3");
box(9, 25, 18, 9, 31, 18, "#edcc83");
box(9, 28, 16, 9, 28, 21, "#edcc83");
box(39, 25, 16, 39, 31, 21, darkWood);
box(39, 26, 17, 39, 30, 20, "#55b9b3");
box(39, 25, 18, 39, 31, 18, "#edcc83");
box(39, 28, 16, 39, 28, 21, "#edcc83");
// A sagging red-and-white striped hammock in the open doorway.
for (const x of [16, 32]) {
box(x, 20, 12, x + 1, 21, 22, wood);
box(x, 20, 22, x + 1, 21, 23, "#e8bd71");
}
line(17, 20, 21, 19, 24, 17, 0, "#f5e4b0");
line(32, 20, 21, 30, 24, 17, 0, "#f5e4b0");
for (let x = 18; x <= 31; x++) {
const sag = Math.round(14 + 0.075 * (x - 24.5) ** 2);
for (let y = 22; y <= 27; y++) {
const z = sag + (y === 22 || y === 27 ? 1 : 0);
set(x, y, z, Math.floor((x - 18) / 2) % 2 ? "#fff0db" : "#d94e3f");
if (y === 22 || y === 27) set(x, y, z + 1, "#f3d99a");
}
}
line(18, 22, 17, 16, 21, 20, 0, "#ead49e");
line(31, 22, 17, 33, 21, 20, 0, "#ead49e");
// Thick pitched thatch, overhanging every side.
for (let x = 5; x <= 43; x++) {
const top = Math.round(35 - Math.abs(x - 24) * 0.49);
for (let y = 10; y <= 42; y++) {
for (let z = top - 2; z <= top; z++) {
const shade = z === top - 2 ? 2
: rand() < 0.17 ? 3
: (x + Math.floor(y / 3)) % 4 === 0 ? 2 : (y % 5 === 0 ? 0 : 1);
set(x, y, z, straw[shade]);
}
if (y % 4 === 0 && x % 3 !== 0)
set(x, y, top - 3, "#c68b3f");
}
}
// Deep, ragged eaves and a highlighted ridge.
for (let y = 10; y <= 42; y++) {
box(5, y, 24, 7, y, 25, y % 3 ? "#cb9040" : "#edbd61");
box(41, y, 24, 43, y, 25, y % 3 ? "#cb9040" : "#edbd61");
box(23, y, 35, 25, y, 35, y % 4 ? "#ffe08a" : "#edbd60");
}
// Bamboo front gable, framed beneath the thatch.
for (let x = 12; x <= 36; x++) {
const top = Math.round(35 - Math.abs(x - 24) * 0.49);
box(x, 13, 25, x, 14, top - 3,
x % 3 === 0 ? "#dfaf62" : "#efc97c");
}
box(17, 12, 25, 31, 12, 26, darkWood);
box(19, 12, 27, 29, 12, 29, "#704730");
box(20, 11, 28, 28, 11, 29, "#332e2b");
// Simple white pirate skull on the little sign.
box(22, 10, 28, 26, 10, 29, "#fff0cc");
set(23, 9, 29, "#302c2a"); set(25, 9, 29, "#302c2a");
set(24, 9, 28, "#302c2a");
line(21, 10, 27, 27, 10, 27, 0, "#fff0cc");
// A few beach treasures near the steps.
for (const [x, y] of [[12, 12], [34, 9], [38, 43]]) {
set(x, y, 2, "#ffe27c");
set(x + 1, y, 2, "#eab846");
}
box(34, 6, 2, 36, 8, 3, "#cf8560");
set(35, 7, 4, "#fff0d4");import { draw } from "./assets/voxel";
import { cabanaDePlaya } from "./assets/cabana-de-playa";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, cabanaDePlaya, x, y, { size: 64, angle: 0, t: performance.now() / 1000 });
// size: lo que mide en px su lado más largo
// angle: giro sobre el piso, en radianes
// t: segundos; si se mueve, se anima solo con eso# En una terminal, en la carpeta del juego
fogon assets add cabana-de-playa
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["cabana-de-playa"] })
# Queda en client/assets/cabana-de-playa.ts
# https://fogon.page/object/cabana-de-playa