← LibraryKitmormon/starter-city-builder
Clone
fogon pieces add starter-city-buildergit clone https://git.fogon.gg/mormon/starter-city-builder.gitfogon new starter-city-builder --from starter-city-builderhttps://fogon.gg/piece/46/kit-de-inicio-constructor-de-ciudadKit de inicio: constructor de ciudad
El Starter Kit City Builder de Kenney, que está hecho para Godot, portado a three.js y TypeScript para Fogón: la misma mecánica, los mismos números y la misma escena, con sus modelos y sonidos originales. Una grilla de casillas de un metro, un selector que sigue al puntero y quince estructuras para colocar, girar y demoler; cada una cuesta plata, la cámara se desplaza, gira y hace zoom, y el mapa se guarda y se carga.

En la demo: clic construye lo que está elegido, clic derecho (o R) lo gira, Supr (o X) demuele lo que hay bajo el selector y Q / E cambian de estructura. La cámara se mueve con W A S D, vuelve al centro con F, gira con el botón del medio apretado (o con ← →) y se acerca con la rueda. F1 guarda el mapa, F2 lo carga y F3 trae el mapa de muestra del kit; los mismos botones están arriba, junto con «Exportar / importar» (el mapa como texto) y «Vaciar». En el teléfono: un toque construye, arrastrar mueve la cámara, dos dedos hacen zoom, y los botones de la derecha giran la estructura y pasan de construir a demoler.
Es solo la página. No hay sala ni red: todo pasa en el navegador de quien juega. Es una base para empezar un juego propio, no un juego terminado.
Qué trae
client/city-builder es lo que se lleva.
| Archivo | Qué hace |
|---|---|
builder.ts | Builder: la grilla y el selector. aim / aimAt apuntan, build, demolish, rotate, toggle y choose son las acciones, save y load pasan el mapa a datos y de vuelta. Es el builder.gd del kit. |
map.ts | CityMap: la ciudad como datos (la plata y qué hay en cada casilla), sin motor. toJSON() y CityMap.from(datos). |
structures.ts | STRUCTURES: las quince estructuras, cada una con su modelo, su nombre y su precio. |
sample.ts | SAMPLE_MAP: el mapa de muestra del kit (122 casillas), decodificado de su map.res. |
view.ts | View: la cámara en un brazo que mira un punto del suelo. Se mueve, gira y hace zoom suavizado (el view.gd del kit). |
environment.ts | Environment: el fondo, la luz de ambiente, el sol con sombras y la misma curva de color que usa Godot («Filmic»). |
audio.ts | Sounds: los efectos (uno al azar entre varios, con el tono apenas distinto cada vez, como el kit) y el ambiente en bucle. |
assets.ts | De dónde salen los archivos: loadModel, loadTexture, url y setBase. |
Lo demás es la demo y sirve de ejemplo: client/main.ts tiene el mouse, el teclado, los toques, los botones, guardar en el navegador y lo que se escribe en pantalla.
Cómo se usa en un juego
fogon pieces add starter-city-builder
Eso trae client/city-builder/ (solo código) y agrega three.js al package.json. Los modelos, las imágenes y los sonidos no viajan con el juego: se cargan desde la demo publicada de esta pieza (https://play.fogon.page/starter-city-builder/city/).
import * as THREE from "three";
import { Builder } from "./city-builder/builder";
import { Environment } from "./city-builder/environment";
import { Sounds } from "./city-builder/audio";
import { View } from "./city-builder/view";
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
const scene = new THREE.Scene();
const environment = new Environment(scene, renderer); // fondo, luces, sombras y curva de color
const view = new View();
const sounds = new Sounds();
const builder = await Builder.create({
sounds,
onCash: (cash) => (cashLabel.textContent = "$" + cash),
});
scene.add(view.object, builder.object);
// El puntero: el selector va a la casilla que tiene debajo, y un clic construye.
const raycaster = new THREE.Raycaster();
canvas.addEventListener("pointermove", (e) => {
raycaster.setFromCamera(new THREE.Vector2((e.clientX / innerWidth) * 2 - 1, -(e.clientY / innerHeight) * 2 + 1), view.camera);
builder.aim(raycaster.ray);
});
canvas.addEventListener("pointerdown", () => {
sounds.unlock(); // el navegador solo deja sonar después de un toque o una tecla
builder.build();
});
renderer.setAnimationLoop(() => {
const dt = 1 / 60;
view.update(dt, 0, 0); // (derecha, atrás): hacia dónde mover la cámara, de −1 a 1
builder.update(dt);
environment.follow(view.object.position, view.zoom * 0.6 + 6); // las sombras, donde mira la cámara
renderer.render(scene, view.camera);
});
// Guardar y cargar: el mapa es un objeto chico, sirve para localStorage o para mandarlo a una sala.
const data = builder.save(); // { cash: 9905, structures: [[x, z, estructura, giros], …] }
builder.load(data);
Agregar estructuras
Una estructura es un modelo que ocupa una casilla (de −0,5 a 0,5, apoyado en y = 0) y un precio. La lista se le pasa al constructor; un mapa nombra cada estructura por su lugar en la lista, así que conviene agregar al final.
import { STRUCTURES } from "./city-builder/structures";
const builder = await Builder.create({
structures: [...STRUCTURES, { model: "building-garage", label: "Otro garaje", price: 120 }],
});
model es el nombre de un .glb de la carpeta models/ de donde se cargan los archivos. Para usar modelos propios, servilos vos (el punto que sigue) y sumalos a esa carpeta.
Usar los archivos sin depender de la demo
Para tenerlos dentro de tu juego (sin conexión, o servidos por vos), bajalos a public/city/ y decíselo al cargador una vez, antes de cargar nada:
mkdir -p public/city/models/Textures public/city/sprites public/city/sounds && cd public/city
B=https://play.fogon.page/starter-city-builder/city
for m in road-straight road-straight-lightposts road-corner road-split road-intersection pavement pavement-fountain \
building-small-a building-small-b building-small-c building-small-d building-garage grass grass-trees grass-trees-tall; do
curl -fo models/$m.glb $B/models/$m.glb
done
curl -fo models/Textures/colormap.png $B/models/Textures/colormap.png
for s in selector coin; do curl -fo sprites/$s.png $B/sprites/$s.png; done
for s in ambience placement-a placement-b placement-c placement-d removal-a removal-b removal-c removal-d rotate toggle; do
curl -fo sounds/$s.ogg $B/sounds/$s.ogg
done
import { setBase } from "./city-builder/assets";
setBase("./city/");
Son 1,7 MB: quince modelos (models/*.glb y su paleta, models/Textures/colormap.png), dos imágenes (sprites/selector.png, sprites/coin.png) y once sonidos (sounds/*.ogg; el ambiente pesa 1,2 MB él solo).
Para hacerlo entre varios
El mapa ya es datos (CityMap): en server/room.ts guardá uno por sala, que el cliente mande «construí esto acá» y que la sala lo valide (¿alcanza la plata?), lo aplique y lo reparta. Builder dibuja lo que diga el mapa.
Qué quedó distinto del original
- El mapa se guarda como JSON (en el kit es un recurso binario de Godot). El giro de cada casilla va de 0 a 3 cuartos de vuelta; el kit guarda el índice de orientación de Godot (0, 16, 10, 22).
- Demoler también sale con X o con retroceso, girar con R y la cámara gira con las flechas: no todos los teclados tienen Supr ni todos los mouse botón del medio. Los controles táctiles, los botones, «Exportar / importar» y «Vaciar» son agregados.
- La cámara se mueve a 15 m por segundo en cualquier pantalla (el kit avanza un cuarto de metro por cuadro: lo mismo a 60 cuadros por segundo).
- El kit prende oclusión ambiental (SSAO); acá no está.
- Como en el kit: la plata puede quedar en negativo, demoler no devuelve nada y volver a poner lo mismo en una casilla (para girarlo) es gratis.
Créditos y licencia
El kit original, sus modelos, imágenes y sonidos son de Kenney (kenney.nl): el código bajo licencia MIT (va copiada en LICENSE-kenney.md) y los modelos, imágenes y sonidos en dominio público (CC0). El port a three.js es nuestro, también MIT. No hace falta dar crédito a Kenney, pero se agradece.
Pick a file.
| Version | When | Size | Commit |
|---|---|---|---|
| v1 in the demo | Nov 12, 2026 | 2.6 MB | 05919b8 |
Nobody has published a version made from this piece yet.
Put together the request for your agent
Pick what you want to do, copy the request and paste it into your AI (Claude, ChatGPT, Codex…). It does the rest.