← BibliotecaObjetomormon/blockyard-props
Blockyard: la terminal de contenedores
Obra original de Saltline ↗
Clonar
fogon pieces add blockyard-propsgit clone https://git.fogon.gg/mormon/blockyard-props.gitfogon new blockyard-props --from blockyard-propsBlockyard: objetos de una terminal de contenedores
Un pack de modelos para three.js: los objetos originales del mapa Blockyard de Contrafuego, tal como salen del juego. Contenedores de 20 y 40 pies en ocho colores, un autoelevador, la garita, torres de luz, barreras, cajones, pallets, una bobina de cable, un tanque IBC y más, cada uno con sus texturas PBR, sus calcos y sus rótulos. Con ellos vienen el rifle del jugador y siete superficies (asfalto, hormigón, ladrillo, chapa).
No están rehechos: se exportaron del juego en marcha (ver Origen y permiso).

En la demo: la lista de la izquierda tiene todo lo que trae el pack, en cuatro pestañas (Objetos, Contenedores, Superficies, Todo junto). Elegí uno y lo ves solo, girando: arrastrá para mirarlo, la rueda o dos dedos acercan, y las flechas ↑↓ recorren la lista. Abajo están su tamaño, sus triángulos y la línea de código que lo trae (un clic la copia). En los controles: Caja de colisión dibuja la caja con la que choca en el juego (amarilla) y las cajas finas (celestes), Mojado lo oscurece y abrillanta como bajo la lluvia, y la grilla es de un metro.
El mapa armado con estos objetos es otra pieza: «Blockyard: el mapa, a pie y con rifle» (blockyard-map).
Qué trae
Dos carpetas, y las dos se llevan (fogon pieces add blockyard-props):
| Archivo | Qué hay |
|---|---|
client/blockyard/props.ts | El cargador. loadProps(), piece(name) / pieceNow(name), pieceNames(), bounds(name), info(name) (caja, triángulos, colisiones finas y lámparas), rifle(), surfaceNames(), wallMaterial(name) y slab(name, ancho, alto, fondo) para las superficies, setWetness(0…1), setBase(url), disposeProps(). |
client/blockyard/light.ts | dusk(scene, renderer): la hora de la terminal. Cielo, sol bajo con sombras, luz de relleno, niebla y el entorno que reflejan los metales (sin un entorno, el acero sale negro). |
shared/blockyard/sizes.ts | Sin three.js (lo puede leer una sala). PROP_SIZE: la caja de colisión de cada objeto, la del juego. propBox(name, x, z, turned, y): esa caja puesta en un lugar. CONTAINER_COLORS y propOf(model). |
Los modelos no viajan con el código: están en public/blockyard/ de esta demo (blockyard.glb, 6 MB, y catalog.json) y el cargador los baja de ahí. Lo demás es la demo (client/main.ts) y una sala vacía.
Los objetos
| Nombre | Qué es | Tamaño (m) | Triángulos |
|---|---|---|---|
container20_<color> | Contenedor de 20 pies | 6,07 × 2,59 × 2,45 | ~5.300 |
container40_<color> | Contenedor de 40 pies | 12,20 × 2,59 × 2,44 | ~6.400 |
light_mast | Torre de luz | 0,99 × 14 × 1,90 | 2.794 |
floodlight_stand | Reflector de pie | 0,92 × 2,24 × 1,66 | 1.438 |
guard_booth | Garita | 3,11 × 2,55 × 2,77 | 3.088 |
shelf_rack | Estantería de depósito, cargada | 2,75 × 4,20 × 1,13 | 7.032 |
jersey_barrier | Barrera de hormigón | 3,00 × 0,86 × 0,61 | 604 |
pallet_stack | Pila de pallets | 1,27 × 1,15 × 1,05 | 2.560 |
crate_wood | Cajón de madera | 1,11 × 1,00 × 0,91 | 1.476 |
crate_stack | Tres cajones apilados, con sus cinchas | 1,21 × 1,91 × 1,04 | 2.552 |
ibc_tote | Tanque IBC de 1000 litros | 1,20 × 1,15 × 1,00 | 2.122 |
forklift | Autoelevador | 3,41 × 2,19 × 1,25 | 11.628 |
cable_reel | Bobina de cable | 1,29 × 1,30 × 0,86 | 2.442 |
tire_stack | Pila de cubiertas | 0,80 × 0,99 × 0,81 | 2.560 |
dumpster | Contenedor de basura | 1,92 × 1,21 × 1,24 | 2.742 |
tarp_cargo | Carga bajo lona | 2,41 × 1,44 × 1,48 | 2.968 |
sandbags | Bolsas de arena | 1,99 × 0,90 × 0,63 | 2.646 |
rifle | El rifle del jugador, sin las manos | 0,07 × 0,34 × 0,88 | 30.702 |
Los colores de los contenedores: red, blue, green, yellow, orange, white, grey, teal (16 modelos: cada uno con su logo, su matrícula y sus chorreaduras de óxido). Las superficies: asphalt, concrete, concrete_dirty, concrete_painted, brick, floor_epoxy, corrugated_roof.
En total: 32 objetos, 173.398 triángulos, 131 texturas en WebP (1024 px las más grandes) y 102 materiales.
Cómo se usa en un juego
Todo está en metros, con y hacia arriba. Cada objeto sale parado sobre el piso, centrado en x y z, con su lado largo sobre x: se pone con position y se gira con rotation.y.
import { loadProps, piece, slab } from "./blockyard/props";
import { dusk } from "./blockyard/light";
await loadProps(); // baja blockyard.glb (6 MB) una sola vez
dusk(scene, renderer); // cielo, sol, y el entorno: sin él los metales salen negros
const forklift = await piece("forklift");
forklift.position.set(4, 0, -2);
scene.add(forklift);
scene.add(await piece("container40_teal"));
scene.add(slab("brick", 6, 3, 0.3)); // una pared de ladrillo de 6 × 3 m
Cada copia comparte geometría y materiales con las demás: ochenta contenedores ocupan en memoria lo que uno de cada color. Por lo mismo, si cambiás un material cambian todas (clonalo antes si querés uno distinto).
La luz. dusk() alumbra 30 m alrededor del origen; para una escena más grande decile dónde y cuánto: dusk(scene, renderer, { center: [-5, 0], reach: 48 }). Si ya tenés tu propia luz, lo único que hace falta es un scene.environment.
El rifle, colgado de la cámara (apunta a −Z, que es hacia donde mira):
import { rifle } from "./blockyard/props";
const gun = await rifle();
gun.position.set(0.115, -0.125, -0.3);
camera.add(gun);
scene.add(camera);
(La pieza blockyard-map trae el resto: retroceso, fogonazo, trazadora, marcas de impacto y sonido.)
En la sala, para que los objetos frenen a los jugadores y a las balas, sus cajas salen de sizes.ts:
import { propBox } from "../shared/blockyard/sizes";
const boxes = [propBox("forklift", 4, -2), propBox("container40_teal", 0, 0), propBox("container20_red", 0, 0, false, 2.59)];
// cada una: [minX, minY, minZ, maxX, maxY, maxZ]
Servir los modelos desde tu juego (para no depender de esta demo): copiá public/blockyard/ a tu public/ y avisale al cargador una vez, antes de cargar:
await loadProps({ base: "./blockyard/" });
Las cajas de colisión
PROP_SIZE trae la caja que el juego usa para cada objeto: [largo en x, alto, fondo en z], centrada y apoyada en el piso. Casi todas coinciden con el modelo a menos de 6 cm. Las que no:
| Objeto | Modelo (m) | Caja (m) | Por qué |
|---|---|---|---|
light_mast | 0,99 × 14 × 1,90 | 0,5 × 14 × 0,5 | La caja es el poste; la base y los brazos con las lámparas (a 13 m) sobresalen. |
floodlight_stand | 0,92 × 2,24 × 1,66 | 1 × 2,2 × 1 | Una pata del trípode sale 78 cm hacia −z. |
guard_booth | 3,11 × 2,55 × 2,77 | 2,6 × 2,7 × 2,2 | El alero del techo y el aire acondicionado sobresalen unos 30 cm; la caja es 15 cm más alta que el techo. |
dumpster | 1,92 × 1,21 × 1,24 | 1,9 × 1,35 × 1,1 | La caja es 14 cm más alta; la tapa sobresale 10 cm hacia −z. |
tarp_cargo | 2,41 × 1,44 × 1,48 | 2,4 × 1,5 × 1,4 | La lona cae 7 cm más allá hacia +z. |
info(name).colliders trae además las cajas finas del juego (el autoelevador tiene once: chasis, mástil, uñas, techo). En la demo, el control Caja de colisión las dibuja sobre el modelo.
Qué se perdió respecto del juego
Los modelos son los del juego: la misma geometría, los mismos colores por vértice, las mismas texturas. Lo que el juego agrega al dibujar no se puede guardar en un archivo de modelo, y no está:
- La lluvia sobre las superficies. El juego moja cada material según hacia dónde mira la cara (charcos arriba, chorreaduras en las paredes, una franja salpicada contra el piso) y le agrega gotas.
setWetness()es un reemplazo parejo: oscurece y abrillanta todo por igual. - La variación a gran escala: manchas de suciedad que el juego calcula por posición en el mundo, para que dos contenedores iguales no se vean iguales.
- El detalle fino del rifle: desgaste, rayas y gotas, que el juego calcula en su sombreador. Quedan sus colores, su rugosidad y su oscurecido por vértice. Tampoco están la retícula de la mira, ni las manos.
- Las variantes por semilla. En el juego cada objeto sale un poco distinto (otro logo, otra matrícula, otras manchas, otra carga en la estantería). Acá hay uno de cada uno; los contenedores, uno por color.
- Las luces de las torres son, en el juego, luces de verdad con halo; acá el foco brilla (material emisivo) e
info(name).lampsdice dónde está cada lámpara y hacia dónde apunta, para ponerle una luz.
Tres ajustes menores: algunas rugosidades que el juego multiplica por más de 1 viajan aparte (el cargador las repone; otro visor de glTF las ve en 1), el tinte de la pintura está cocido en la textura de color (por eso hay una por color) y la munición de latón del cargador del rifle usa las coordenadas de textura de su malla en vez de la proyección del juego.
Origen y permiso
Los modelos, los materiales y el rifle son del juego Saltline (https://claude.ai/artifact/BGY1SztrAYcJQHSsnHHGmp) y están acá con permiso de su autor. No son de dominio público ni tienen una licencia abierta: si querés usarlos fuera de Fogón, o venderlos, preguntale a su autor.
El cargador, la luz, las cajas de colisión como datos, la demo y las herramientas de exportación son nuestros.
Cómo se hizo
Saltline no trae archivos de modelo: construye cada objeto por código al arrancar y fabrica sus texturas en la placa de video. Para tenerlos como archivo hubo que sacarlos del juego andando (las herramientas quedan en tools/, en la carpeta del estudio: no viajan con la pieza publicada):
tools/export/export.tsabre el juego en un Chrome sin ventana, le pide cada objeto a su propio constructor, lee cada textura de la placa de video, pasa los materiales a materiales estándar y los guarda con el exportador de glTF de three.js. Sale un.glbcrudo de 60 MB.tools/build.tslo achica con glTF-Transform: une las mallas por material, suelda vértices, pasa las texturas a WebP y comprime la geometría con meshopt. Quedan 6 MB, ycatalog.jsoncon la caja y los datos de cada objeto.
Elegí un archivo.
| Versión | Cuándo | Peso | Commit |
|---|---|---|---|
| v2 en la demo | 12 de nov de 2026 | 7.3 MB | e36431d |
| v1 | 12 de nov de 2026 | 7.2 MB | f008477 |
Todavía nadie publicó una versión hecha a partir de esta pieza.
Hacé tu versión de
Copiá este pedido y pegáselo a tu IA (Claude, ChatGPT…): arma tu versión con el código de este juego y la publica como un juego tuyo.