← LibraryKitmormon/starter-platformer
Clone
fogon pieces add starter-platformergit clone https://git.fogon.gg/mormon/starter-platformer.gitfogon new starter-platformer --from starter-platformerhttps://fogon.gg/piece/43/kit-de-inicio-plataformas-3dKit de inicio: plataformas 3D
El Starter Kit 3D Platformer de Kenney, que está hecho para Godot, pasado a three.js y TypeScript: el mismo personaje, el mismo nivel y los mismos números, leídos de sus escenas y sus scripts. Un muñeco que camina, salta dos veces y se aplasta al caer; una cámara que lo sigue y gira; monedas, ladrillos que se rompen de un cabezazo, plataformas que se caen y nubes.

En la demo: W A S D camina, espacio salta (y otra vez en el aire), las flechas giran la cámara y + / − la acercan y la alejan, como en el original. Además se puede arrastrar para girar y usar la rueda. En el teléfono: el pulgar izquierdo camina, un botón salta, otros dos acercan y alejan, y arrastrando se gira. También anda con un mando. Si te caés, el nivel empieza de nuevo.
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 de plataformas, no un juego terminado (el original tampoco: la bandera del final no hace nada).
Qué trae
client/platformer es lo que se lleva.
| Archivo | Qué hace |
|---|---|
game.ts | Game: todo junto. Arma el nivel, el jugador, la cámara y la luz, avanza la física a 60 pasos por segundo (como Godot) y dibuja. Avisa con onCoins y onRestart. |
level.ts | LEVEL: el nivel del kit como una lista (qué, dónde, girado cuánto), y los tipos Level y Thing para escribir otro. |
player.ts | Player: el personaje del kit (player.gd). Sus números están a la vista: movementSpeed 250, jumpStrength 7, fallAcceleration 25. Doble salto, se estira al saltar y se aplasta al caer, rastro de polvo y la sombra redonda debajo. |
view.ts | View: la cámara (view.gd). Sigue al jugador con retraso, gira y se acerca (zoom de 4 a 16 m). |
objects.ts | World: lo que hay en el nivel y lo que hace. Monedas que giran y se juntan, ladrillos que se rompen, plataformas que se caen, nubes que flotan. |
physics.ts | Los choques: una cápsula contra cajas y cilindros (moveAndSlide, box, cylinder), con pisos, paredes y techos como los cuenta Godot. Sin motor de física. |
environment.ts | addEnvironment: el sol con sus sombras, la luz ambiente, el cielo y la curva de tonos «Filmic» de Godot (useFilmicLook), para que se vea como el original. |
particles.ts | Particles: las chispas de las monedas, el polvo y los pedazos de ladrillo. |
controls.ts | Controls: teclado y mando, y extra para sumar un pad táctil. |
audio.ts | Audio: los seis sonidos del kit, cada vez un poco más agudos o más graves, y los pasos. |
assets.ts | loadAssets: baja los modelos, las imágenes y el cielo, y da copias que comparten geometría y material. |
Lo demás es la demo y sirve de ejemplo: client/main.ts tiene el contador de monedas, arrastrar para girar, la rueda y el pad táctil.
Cómo se usa en un juego
fogon pieces add starter-platformer
Eso trae client/platformer (solo código) y agrega three.js al package.json. Los modelos y los sonidos no viajan con el juego: se cargan desde la demo publicada de esta pieza (https://play.fogon.page/starter-platformer/platformer/).
import * as THREE from "three";
import { loadAssets } from "./platformer/assets";
import { Audio } from "./platformer/audio";
import { Controls } from "./platformer/controls";
import { Game } from "./platformer/game";
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
const assets = await loadAssets();
const audio = new Audio();
await audio.load(assets.base); // los sonidos están en la misma carpeta que los modelos
const game = new Game(renderer, assets, { audio });
const controls = new Controls();
game.onCoins = (coins) => (counter.textContent = String(coins));
addEventListener("pointerdown", () => audio.unlock()); // el navegador pide un gesto antes de sonar
addEventListener("keydown", () => audio.unlock());
function resize() {
renderer.setSize(innerWidth, innerHeight, false);
game.resize(innerWidth, innerHeight);
}
addEventListener("resize", resize);
resize();
let last = performance.now();
renderer.setAnimationLoop(() => {
const now = performance.now();
game.update((now - last) / 1000, controls.read());
last = now;
game.render();
});
Para servir los archivos vos (sin depender de la demo), copiá la carpeta public/platformer de este proyecto a tu public/ (son 880 KB) y llamá loadAssets({ base: "./platformer/" }).
Otro nivel. Un nivel es una lista. Las medidas están en metros, con +Y para arriba, y at es donde apoya cada cosa:
import type { Level } from "./platformer/level";
const mine: Level = {
spawn: [0, 0.5, 0], // donde aparece el jugador
floor: -10, // más abajo que esto, el nivel empieza de nuevo
things: [
{ kind: "platform-large", at: [0, 0, 0] },
{ kind: "coin", at: [1, 0.635, 0] },
{ kind: "brick", at: [-1, 1.986, 0] }, // a 1,5 m sobre el piso: se rompe de un salto
{ kind: "platform-falling", at: [4, 0.4, 0], yaw: 10 },
{ kind: "platform-grass-large-round", at: [9, 1, 0] },
{ kind: "cloud", at: [3, 2, -6], scale: 1.4 },
{ kind: "flag", at: [9, 1.48, 0] },
],
};
const game = new Game(renderer, assets, { audio, level: mine });
// o más tarde: game.restart(mine);
Las plataformas miden 2, 3 y 5 m de lado (platform, platform-medium, platform-large) y medio metro de alto; la redonda, 5 m de diámetro. Con un salto se sube 1 m y con dos, hasta 1,9 m; de un salto se cruzan unos 2,3 m y de dos, unos 4 m.
Otros números. game.player.jumpStrength = 9, game.player.movementSpeed = 320, game.view.zoom = 6: son campos comunes, se cambian cuando quieras.
Algo propio en el nivel. game.scene es la escena de three.js y game.world.colliders la lista de lo que frena al jugador: para una pared o un piso tuyos, agregá tu malla a la escena y un box(x, y0, z, mitadX, alto, mitadZ, giro) o un cylinder(x, y0, z, radio, alto) a esa lista (los dos salen de physics.ts; el giro va en radianes). Al reiniciar el nivel la lista se arma de nuevo.
Solo la luz. addEnvironment(renderer, scene, { sky }) sirve sin el resto, para darle a cualquier escena el aspecto del kit. La pieza starter-scene (el kit de la escena básica) es eso mismo, más completo.
Qué quedó distinto del original
- Los choques son cajas y cilindros. En Godot las plataformas chocan con la forma exacta de su malla (bordes redondeados incluidos); acá, con una caja del mismo tamaño (un cilindro para la redonda). El personaje es la misma cápsula de 0,3 m de radio y 1 m de alto.
- Sin oscurecimiento en los rincones ni resplandor. El original prende SSAO y «glow»; acá no están. El sol, la luz ambiente, el cielo, la curva de tonos y los ajustes de brillo, contraste y saturación son los mismos, y los colores salen a pocos puntos de los de la captura del kit.
- Las sombras son las de three.js: un solo mapa de 2048 px que sigue al jugador (16 m para cada lado).
- Se agregó arrastrar para girar la cámara, la rueda y el pad táctil. El teclado y el mando son los del kit.
Límites
- Es para uno: no hay sala.
server/room.tsyshared.tsestán vacíos, solo porque todo proyecto de Fogón los lleva. - No hay enemigos, ni vidas, ni final: como en el kit, solo se juntan monedas.
- La curva de tonos se pone en el lugar del «tone mapping a medida» de three.js, que es uno solo por página.
- Necesita WebGL 2 (cualquier navegador actual). three.js es una dependencia de npm: el juego que lo use se arma con la CLI de Fogón (
fogon dev,fogon deploy).
Créditos y licencias
- De Kenney (kenney.nl): el diseño del juego, el nivel y sus números (el repositorio original, con licencia MIT: está en
LICENSE-kenney.md), y los modelos, las imágenes y los sonidos depublic/platformer, en dominio público (CC0). - Nuestro: el pase a three.js y TypeScript (todo
client/), también MIT. - La tipografía del contador es Lilita One, de Google Fonts (como en el kit).
Pick a file.
| Version | When | Size | Commit |
|---|---|---|---|
| v1 in the demo | Nov 12, 2026 | 1.8 MB | 62f8dee |
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.