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 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Draw a stick figure on paper and take a photo of it. The drawing becomes your fighter on a canvas, and you control it live against a friend who is playing on their own device. Your fighter's power comes from what you drew: what it holds, how big it is, its pose and its colors. Every match result goes to a shared leaderboard.
Live: https://inkfight.vercel.app
Demo accounts (created by prisma/seed.ts, each with a starter fighter):
| Password | |
|---|---|
| [email protected] | inkfight123 |
| [email protected] | inkfight123 |
npm install
npx prisma dev -n inkfight-local --detach # local Postgres; put its TCP URL in .env (add &pgbouncer=true)
npx prisma migrate deploy && npm run seed
npm run dev # http://localhost:3001
.env needs DATABASE_URL, DATABASE_URL_UNPOOLED and AUTH_SECRET (see .env.example). Locally, uploads go to ./uploads. If BLOB_READ_WRITE_TOKEN is set, they go to Vercel Blob instead. For real drawing analysis, add ANTHROPIC_API_KEY. Without it, a deterministic offline generator creates the fighter.
The Vercel project inkfight has a Neon Postgres database (DATABASE_URL, DATABASE_URL_UNPOOLED) and a public Blob store (BLOB_READ_WRITE_TOKEN), plus AUTH_SECRET. npx vercel deploy --prod runs the vercel-build script: migrate, seed the demo accounts (idempotent), then build.
Vercel can't keep WebSockets open, so the server only handles matchmaking: the room creator's browser posts a WebRTC offer to /api/rooms/[code], the friend posts an answer, and from then on the two browsers talk directly over WebRTC data channels. The host's browser runs the authoritative 60 Hz simulation (src/game/sim.ts) and streams snapshots to the guest, exactly like a game server would. After the match it reports the result to /api/battles.
NEXT_PUBLIC_ICE_SERVERS (a JSON array of RTCIceServer) to cover those cases.| Keyboard | Phone | |
|---|---|---|
| Move | A / D (or ← →) | ◀ ▶ |
| Jump | W / ↑ / Space | ▲ |
| Attack | J | HIT |
| Block (hold) | K | 🛡 |
| Special (meter full) | L | ★ |
| Stat | In the game |
|---|---|
| HP | Health |
| ATK | Punch damage (4–10 per hit) |
| DEF | Less damage taken (up to −30%), and blocks absorb 55–90% |
| SPD | Run speed, jump height, attack rate |
| Class (from the held item) | Special move: Mage → magic bolt, Ranger → arrow, Caster → heavy orb, Warrior → dash slash, Tank → shield charge + armor, Brawler → launcher uppercut |
Hitting, getting hit and time all fill the special meter. Each fighter's page has a "How it fights" panel with the exact numbers.
| Piece | File |
|---|---|
| Authoritative 60 Hz fight simulation (pure TS) | src/game/sim.ts |
| P2P rooms: signaling, host loop, ready/rematch | src/game/useGameRoom.ts, src/app/api/rooms/** |
| Login (bcrypt + signed cookie) | src/lib/auth.ts, src/app/(auth)/** |
| Wire protocol | src/game/protocol.ts |
| Drawing → transparent sprite (removes the paper, crops to the ink) | src/game/sprite.ts |
| Canvas renderer (interpolation, squash/stretch, FX, HUD) | src/game/render.ts |
| Canvas + keyboard/touch controls | src/components/GameCanvas.tsx |
| Vision analysis + rule-based stats | src/lib/vision.ts, src/lib/stats.ts |
The host sends snapshots 30 times per second. The guest only sends inputs and draws what it receives, so both players always see the same fight. Jump, attack and special presses are sent as counters, so a quick tap between two packets is still registered.