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.