← CiudadObjeto 3Dfogon/estadio-de-barrio
Estadio de barrio
Arrastrá para girarlo// «Estadio de barrio» · gpt-6-sol (medium)
// A small neighborhood football stadium: a rectangular green pitch with white lines and two goals, surrounded by colorful concrete stands on all four sides painted in blue and gold stripes, four tall floodlight towers at the corners and a scoreboard at one end. Seen from above, compact and readable.
const concrete = "#d8d5c9";
const concreteLight = "#eee9d9";
const concreteShade = "#b7b4aa";
const blue = "#2181bc";
const blueLight = "#45a6d7";
const gold = "#f5bc39";
const goldLight = "#ffda69";
const iron = "#28564d";
const white = "#f7f5e9";
// Compact asphalt plinth and warm brick stadium wall.
box(2, 2, 0, 45, 45, 0, "#62686a");
box(3, 3, 1, 44, 44, 1, concreteShade);
box(3, 3, 2, 44, 44, 2, concrete);
for (let z = 2; z <= 4; z++) {
const brick = z === 3 ? "#bd6750" : "#cf7658";
box(3, 3, z, 44, 3, z, brick);
box(3, 44, z, 44, 44, z, brick);
box(3, 4, z, 3, 43, z, brick);
box(44, 4, z, 44, 43, z, brick);
}
box(3, 3, 5, 44, 3, 5, concreteLight);
box(3, 44, 5, 44, 44, 5, concreteLight);
box(3, 4, 5, 3, 43, 5, concreteLight);
box(44, 4, 5, 44, 43, 5, concreteLight);
// Stepped concrete terraces: blue and gold rows read clearly from above.
for (let tier = 0; tier < 7; tier++) {
const left = 10 - tier, right = 37 + tier;
const north = 9 - tier, south = 38 + tier;
const h = 3 + tier;
const seat = tier % 3 === 1 ? gold : blue;
const highlight = tier % 3 === 1 ? goldLight : blueLight;
box(left, 9, 2, left, 38, h, concreteShade);
box(right, 9, 2, right, 38, h, concreteShade);
box(10, north, 2, 37, north, h, concreteShade);
box(10, south, 2, 37, south, h, concreteShade);
box(left, 9, h + 1, left, 38, h + 1, seat);
box(right, 9, h + 1, right, 38, h + 1, seat);
box(10, north, h + 1, 37, north, h + 1, seat);
box(10, south, h + 1, 37, south, h + 1, seat);
// Little individual seat backs, with gaps that suggest aisles.
for (let y = 11; y <= 36; y += 3) {
if (y >= 22 && y <= 25) continue;
set(left, y, h + 2, highlight);
set(right, y, h + 2, highlight);
}
for (let x = 12; x <= 35; x += 3) {
if (x >= 22 && x <= 25) continue;
set(x, north, h + 2, highlight);
set(x, south, h + 2, highlight);
}
}
// Pale aisle breaks and the inner lip of the terraces.
for (let x of [22, 23, 24]) {
for (let y = 3; y <= 9; y++) set(x, y, 3 + (9 - y) + 1, concreteLight);
for (let y = 38; y <= 44; y++) set(x, y, 3 + (y - 38) + 1, concreteLight);
}
box(11, 9, 2, 11, 38, 3, concreteLight);
box(36, 9, 2, 36, 38, 3, concreteLight);
// Mown grass, with broad alternating green strips.
for (let y = 10; y <= 37; y++) {
for (let x = 12; x <= 35; x++) {
let c = Math.floor((y - 10) / 4) % 2 ? "#48a957" : "#57b963";
if (rand() < 0.075) c = "#68c36d";
set(x, y, 2, c);
}
}
// Crisp white pitch markings.
function stripeX(x0, x1, y) {
for (let x = x0; x <= x1; x++) set(x, y, 3, white);
}
function stripeY(x, y0, y1) {
for (let y = y0; y <= y1; y++) set(x, y, 3, white);
}
stripeX(12, 35, 10);
stripeX(12, 35, 37);
stripeY(12, 10, 37);
stripeY(35, 10, 37);
stripeX(12, 35, 23);
set(24, 23, 4, white);
for (let a = 0; a < Math.PI * 2; a += 0.075) {
set(Math.round(24 + 4 * Math.cos(a)),
Math.round(23 + 4 * Math.sin(a)), 3, white);
}
stripeX(17, 30, 16);
stripeY(17, 10, 16);
stripeY(30, 10, 16);
stripeX(17, 30, 31);
stripeY(17, 31, 37);
stripeY(30, 31, 37);
stripeX(20, 27, 13);
stripeY(20, 10, 13);
stripeY(27, 10, 13);
stripeX(20, 27, 34);
stripeY(20, 34, 37);
stripeY(27, 34, 37);
set(24, 15, 4, white);
set(24, 32, 4, white);
// Two chunky white goal frames and sparse silver netting.
for (let y of [9, 38]) {
for (let z = 3; z <= 6; z++) {
set(20, y, z, white);
set(27, y, z, white);
}
stripeX(20, 27, y);
for (let x = 20; x <= 27; x++) set(x, y, 6, white);
const back = y === 9 ? 8 : 39;
for (let x = 20; x <= 27; x += 2) {
set(x, back, 3, "#b8cbd0");
set(x, back, 5, "#b8cbd0");
}
for (let z of [3, 5]) {
set(20, back, z, "#b8cbd0");
set(27, back, z, "#b8cbd0");
}
}
// Four tall corner floodlight masts.
for (let [tx, ty] of [[6, 6], [41, 6], [6, 41], [41, 41]]) {
box(tx, ty, 6, tx, ty, 20, iron);
box(tx - 1, ty - 1, 10, tx + 1, ty + 1, 10, "#416c60");
box(tx - 1, ty - 1, 16, tx + 1, ty + 1, 16, "#416c60");
box(tx - 2, ty - 1, 21, tx + 2, ty + 1, 21, concreteShade);
box(tx - 2, ty - 1, 22, tx + 2, ty + 1, 22, "#e7dfbe");
for (let dx of [-2, 0, 2]) {
for (let dy of [-1, 1]) set(tx + dx, ty + dy, 23, "#fff4ae");
}
}
// Scoreboard above the far-end stand, facing down the pitch.
box(18, 42, 9, 19, 42, 13, iron);
box(28, 42, 9, 29, 42, 13, iron);
box(17, 41, 13, 30, 43, 20, "#294c59");
box(18, 40, 14, 29, 40, 19, "#193b48");
box(18, 40, 20, 29, 40, 20, gold);
box(19, 40, 19, 28, 40, 19, blueLight);
// Simple, legible 1–0 score in warm illuminated blocks.
for (let z = 15; z <= 18; z++) set(22, 39, z, goldLight);
set(21, 39, 17, goldLight);
for (let z = 15; z <= 18; z++) {
set(26, 39, z, white);
set(28, 39, z, white);
}
for (let x = 26; x <= 28; x++) {
set(x, 39, 15, white);
set(x, 39, 18, white);
}
set(24, 39, 16, gold);
// Tiny fileteado-inspired accent on the exterior wall.
for (let x = 18; x <= 29; x++) {
set(x, 44, 3, x % 2 ? gold : blue);
}import { draw } from "./assets/voxel";
import { estadioDeBarrio } from "./assets/estadio-de-barrio";
// En cada cuadro: parado sobre (x, y), el centro de su base.
draw(ctx, estadioDeBarrio, 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 estadio-de-barrio
# Con las herramientas de Fogón (conector)
add_assets({ slug: "<tu-juego>", ids: ["estadio-de-barrio"] })
# Queda en client/assets/estadio-de-barrio.ts
# https://fogon.page/object/estadio-de-barrio