← BibliotecaConceptomormon/blockyard-map
Blockyard: el mapa, a pie y con rifle
Obra original de Saltline ↗
Clonar
fogon pieces add blockyard-mapgit clone https://git.fogon.gg/mormon/blockyard-map.gitfogon new blockyard-map --from blockyard-maphttps://fogon.gg/piece/52/blockyard-el-mapa-a-pie-y-con-rifleBlockyard: el mapa, a pie y con rifle
El mapa Blockyard de Contrafuego, armado con los modelos originales del pack «Blockyard: objetos de una terminal de contenedores» (blockyard-props): una terminal de 66 × 56 m con una base en cada punta, tres carriles entre ellas (norte, medio y sur) separados por pilas de contenedores, y dos sitios abiertos. Viene como concepto completo de un juego de disparos en primera persona: el trazado como datos, la función que lo dibuja, las colisiones para caminar y para las balas, y el rifle en la mano con todo lo que pasa al disparar.

En la demo caminás por el patio con el rifle original y disparás. Cada tiro patea, hace un fogonazo, deja una trazadora y una marca donde pega, y suena (el sonido está hecho por código). Repartidos por el patio hay blancos de acero: caen cuando les das y se vuelven a parar a los cinco segundos.
- Teclado y mouse: WASD o flechas para caminar, Shift para correr, el mouse mira, clic dispara (también F o espacio), R recarga, M muestra el patio desde arriba.
- Teléfono: la mitad izquierda de la pantalla camina, la derecha mira, y hay un botón de fuego y uno de recarga.
Nada pasa por una sala: es solo la página.
Necesita el pack
Los modelos no están en esta pieza: los carga del pack publicado. En tu juego hacen falta las dos:
fogon pieces add blockyard-props # el cargador de los modelos, la luz y las cajas de colisión
fogon pieces add blockyard-map # el mapa, las colisiones y el rifle en mano
El código de esta pieza importa del pack por sus rutas (client/blockyard/…, shared/blockyard/…), que es donde fogon pieces add lo deja. En el código fuente de esta demo hay una copia idéntica de esos tres archivos del pack (client/blockyard/props.ts, client/blockyard/light.ts, shared/blockyard/sizes.ts) solo para que compile; no se comparten desde acá.
Qué trae
Dos carpetas, y las dos se llevan:
| Archivo | Qué hay |
|---|---|
shared/blockyard-map/layout.ts | El patio como números, sin three.js (lo puede leer una sala). WALLS y PROPS: qué hay y dónde (121 objetos). yardBoxes(): todo lo sólido. yardMap(): el mapa con la forma que pide el kit «Duelo por equipos». YARD, YARD_BASES, YARD_MID, y modelOf(i) / containerColor(i): qué modelo va en cada lugar. |
shared/blockyard-map/hit.ts | Caminar y disparar entre cajas, también sin three.js. slide(boxes, x, z): un cuerpo que no atraviesa lo sólido y resbala contra las paredes. castShot(boxes, origen, dirección): dónde termina una bala (punto, cara, distancia). castSphere(...): para blancos redondos. |
client/blockyard-map/yard.ts | buildYard(): el patio completo (piso, muros y los 121 objetos; cada modelo repetido se dibuja de una vez, con instancias). yardLamps(): dónde están las luces. yardDusk(scene, renderer): la luz del pack, centrada en el patio y con sombras que lo cubren. |
client/blockyard-map/gun.ts | createGun(camera, scene, rifle): el rifle en la mano. Cadencia, cargador y recarga; retroceso (del arma y de la mira), fogonazo con su luz, trazadora, marca y polvo donde pega, y el estampido, hechos por código. No sabe qué es sólido: vos le decís dónde termina cada tiro. |
Lo demás es la demo (client/main.ts: los controles, los blancos, la vista desde arriba) y una sala vacía.
Cómo se usa en un juego
Todo está en metros, con y hacia arriba; x va de oeste a este (−38…28) y z de norte a sur (−28…28).
Dibujar el patio:
import { buildYard, yardDusk } from "./blockyard-map/yard";
yardDusk(scene, renderer); // cielo, sol con sombras, y el entorno que reflejan los metales
scene.add(await buildYard()); // { lamps: true } enciende las torres; { instanced: false } deja cada objeto suelto
Caminar sin atravesar los contenedores:
import { yardBoxes } from "../shared/blockyard-map/layout";
import { slide } from "../shared/blockyard-map/hit";
const boxes = yardBoxes();
// cada cuadro: movés el cuerpo a donde quiere ir, y slide() lo saca de lo sólido
[body.x, body.z] = slide(boxes, body.x + vx * dt, body.z + vz * dt);
camera.position.set(body.x, 1.68, body.z);
El rifle y los tiros:
import { rifle } from "./blockyard/props"; // (del pack)
import { castShot } from "../shared/blockyard-map/hit";
import { createGun } from "./blockyard-map/gun";
scene.add(camera); // el rifle cuelga de la cámara
const gun = createGun(camera, scene, await rifle());
// cada cuadro:
if (triggerHeld)
gun.fire((origin, direction) => {
const hit = castShot(boxes, [origin.x, origin.y, origin.z], [direction.x, direction.y, direction.z]);
return hit && { point: hit.point, normal: hit.normal }; // { kind: "metal" } suena a chapa y no deja agujero
});
gun.update(dt, walkingSpeed);
camera.rotation.set(pitch + gun.recoil.pitch, yaw + gun.recoil.yaw, 0, "YXZ");
gun.fire() respeta la cadencia y el cargador: solo te llama cuando sale un tiro de verdad, con la posición del ojo y hacia dónde va (la puntería más un poco de dispersión, que crece si no soltás el gatillo). gun.ammo, gun.reloading y gun.reload() son para tu pantalla. Las opciones: rate (10 tiros por segundo), magazine (30), reloadTime, spread, volume (0 lo calla), marks (cuántas marcas quedan en las paredes) y hold (dónde cuelga).
En un juego con sala, la sala decide a quién le pegaste: castShot y slide no usan three.js justamente para que el servidor haga la misma cuenta con las mismas cajas.
Con el kit «Duelo por equipos» (team-deathmatch): el patio ya viene como mapa, con sus cajas, las dos bases y el medio. En la sala y en la página:
import { yardMap } from "../shared/blockyard-map/layout";
const map = yardMap(); // { bounds, boxes, bases, mid }: lo que pide deathmatch(map)
y en la página se dibuja con buildYard() en lugar de las cajas grises del kit.
El trazado
- Las bases están contra los muros oeste y este (
YARD_BASES). Delante de cada una hay una fila de contenedores con tres salidas: norte, medio y sur. - El medio tiene un contenedor cruzado, barreras, un tanque y cajones para cubrirse.
- Sitio A (norte) y sitio B (sur) son los dos claros, con contenedores sueltos, cajones, pallets, una estantería y un autoelevador.
- Las pilas que separan los carriles tienen dos y tres contenedores de alto: no se ve de un carril al otro.
Cambiar el mapa es cambiar PROPS ([objeto, x, z, girado, altura]) y WALLS: lo dibujado y lo sólido salen de la misma lista.
Qué no está respecto del juego
- El piso de la terminal (líneas pintadas, juntas, charcos y reflejos), el fondo (barco, grúas, mar, cielo con nubes) y la lluvia: el juego los hace con sombreadores propios que no se pueden exportar. El patio usa la superficie
asphaltdel pack y el atardecer dedusk. - Los colores de los contenedores caen en el mismo lugar que en el juego; los logos y las matrículas no siempre (el pack trae un modelo por color).
- Las luces de las torres están apagadas por defecto:
buildYard({ lamps: true })pone una luz por torre. - El jugador no tiene cuerpo ni manos, no salta ni se agacha, y no hay enemigos: los blancos de la demo son nuestros, hechos por código. Para un juego completo con equipos, bots y rondas, sumale
team-deathmatch. - Las colisiones son las cajas del juego: un poco más simples que los modelos (ver el README del pack).
Origen y permiso
Los modelos con los que se arma el patio y el rifle son del juego Saltline (https://claude.ai/artifact/BGY1SztrAYcJQHSsnHHGmp) y se publican con permiso de su autor en la pieza blockyard-props, de donde esta los carga. 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 trazado del mapa, las colisiones, el rifle en mano (retroceso, fogonazo, trazadora, marcas, sonido), los blancos y la demo son nuestros.
Elegí un archivo.
| Versión | Cuándo | Peso | Commit |
|---|---|---|---|
| v2 en la demo | 12 de nov de 2026 | 1.3 MB | 05787f9 |
| v1 | 12 de nov de 2026 | 1.3 MB | e426350 |
Todavía nadie publicó una versión hecha a partir de esta pieza.
Armá el pedido para tu agente
Elegí qué querés hacer, copiá el pedido y pegáselo a tu IA (Claude, ChatGPT, Codex…). Ella hace el resto.