BeamNG.Earth
BeamNG.drive용 1:1 비율 실시간 지구, 실제 고도·위성 이미지·부동 원점·보조 서버에서 LOD 스트리밍
Functor Lang으로 순수 함수 게임을 작성, Rust 런타임이 네이티브·WebAssembly에서 실시간 실행, 상태 유지 핫리로드 지원
Write games as pure functions in Functor Lang — a tiny, interpreted, F#-inspired game language that the Rust runtime runs live on native + WebAssembly, with state-preserving hot-reload and no compile
게임Rust · JavaScriptGitHub @tommy-xr온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기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.