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。 以下為已儲存的摘錄。
A very small, single-page poker-scoring roguelike: play poker hands for
chips × mult, clear an escalating chip target each round, and spend money on
a handful of simple jesters between rounds.檢視完整 README ↗A very small, single-page poker-scoring roguelike: play poker hands for chips × mult, clear an escalating chip target each act, and spend money on a handful of simple jesters between acts.
A dark baroque masquerade court: you are the fool, and your head is the ante. The venues climb from the Scullery to the Throne Room, and each act is an audience (Small, Grand, Royal Command), and poker hands keep their plain poker names. The mask cards are the Masquerade Ball, tarot-style cards are Decrees, and a portrait of the King reacts to how the act is going. Playing cards are drawn as aged ivory stock with serif indices and split court-card panels.
No build step, no dependencies — just index.html, styles.css, and the
plain scripts in src/. Open index.html directly, or serve the folder with anything
static (it's also set up for GitHub Pages).
prefers-reduced-motion.?debug runs save to their own slot, separate from normal play.?debug to the URL for a debug shop, a Win button that instantly clears the current act into the real shop, and a starting hand of jesters.assets/jesters/missing_no.png instead.Mid-act saves, a much larger jester roster, more consumable card types, alternate
decks, and difficulty tiers. This is the "real basic" version — small and
deliberately scoped, not a sprawling feature set. (Card art is a partial
exception: a lightweight, optional <img> hook and generated art for the
jesters landed early since it's additive and non-breaking — see
assets/jesters/PROMPTS.md; mask, decree, boss and King portrait prompts live in
assets/masks/, assets/decrees/, assets/bosses/ and assets/court/;
tools/imagegen/queue_cards.py queues them into ComfyUI and
tools/imagegen/export_cards.py copies finished renders into place at 150px.)
Dev tooling only — the game itself still has no build step and no runtime dependencies.
The game is a set of classic <script> files in src/, loaded in the order
index.html lists them and sharing one global scope (no modules, so opening
index.html from disk keeps working):
data.js, jesters.js, court.js — constants, mask/decree/prop pools, the
jester roster, boss modifiers, venues.state.js, scoring.js — the run's state, deck and act setup; hand
detection and scoring.actions.js, score-sequence.js, shop.js, consumables.js, run.js —
what the player can do: select/play/discard, the scoring animation,
shopping, using masks and decrees, new runs and saving.drag.js, cards-view.js, render.js, overlay.js — drag-to-reorder and
everything drawn on screen.main.js — wires up the page, plus the Node-only test hooks.sounds.js, backdrop.js — audio and the candlelit canvas backdrop.Because the scripts share globals, ESLint is given each file's neighbours'
top-level names (read from index.html, see eslint.config.js), and
test/globals.test.js flags top-level names nothing uses. Tests load the
scripts through tools/load-game.js.
Tests run on Node's built-in test runner, no install required:
node --test
Three layers, each testing what the one below it can't reach:
test/scoring.test.js — pure scoring-math regression tests (hand
detection, jester effects, target scaling).test/game-flow.test.js — game-flow/integration tests (play, discard,
shop, act/venue transitions, win/game-over) driven directly against the
state machine, no DOM.test/render.test.js — UI/wiring tests: real button clicks and keyboard
events against a real DOM (via jsdom, attached to Node's own global so
it's coverage-tracked, not window.eval'd in a separate context), for
the rendering and event-wiring code the other two layers can't exercise.Branch coverage is gated at 90% (npm run test:coverage, needs a one-time
npm install for jsdom):
npm install
npm run test:coverage
Linting also needs that same npm install (ESLint is a dev dependency only):
npm run lint