This project is 100% built by AI. Every line of code, every test, every config file, every batch script, and even this README — all written by AI agents (Claude, DeepSeek, Qwen). No human wrote a single line of code. Yes, it's a bit absurd. But it works.
An AI-native 2D game engine prototype. Core innovation: closed-loop AI game testing.
中文文档:README.zh-CN.md
Developer describes requirements in natural language -> AI writes scripts -> sandbox executes headlessly -> AI analyzes results -> AI iterates -> developer reviews deterministic replay.
Developer: "Make the player jump over the gap and land on the platform"
|
v
LLM Bridge (DeepSeek V3.2 / Qwen3-Max / Custom)
| Writes game.onTick() script
v
Docker Sandbox (headless, network=none, memory-limited)
| Runs 180 frames of physics simulation
v
AI Probe & Analysis
| Checks: did player reach target? How close? Trajectory events?
v
AI Iterates (up to 40 rounds)
| Adjusts jumpForce, timing, moveSpeed based on precision feedback
v
Deterministic Replay -> Developer watches result in browser
GameSenseSandbox/
src/
engine/ # Pure-logic state engine
| state.ts - GameState, Entity, Input type definitions
| tick.ts - Core tick loop (60 FPS fixed timestep)
| collision.ts - AABB collision detection & resolution
| scene.ts - Scene config -> initial state builder
| rng.ts - Deterministic PRNG (seedrandom)
|
sandbox/ # Script execution via Docker container
| index.ts - Sandbox.run() orchestrator
| docker.ts - Docker container lifecycle management
|
replay/ # State recording and replay
| recorder.ts - Frame-by-frame state recording
| player.ts - Replay playback controller
|
mcp/ # MCP (Model Context Protocol) server
| index.ts - MCP module entry
| server.ts - Tool registration (scene_load, sandbox_run, etc.)
| scene-manager.ts - Scene state management singleton
| probes.ts - Runtime probe queries
|
adapter/ # LLM bridge layer
| llm-bridge.ts - Core AI iteration loop with function calling
| models.ts - LLM provider configurations
| config.ts - Runtime config management
|
viewer/ # HTML5 Canvas frontend
| app.ts - Main application controller
| canvas.ts - Canvas renderer (replay + scene editor)
| index.html - Entry point
|
scenarios/ # Built-in test scenario definitions
index.ts - Scenario registry
docker/
runner/
runner.js - Headless physics engine (mirrors src/engine)
Dockerfile - Minimal Node.js sandbox image
tests/ # Vitest test suites (132 tests, 16 files)
server.mjs # Production static file server
vite.config.ts # Vite config with API plugin
- Deterministic physics: Fixed 60 FPS timestep, seeded PRNG, no
Math.random()orDate.now()in game logic. Same seed + same inputs = identical replay, always. - Docker isolation: AI-generated scripts run in a network-disabled, memory-limited, read-only Docker container. The host process is never at risk.
- Dual physics engine:
src/engine/collision.ts(TypeScript, for the viewer) anddocker/runner/runner.js(JavaScript, for headless sandbox) implement identical AABB collision & grounding logic. - Pure functions: Game state is immutable between ticks. Each
tick()produces a new state object. - AI iteration loop: The LLM bridge uses OpenAI-compatible function calling to orchestrate scene setup, script writing, sandbox execution, and result analysis in a closed loop.
- Coordinate system: Y-axis points UP (positive Y = higher). Origin at bottom-left.
- Gravity: Default 980 px/s^2 downward, applied as
vy -= gravity * dteach frame. - Collision: AABB overlap detection with edge-biased normal calculation. Vertical collisions set
isGrounded = truewhen entity lands on top of another. - Input handling:
applyInput()sets player velocity from keyboard/AI input. Jump only fires whenisGroundedis true. Double jump supported (edge-triggered, 85% force). - Tick order:
applyInput -> applyPendingCommands -> resetFrameState -> applyPhysics -> detectCollisions -> resolveCollisions -> detectTriggerOverlaps
- Play/Pause, step forward/backward, timeline scrubbing
- Speed control (0.25x - 4x)
- Replay archive (last 5 sessions)
- Import/Export replay JSON
- Export scene config from replay
- Unity-style editor with Edit/Play/Pause modes
- Create/move/resize entities (player, platform, obstacle, trigger)
- WASD/arrow keys control in play mode with real-time physics
- Mouse wheel zoom + middle-button pan
- Export/Import scene layout JSON
- Auto-stop when player falls below y=-1000
- Built-in challenge scenes bundled into the viewer
- Click to load into scene editor
- Includes narrow landing chains, vertical/horizontal mixed routes
- Natural language game scene testing via LLM
- Connects to DeepSeek V3.2 / Qwen3-Max / custom OpenAI-compatible endpoints
- AI writes sandbox scripts, runs, probes, and iterates automatically
- Up to 40 iterations with progressive stagnation escalation
- Precision trajectory feedback (takeoff/peak/landing events, closest-approach offset)
- AI obeys exact engine physics rules (gravity, jump limits, AABB)
- Console.log output from sandbox scripts displayed in chat
- Scene changes synced back to editor
| Provider | Model | API Endpoint |
|---|---|---|
| DeepSeek | deepseek-chat (V3.2) | api.deepseek.com |
| Qwen | qwen3-max | dashscope.aliyuncs.com |
| Custom | user-defined | user-defined |
Note: You can use any OpenAI-compatible service by setting custom
baseUrl+modelin the UI.
| Component | Technology | Version |
|---|---|---|
| Language | TypeScript (strict) | 5.5+ |
| Runtime | Node.js | >= 20 |
| Sandbox | Docker (network=none, read-only, memory limit) | - |
| Testing | Vitest | 2.0+ |
| Linting | Biome | 1.9+ |
| Bundler | Vite | 6.0+ |
| PRNG | seedrandom | 3.0+ |
| MCP SDK | @modelcontextprotocol/sdk | 1.27+ |
| Schema | Zod | 3.23+ |
- Node.js >= 20 (required)
- Docker (required for AI sandbox execution)
- An API key for at least one supported LLM provider (for AI chat feature)
Double-click start.bat. It will:
- Check Node.js and Docker availability
- Install npm dependencies
- Build TypeScript
- Generate a demo replay
- Build the viewer
- Start the server
npm install
npm start # Start Vite dev server at http://localhost:5173npm run build:viewer # Build viewer to dist/
node server.mjs # Serve from dist/Or on Windows, double-click build-release.bat to produce a release/ folder.
npm install
# Type check
npx tsc --noEmit
# Run all 132 tests
npx vitest run
# Run specific test suites
npx vitest run tests/engine/
npx vitest run tests/sandbox/
npx vitest run tests/integration/
# Lint
npx biome check src/
# Dev server with hot reload
npm run dev- ~10,000 lines of TypeScript/JavaScript
- 52 source files
- 132 tests across 16 test files
- 7 MCP tools
- 4 LLM provider integrations
-
Docker must be running for sandbox execution (AI chat / test scenarios that run scripts). The viewer's scene editor and replay features work without Docker.
-
API keys are entered in the browser UI and sent only to the configured LLM endpoint. Keys are cleared from the frontend when you click the exit button.
-
The physics engine runs at 60 FPS fixed timestep. All timing calculations assume
dt = 1/60. Gravity default is 980 px/s^2. -
Y-axis points UP. This is important for understanding position values: a player at y=200 is above a platform at y=100.
-
Deterministic replay: Given the same seed and inputs, the simulation produces identical results every time. This is guaranteed by using seeded PRNG and avoiding all non-deterministic APIs.
MIT
Built entirely by AI agents. The humans just provided the requirements and pressed Enter.