Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
翻译准备中
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Functor: A functional language for games
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Note: alpha software. Functor is early software under active development — the language, the prelude, and file formats can all change between releases without a deprecation path. Binaries and changelogs are published on the releases page.
Use the scrubber bar to move backward and forward in time, and use the extrapolate button to project state forward (replaying key events / other effects in the process)
try it yourself at https://functor.games/sandbox?example=platformer
When a scene is paused, see live values flowing through the system - visualize what code paths were hit and with what values
Try it yourself at https://functor.games/sandbox?example=orbit
Asset management, animation, physics, and spatial audio — in the box. Stream a rigged model straight from a URL and the runtime skins and blends its clips; there's no asset pipeline to set up.
Try it yourself at https://functor.games/sandbox?example=batteries
Client and server are just roles of the same game, running side by side in the browser — and the network view makes the wire itself visible: every intent and every snapshot is a real packet flying at its real delay, decoded as Steer and Snapshot values rather than bytes. Degrade a client's link to mobile and watch that wire fall behind while the LAN client keeps pace.
try it yourself at https://functor.games/sandbox?example=orbs#clients=2
Games run and respond headlessly. Drive and inspect a running game entirely over HTTP — read its live state and render tree, inject input, capture frames — the way a coding agent would.
functor mcp serves that same runtime as MCP tools over stdio, so
any coding agent can build, run, inspect, and rewind your game — real Functor code, deterministic
(pin the clock, inject input, step frame by frame), on the runtime that ships to native and web. An agent can
scaffold a project, launch it, iterate on it, and save it to disk entirely through the server, with
no filesystem of its own.
claude mcp add functor -- functor mcp
Any other MCP client registers it as an ordinary stdio server (command: "functor", args: ["mcp"]) —
see docs/mcp.md for the full tool surface, or
Driving games with agents in the manual.
No install needed:
.fun, watch it hot-reload, and scrub the timeline.Install a prebuilt binary — no toolchain needed.
# macOS / Linux
curl -fsSL https://raw.githubusercontent.com/tommy-xr/functor/main/install.sh | sh
# Windows (PowerShell)
irm https://raw.githubusercontent.com/tommy-xr/functor/main/install.ps1 | iex
This downloads the right binary for your platform into ~/.functor/bin and prints
the line to add it to your PATH.
(Prefer to grab it by hand? Download the archive for your platform from the releases page and extract the single
functorbinary)
Then scaffold a game and run it — a window opens; edit my-game/game.fun and save
to hot-reload with the model preserved:
functor -d my-game init # scaffold a starter project
functor -d my-game run native # open a window and run it
Prefer to build from source? See DEVELOPMENT.md.
Functor is:
.fun).fun file and accommodates hot-reloadUltimately, Functor is an experiment - what is game development like with functional programming? And namely if we impose some additional constraints - like pure functions and determinism - can we improve the development experience?
The functor runtime runs in both WebAssembly and native code - you write your game as pure Model-View-Update functions in a .fun file.
None of the ideas in functor are new, every idea here can be traced back to a particular source of inspiration
Games follow an Elm-style MVU loop: your model is an immutable value, and
input/tick/update are pure functions that return a new model (optionally
paired with an effect, whose result is folded back through update). draw
describes a frame — a camera plus a scene — from the model. A runner-hosted game
defines these top-level Functor Lang bindings:
let init = { … } // the initial model (a value)
let tick = (model, dt, tts) => model' // per-frame step
let draw = (model, tts) => Frame.create(camera, scene)
let input = (model, key, isDown) => model' // OPTIONAL; key: Key.t (Key.W, Key.Up, …)
let sampledInput = (model, snapshot: Input.snapshot) => model' // OPTIONAL levels + deterministic edges
let update = (model, msg) => model' // OPTIONAL; msgs are ADT variants
let subscriptions = (model) => Sub.every(Time.seconds(1.0), Beat) // OPTIONAL timers
let physics = (model) => Physics.scene(Vec3.make(0.0, -9.81, 0.0), [body, …]) // OPTIONAL
let soundScape = (model) => AudioScene.create([source, …]) // OPTIONAL looping audio
Because the model is a plain, cheap-to-clone value the host holds between frames,
the runtime can hot-reload your edits with the model preserved and record the
model every rendered frame — that's what powers the live editing and whole-game
time-travel scrubber you see at functor.games (design notes:
docs/time-travel.md).
The bundled sample games live in this repo, so clone it to run them. Some samples reference glTF model assets that aren't checked in (they download from BabylonJS Assets); fetch them first:
npm run fetch:assets
The CLI operates on a directory containing a functor.json
({"language": "functor-lang", "entry": "game.fun"}). Point it at the example with -d.
The run command interprets the game's .fun and launches it — no build step:
# Native — opens a window
functor -d examples/hello run native
# A primitives-only sample (no assets needed)
functor -d examples/primitives run native
# A 4×4 km, 16-bit heightmap terrain with LOD, collision, and instanced grass
functor -d examples/terrain run native
# The same scale at night: biome terrain, a camera-mounted flashlight, ~370 instanced props
functor -d examples/night-terrain run native
# A procedural synthwave city at night: thousands of instanced towers and neon signs
functor -d examples/neon-city run native
# Printable parts at true scale on your desk, in mixed reality (also runs on desktop)
functor -d examples/parts-mr run vr
# A grid shaded onto your real room's surfaces from the headset's depth (Quest 3)
functor -d examples/scene-grid run vr
# Bouncy balls off your real room, fused from the headset's depth as you look around (Quest 3)
functor -d examples/room-bounce run vr
# Web — serves the .fun + wasm bundle at http://127.0.0.1:8080
functor -d examples/primitives run wasm
native is the default environment, so ... run is equivalent to ... run native.
Games capture relative mouse input by default when they implement captured
mouse hooks. Set mouseCapture to false only when such a game should keep
the pointer free:
{
"language": "functor-lang",
"entry": "game.fun",
"mouseCapture": false
}
With capture enabled (the default), native offers click-to-capture and the web
player shows its mouse-capture button, routing captured motion/buttons to the
game’s mouseMove/mouseButton hooks. On native, a non-UI click enters
capture; Escape or focus loss releases it. Projects without captured mouse
hooks show no game-capture control.
Pointer-led 2D games use "cursor": "visible" instead to receive absolute
motion/buttons without capture; this also overrides the implicit capture
default.
Every project also has a shell-owned Debug camera in the timeline controls,
available while playing or paused. It snapshots the current authored view and
never changes the model, input log, replay, GET /scene, or the camera used by
game-driven culling and render-target/portal passes:
Activating it is an explicit capture click. Escape releases the pointer while
preserving the debug view; click the viewport to recapture. Exit debug view
returns to the latest game-authored camera. Resuming playback does not discard
the view, so the same alternate viewpoint can inspect a live or paused game.
This debug camera is runtime state, not a manifest setting, and is independent
of mouseCapture.
XR games can use the Quest-isomorphic desktop adapter with
... run native --emulate-xr; see the VR guide
for its mouse/keyboard controls and deterministic --input-script path.
(These commands assume functor is on your PATH; when running from a source build,
use ./target/release/functor instead — see DEVELOPMENT.md.)
| Command | Description |
|---|---|
functor -d <dir> init [3d|fps|multiplayer] | Scaffold a new Functor Lang project (3d is the default; multiplayer scaffolds client + server roles) |
functor -d <dir> build [native|wasm] | Typecheck the .fun project (diagnostics are errors) |
functor -d <dir> run [native|wasm] | Interpret and run the game (native window / browser) |
functor -d <dir> develop [native|wasm] | Same as run — Functor Lang hot-reload is built into the runtime — plus, on native, the debug runtime on localhost:8077 (--no-debug to skip it) |
functor docs [--format markdown|json] | Generate the API reference — the embedded engine prelude plus the language standard library |
For build-from-source instructions and what build/run do under the hood, see
DEVELOPMENT.md.
Is this actually a good idea or not?
I'm not sure yet. I'm interested to see what a full game looks like in this environment. There are several benefits to the constraints (ie, immutability + determinism = time-travel + extrapolation), but the ergonomics may still be challenging for writing a full game. Remains to be seen!
Makes me think of John Carmack's comments in this gamasutra article about functional programming:
If you are in circumstances where you can undertake significant development work in a non-mainstream language, I'll cheer you on, but be prepared to take some hits in the name of progress.
Xbot.glb (examples/hello, examples/animation, examples/crossfade, examples/crowd) is Adobe
Mixamo's "X Bot" character, distributed via BabylonJS Assets.examples/glove (vr_glove_model.glb) is from Valve's
SteamVR Unity Plugin
(© Valve Corporation, BSD-3-Clause — notice at examples/glove/LICENSE.steamvr),
converted to glTF with FBX2glTF.examples/*/*.wav) is procedurally synthesized — original/CC0, no
third-party samples. Regenerate with npm run generate:audio
(scripts/generate-audio.mjs).examples/asteroids uses Kenney assets (CC0): sounds from
the Sci-Fi Sounds pack and the ship
model (craft_racer) from the Space Kit
(fetched by npm run fetch:assets, not checked in). Thanks, Kenney! Details
per file in examples/asteroids/ASSETS.md.