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